Khi công cụ HWASan phát hiện thấy lỗi bộ nhớ, quy trình sẽ bị chấm dứt bằng abort() và một báo cáo sẽ được in ra stderr và logcat. Giống như mọi sự cố gốc trên Android, các lỗi HWASan đều nằm trong /data/tombstones.
Báo cáo mẫu
So với các sự cố gốc thông thường, HWASan mang theo thông tin bổ sung trong trường Thông báo huỷ ở gần đầu tệp tombstone. Sau đây là một ví dụ về sự cố dựa trên heap. Đối với các lỗi ngăn xếp, hãy xem lưu ý cho các phần dành riêng cho ngăn xếp.
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys' Revision: 'DVT1.0' ABI: 'arm64' Timestamp: 2019-04-24 01:13:22+0000 pid: 11154, tid: 11154, name: sensors@1.0-ser >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<< signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr -------- Abort message: '==9569==ERROR: HWAddressSanitizer: tag-mismatch on address 0x00433ae20045 at pc 0x00623ae2a9cc READ of size 1 at 0x00433ae20045 tags: 5b/83 (ptr/mem) in thread T0 #0 0x7240450c68 (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) #1 0x723dffd490 (/vendor/lib64/sensors.ssc.so+0x34490) #2 0x723e0126e0 (/vendor/lib64/sensors.ssc.so+0x496e0) [...] [0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5 Cause: use-after-free 0x00433ae20045 is located 5 bytes inside of 10-byte region [0x00433ae20040,0x00433ae2004a) freed by thread T0 here: #0 0x72404d1b18 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x10b18) #1 0x723af23040 (/vendor/lib64/libgralloccore.so+0x5040) #2 0x723af23fa4 (/vendor/lib64/libgralloccore.so+0x5fa4) [...] previously allocated here: #0 0x72404ce554 (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0xd554) #1 0x7240115654 (/apex/com.android.runtime/lib64/bionic/libc.so+0x43654) #2 0x7240450ac8 (/system/lib64/vndk-sp-R/libcutils.so+0x8ac8) [...] hwasan_dev_note_heap_rb_distance: 1 1023 hwasan_dev_note_num_matching_addrs: 0 hwasan_dev_note_num_matching_addrs_4b: 0 Thread: T0 0x006a00002000 stack: [0x007fc1064000,0x007fc1864000) sz: 8388608 tls: [0x00737702ffc0,0x007377033000) Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae1ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x006f33ae2000: 08 00 08 00 [83] 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x006f33ae2080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: 72 .. d0 .. [..] .. .. .. .. .. .. .. .. .. .. .. 0x006f33ae2010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags Registers where the failure occurred (pc 0x00623ae2a9cc): x0 0000007fc18623ec x1 5b0000433ae20045 x2 0000000000000013 x3 ffffffffffffffff x4 ffffffffffffffff x5 0000007fc1861da3 x6 6f7420676e696f47 x7 45522061206f6420 x8 0000000000000000 x9 0200006b00000000 x10 00000007fc18623f x11 5b0000433ae20040 x12 6f64206f7420676e x13 0a44414552206120 x14 0000000000000010 x15 ffffffffffffffff x16 000000737169ac94 x17 0000000000000007 x18 0000007377bd8000 x19 0000007fc1862498 x20 0200006b00000000 x21 0000007fc18624a8 x22 0000000000000001 x23 0000000000000000 x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000 x28 0000000000000000 x29 0000007fc1862410 x30 000000623ae2a9d0 sp 0000007fc18623d0 SUMMARY: HWAddressSanitizer: tag-mismatch (/system/lib64/vndk-sp-R/libcutils.so+0x8c68) [ … regular crash dump follows …]
Điều này tương tự như báo cáo AddressSanitizer. Không giống như những lỗi đó, hầu hết các lỗi HWASan đều là lỗi không khớp thẻ, tức là một hoạt động truy cập bộ nhớ trong đó thẻ con trỏ không khớp với thẻ bộ nhớ tương ứng. Đây có thể là bất kỳ thông tin nào sau đây:
- Truy cập ngoài phạm vi trên ngăn xếp hoặc vùng nhớ
- Lỗi use-after-free trên bộ nhớ khối xếp
- Lỗi sử dụng sau khi trả về trên ngăn xếp
Phần
Sau đây là nội dung giải thích về từng phần trong báo cáo HWASan.
Lỗi truy cập
Chứa thông tin về hoạt động truy cập bộ nhớ không hợp lệ, bao gồm:
- Loại quyền truy cập (
READso vớiWRITE) - Kích thước truy cập (số byte đã được cố gắng truy cập)
- Số luồng truy cập
- Con trỏ và thẻ bộ nhớ (để gỡ lỗi nâng cao)
Truy cập vào dấu vết ngăn xếp
Dấu vết ngăn xếp của hoạt động truy cập bộ nhớ không hợp lệ. Xem phần Ký hiệu hoá để ký hiệu hoá.
Nguyên nhân
Nguyên nhân có thể dẫn đến lỗi truy cập. Nếu có nhiều đề xuất, các đề xuất đó sẽ được liệt kê theo thứ tự giảm dần về mức độ phù hợp. Đứng trước thông tin chi tiết về nguyên nhân tiềm ẩn. HWASan có thể chẩn đoán các nguyên nhân sau:
- Sử dụng sau khi giải phóng
- Không khớp thẻ ngăn xếp, có thể là sử dụng ngăn xếp sau khi trả về, sử dụng ngăn xếp sau phạm vi hoặc ngoài giới hạn
- Vùng đệm của vùng nhớ khối xếp bị tràn
- Bong bóng bổ sung toàn cầu
Thông tin về bộ nhớ
Mô tả những gì HWASan biết về bộ nhớ đang được truy cập và có thể khác nhau tuỳ thuộc vào loại lỗi:
| Loại lỗi | Nguyên nhân | Định dạng báo cáo |
|---|---|---|
| Thẻ không khớp | Sử dụng sau khi giải phóng | Sử dụng định dạng báo cáo này:<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| Vùng đệm của vùng nhớ khối xếp bị tràn | Xin lưu ý rằng đây cũng có thể là một trường hợp tràn số âm.<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: |
|
| Thẻ ngăn xếp không khớp | Báo cáo ngăn xếp không phân biệt giữa lỗi tràn hoặc lỗi trống và lỗi sử dụng sau khi trả về. Ngoài ra, để tìm được vị trí phân bổ ngăn xếp là nguồn gốc của lỗi, bạn cần thực hiện một bước biểu tượng hoá ngoại tuyến. Xem phần Tìm hiểu báo cáo ngăn xếp. | |
| Không hợp lệ | Sử dụng sau khi giải phóng | Lỗi giải phóng gấp đôi. Nếu điều này xảy ra khi quá trình tắt, thì điều này có thể biểu thị hành vi vi phạm ODR.
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| Không thể mô tả địa chỉ | Có thể là một vùng nhớ trống (vùng nhớ chưa được phân bổ trước đó) hoặc một vùng nhớ trống kép sau khi vùng nhớ được phân bổ bị loại bỏ khỏi vùng đệm trống của HWASan. | |
| 0x... là bộ nhớ bóng HWAsan | Một giải phóng tuỳ ý, vì ứng dụng đang cố gắng giải phóng bộ nhớ bên trong HWASan. |
Dấu vết ngăn xếp huỷ phân bổ
Dấu vết ngăn xếp của nơi bộ nhớ được giải phóng. Chỉ xuất hiện khi có lỗi sử dụng sau khi giải phóng hoặc giải phóng không hợp lệ. Xem phần Ký hiệu hoá để ký hiệu hoá.
Dấu vết ngăn xếp phân bổ
Dấu vết ngăn xếp của vị trí bộ nhớ được phân bổ. Xem phần Ký hiệu hoá để ký hiệu hoá.
Thông tin gỡ lỗi nâng cao
Báo cáo HWASan cũng có một số thông tin gỡ lỗi nâng cao, bao gồm (theo thứ tự):
- Danh sách các luồng trong quy trình
- Danh sách các luồng trong quy trình
- Giá trị của các thẻ bộ nhớ gần bộ nhớ bị lỗi
- Kết xuất các thanh ghi tại thời điểm truy cập bộ nhớ
Tệp kết xuất thẻ nhớ
Bạn có thể sử dụng trích xuất dữ liệu bộ nhớ thẻ để tìm các hoạt động phân bổ bộ nhớ lân cận có cùng thẻ với thẻ con trỏ. Các thẻ này có thể chỉ đến một lượt truy cập ngoài phạm vi với độ lệch lớn. Một thẻ tương ứng với 16 byte bộ nhớ; thẻ con trỏ là 8 bit hàng đầu của địa chỉ. Dữ liệu kết xuất bộ nhớ thẻ có thể đưa ra gợi ý, ví dụ: sau đây là một lỗi tràn bộ nhớ đệm ở bên phải:
tags: ad/5c (ptr/mem) [...] Memory tags around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: 0e 0e 0e 57 20 20 20 20 20 2e 5e 5e 5e 5e 5e b5 =>0x006f33ae2000: f6 f6 f6 f6 f6 4c ad ad ad ad ad ad [5c] 5c 5c 5c 0x006f33ae2010: 5c 04 2e 2e 2e 2e 2e 2f 66 66 66 66 66 80 6a 6a Tags for short granules around the buggy address (one tag corresponds to 16 bytes): 0x006f33ae1ff0: ab 52 eb .. .. .. .. .. .. .. .. .. .. .. .. .. =>0x006f33ae2000: .. .. .. .. .. .. .. .. .. .. .. .. [..] .. .. .. 0x006f33ae2010: .. 5c .. .. .. .. .. .. .. .. .. .. .. .. .. ..
Lưu ý rằng có 6 × 16 = 96 byte của thẻ ad ở bên trái khớp với thẻ con trỏ.
Nếu kích thước của một hoạt động phân bổ không phải là bội số của 16, thì phần còn lại của kích thước sẽ được lưu trữ dưới dạng thẻ nhớ và thẻ này được lưu trữ dưới dạng thẻ hạt ngắn. Trong ví dụ trước, ngay sau thẻ phân bổ được đánh dấu in đậm ad, chúng ta có một thẻ phân bổ 5 × 16 + 4 = 84 byte 5c.
Thẻ bộ nhớ bằng 0 (ví dụ: tags: ad/00 (ptr/mem)) cho biết lỗi stack-use-after-return.
Tệp kết xuất thanh ghi
Dữ liệu kết xuất thanh ghi trong báo cáo HWASan tương ứng với chỉ dẫn đã thực hiện thao tác truy cập bộ nhớ không hợp lệ. Sau tệp kết xuất này là một tệp kết xuất thanh ghi khác từ trình xử lý tín hiệu Android thông thường. Bỏ qua tệp kết xuất thứ hai vì tệp này được lấy khi HWASan gọi abort() và không liên quan đến lỗi.
Biểu tượng hoá
Để lấy tên hàm và số dòng trong dấu vết ngăn xếp (và lấy tên biến cho lỗi sử dụng sau phạm vi), bạn cần thực hiện bước tượng trưng hoá ngoại tuyến.
Thiết lập lần đầu: cài đặt llvm-symbolizer
Để biểu thị bằng ký hiệu, hệ thống của bạn phải cài đặt llvm-symbolizer và có thể truy cập từ $PATH. Trên Debian, bạn có thể cài đặt bằng cách sử dụng sudo apt install llvm.
Lấy tệp biểu tượng
Để biểu thị, chúng tôi yêu cầu các tệp nhị phân chưa được rút gọn chứa các biểu tượng. Vị trí của các tệp này phụ thuộc vào loại bản dựng:
- Đối với các bản dựng cục bộ, các tệp biểu tượng nằm trong
out/target/product/<product>/symbols/. - Đối với các bản dựng AOSP (ví dụ: được cài đặt ROM bằng Android Flash Tool), các bản dựng này nằm trên Android CI. Trong Artifacts (Cấu phần phần mềm) cho bản dựng, có một tệp
${PRODUCT}-symbols-${BUILDID}.zip. - Đối với bản dựng nội bộ của tổ chức, hãy xem tài liệu của tổ chức để biết cách lấy tệp biểu tượng.
Tượng trưng hoá
hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash
Tìm hiểu báo cáo ngăn xếp
Đối với các lỗi xảy ra với các biến ngăn xếp, báo cáo HWASan sẽ chứa những thông tin chi tiết như sau:
Cause: stack tag-mismatch Address 0x007d4d251e80 is located in stack of thread T64 Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000) Previously allocated frames: record_addr:0x7df7300c98 record:0x51ef007df3f70fb0 (/apex/com.android.art/lib64/libart.so+0x570fb0) record_addr:0x7df7300c90 record:0x5200007df3cdab74 (/apex/com.android.art/lib64/libart.so+0x2dab74) [...]
Để giúp bạn hiểu rõ các lỗi ngăn xếp, HWASan sẽ theo dõi các khung ngăn xếp trước đây. HWASan không chuyển đổi những nội dung này thành nội dung mà con người có thể hiểu được trong báo cáo lỗi và yêu cầu thêm bước biểu tượng hoá.
Vi phạm ODR
Một số lỗi sử dụng sau khi giải phóng do HWASan báo cáo có thể cho biết lỗi vi phạm Quy tắc một định nghĩa (ODR). Lỗi vi phạm ODR xảy ra khi cùng một biến được xác định nhiều lần trong cùng một chương trình. Điều này cũng có nghĩa là biến bị huỷ nhiều lần, có thể dẫn đến lỗi sử dụng sau khi giải phóng.
Sau khi biểu thị, lỗi vi phạm ODR sẽ cho thấy lỗi sử dụng sau khi giải phóng bằng __cxa_finalize, trên cả ngăn xếp truy cập không hợp lệ và ngăn xếp đã giải phóng tại đây. Ngăn xếp được phân bổ trước đó tại đây chứa __dl__ZN6soinfo17call_constructorsEv và phải trỏ đến vị trí trong chương trình xác định biến cao hơn trên ngăn xếp.
ODR có thể bị vi phạm nếu bạn sử dụng thư viện tĩnh. Nếu một thư viện tĩnh xác định một biến toàn cục C++ được liên kết với nhiều thư viện dùng chung hoặc tệp thực thi, thì có thể có nhiều định nghĩa của cùng một biểu tượng trong cùng một không gian địa chỉ, gây ra lỗi ODR.
Khắc phục sự cố
Phần này mô tả một số lỗi và cách giải quyết các lỗi đó.
HWAddressSanitizer không thể mô tả địa chỉ chi tiết hơn
Đôi khi, HWASan có thể hết dung lượng để lưu trữ thông tin về các lần phân bổ bộ nhớ trước đây. Trong trường hợp đó, báo cáo chỉ chứa một dấu vết ngăn xếp cho hoạt động truy cập bộ nhớ tức thì, theo sau là một ghi chú:
HWAddressSanitizer can not describe address in more detail.
Trong một số trường hợp, bạn có thể giải quyết vấn đề này bằng cách chạy thử nghiệm nhiều lần. Một lựa chọn khác là tăng kích thước nhật ký HWASan. Bạn có thể thực hiện việc này trên toàn cầu trong build/soong/cc/sanitize.go (tìm hwasanGlobalOptions) hoặc trong môi trường xử lý (hãy thử adb shell echo $HWASAN_OPTIONS để xem các chế độ cài đặt hiện tại).
Lỗi này cũng có thể xảy ra nếu bộ nhớ được truy cập không được ánh xạ hoặc được phân bổ bởi một trình phân bổ không nhận biết HWASan. Trong trường hợp này, thẻ mem có trong tiêu đề sự cố thường là 00. Nếu có quyền truy cập vào toàn bộ thông tin về tệp, bạn nên tham khảo tệp kết xuất bản đồ bộ nhớ để tìm hiểu xem địa chỉ thuộc về bản đồ nào (nếu có).
Lỗi lồng nhau trong cùng một luồng
Điều này có nghĩa là đã xảy ra lỗi khi tạo báo cáo sự cố HWASan. Điều này thường là do lỗi trong thời gian chạy HWASan. Báo cáo lỗi và cung cấp hướng dẫn về cách tái hiện vấn đề (nếu có thể).