เมื่อเครื่องมือ HWASan ตรวจพบข้อบกพร่องเกี่ยวกับหน่วยความจำ ระบบจะหยุดกระบวนการด้วย abort() และพิมพ์รายงานไปยัง stderr และ logcat ข้อผิดพลาด HWASan จะอยู่ใน /data/tombstones เช่นเดียวกับข้อขัดข้องที่เกิดจากโค้ดเนทีฟทั้งหมดใน Android
รายงานตัวอย่าง
เมื่อเทียบกับข้อขัดข้องที่เกิดจากโค้ดเนทีฟทั่วไป HWASan จะมีข้อมูลเพิ่มเติมในช่องข้อความ Abort ใกล้ด้านบนของ Tombstone ตัวอย่างข้อขัดข้องที่เกิดจากฮีปมีดังนี้ สำหรับ ข้อบกพร่องของสแต็ก โปรดดูหมายเหตุสำหรับส่วนที่เฉพาะเจาะจงกับสแต็ก
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 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 …]
รายงานนี้คล้ายกับรายงาน AddressSanitizer แต่ข้อบกพร่อง HWASan เกือบทั้งหมดเป็นข้อผิดพลาดการกำหนดแท็กไม่ตรงกัน ซึ่งหมายถึงการเข้าถึงหน่วยความจำที่แท็กตัวชี้ไม่ตรงกับแท็กหน่วยความจำที่เกี่ยวข้อง ซึ่งอาจเป็นกรณีใดกรณีหนึ่งต่อไปนี้
- การเข้าถึงนอกขอบเขตในสแต็กหรือฮีป
- ข้อผิดพลาด Use-after-free ในฮีป
- ข้อผิดพลาด Use-after-return ในสแต็ก
ส่วน
คำอธิบายของแต่ละส่วนในรายงาน HWASan มีดังนี้
ข้อผิดพลาดในการเข้าถึง
มีข้อมูลเกี่ยวกับการเข้าถึงหน่วยความจำที่ไม่ถูกต้อง ซึ่งรวมถึงข้อมูลต่อไปนี้
- ประเภทการเข้าถึง (
READเทียบกับWRITE) - ขนาดการเข้าถึง (จำนวนไบต์ที่พยายามเข้าถึง)
- หมายเลขเธรดของการเข้าถึง
- แท็กตัวชี้และแท็กหน่วยความจำ (สำหรับการแก้ไขข้อบกพร่องขั้นสูง)
สแต็กเทรซของการเข้าถึง
สแต็กเทรซของการเข้าถึงหน่วยความจำที่ไม่ถูกต้อง ดูการสร้างสัญลักษณ์เพื่อ สร้างสัญลักษณ์
สาเหตุ
สาเหตุที่เป็นไปได้ของการเข้าถึงที่ไม่ถูกต้อง หากมีสาเหตุที่เป็นไปได้หลายรายการ ระบบจะแสดงรายการตามลำดับความน่าจะเป็นจากมากไปน้อย โดยจะอยู่ก่อนข้อมูลโดยละเอียดเกี่ยวกับสาเหตุที่เป็นไปได้ HWASan สามารถวินิจฉัยสาเหตุต่อไปนี้ได้
- Use-after-free
- การกำหนดแท็กสแต็กไม่ตรงกัน ซึ่งอาจเป็นการใช้สแต็กหลังจากกลับมา การใช้สแต็กหลังจากขอบเขต หรือการใช้สแต็กนอกขอบเขต
- บัฟเฟอร์ฮีปล้น
- การล้นทั่วโลก
ข้อมูลหน่วยความจำ
อธิบายสิ่งที่ HWASan ทราบเกี่ยวกับหน่วยความจำที่เข้าถึง และอาจแตกต่างกันไปตามประเภทข้อบกพร่อง
| ประเภทข้อบกพร่อง | สาเหตุ | รูปแบบรายงาน |
|---|---|---|
| การกำหนดแท็กไม่ตรงกัน | Use-after-free | ใช้รูปแบบรายงานต่อไปนี้<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| บัฟเฟอร์ฮีปล้น | โปรดทราบว่าอาจเป็นการล้นต่ำด้วย<address> is located N bytes to the right of M-byte region [<start>, <end>) allocated here: |
|
| การกำหนดแท็กสแต็กไม่ตรงกัน | รายงานสแต็กจะไม่แยกความแตกต่างระหว่างข้อบกพร่องการล้นหรือการล้นต่ำกับข้อบกพร่อง Use-after-return นอกจากนี้ คุณต้องสร้างสัญลักษณ์แบบออฟไลน์เพื่อค้นหาการจัดสรรสแต็กที่เป็นแหล่งที่มาของข้อผิดพลาด ดูทำความเข้าใจรายงานสแต็ก รายงาน | |
| การคืนหน่วยความจำไม่ถูกต้อง | Use-after-free | ข้อบกพร่องการคืนหน่วยความจำซ้ำ หากเกิดเหตุการณ์นี้เมื่อปิดกระบวนการ อาจหมายถึงการละเมิดกฎการกำหนดครั้งเดียว
<address> is located N bytes inside of M-byte region [<start>, <end>) freed by thread T0 here: |
| อธิบายที่อยู่ไม่ได้ | อาจเป็นการคืนหน่วยความจำแบบสุ่ม (การคืนหน่วยความจำที่ไม่ได้จัดสรรไว้ก่อนหน้านี้) หรือการคืนหน่วยความจำซ้ำหลังจากนำหน่วยความจำที่จัดสรรไว้ออกจากบัฟเฟอร์ว่างของ HWASan | |
| 0x... คือหน่วยความจำ Shadow ของ HWASan | เป็นการคืนหน่วยความจำแบบสุ่ม เนื่องจากแอปพยายามคืนหน่วยความจำภายในของ HWASan |
สแต็กเทรซของการคืนหน่วยความจำ
สแต็กเทรซของตำแหน่งที่คืนหน่วยความจำ จะปรากฏเฉพาะในกรณีที่เกิดข้อบกพร่อง Use-after-free หรือ Invalid-free ดูการสร้างสัญลักษณ์เพื่อสร้างสัญลักษณ์
สแต็กเทรซของการจัดสรร
สแต็กเทรซของตำแหน่งที่จัดสรรหน่วยความจำ ดูการสร้างสัญลักษณ์เพื่อสร้างสัญลักษณ์
ข้อมูลการแก้ไขข้อบกพร่องขั้นสูง
รายงาน HWASan ยังมีข้อมูลการแก้ไขข้อบกพร่องขั้นสูงบางอย่าง ซึ่งรวมถึงข้อมูลต่อไปนี้ (ตามลำดับ)
- รายการเธรดในกระบวนการ
- รายการเธรดในกระบวนการ
- ค่าของแท็กหน่วยความจำใกล้กับหน่วยความจำที่เกิดข้อผิดพลาด
- การดัมป์รีจิสเตอร์ ณ จุดที่มีการเข้าถึงหน่วยความจำ
การดัมป์แท็กหน่วยความจำ
คุณสามารถใช้การดัมป์หน่วยความจำแท็กเพื่อค้นหาการจัดสรรหน่วยความจำที่อยู่ใกล้เคียงซึ่งมีแท็กเดียวกับแท็กตัวชี้ แท็กเหล่านี้อาจชี้ไปยังการเข้าถึงนอกขอบเขตที่มีออฟเซ็ตขนาดใหญ่ แท็ก 1 รายการสอดคล้องกับหน่วยความจำ 16 ไบต์ โดยแท็กตัวชี้คือ 8 บิตบนสุดของที่อยู่ การดัมป์หน่วยความจำแท็กอาจให้คำแนะนำได้ เช่น ตัวอย่างต่อไปนี้เป็นการล้นบัฟเฟอร์ไปทางขวา
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 .. .. .. .. .. .. .. .. .. .. .. .. .. ..
โปรดสังเกตแท็ก ad ที่ต่อเนื่องกัน 6 × 16 = 96 ไบต์ทางด้านซ้ายซึ่งตรงกับแท็กตัวชี้
หากขนาดของการจัดสรรไม่ใช่จำนวนเท่าของ 16 ระบบจะจัดเก็บส่วนที่เหลือของขนาดเป็น
แท็กหน่วยความจำ และจัดเก็บแท็กเป็น แท็กแกรนูล
ขนาดเล็ก ในตัวอย่างก่อนหน้า หลังจากแท็ก ad ที่จัดสรรไว้ซึ่งแสดงเป็นตัวหนา เรามีการจัดสรรแท็ก 5c ขนาด 5 × 16 + 4 = 84 ไบต์
แท็กหน่วยความจำเป็น 0 (เช่น tags: ad/00 (ptr/mem)) บ่งบอกถึงข้อบกพร่อง
Stack-use-after-return
การดัมป์รีจิสเตอร์
การดัมป์รีจิสเตอร์ในรายงาน HWASan สอดคล้องกับคำสั่งที่ทำการเข้าถึงหน่วยความจำที่ไม่ถูกต้อง การดัมป์นี้จะตามด้วยการดัมป์รีจิสเตอร์อีกรายการจากตัวจัดการสัญญาณ Android ปกติ โปรดละเว้นการดัมป์รายการที่ 2 เนื่องจากระบบดำเนินการเมื่อ HWASan เรียก
abort() และไม่เกี่ยวข้องกับข้อบกพร่อง
การสร้างสัญลักษณ์
หากต้องการรับชื่อฟังก์ชันและหมายเลขบรรทัดในสแต็กเทรซ (และรับชื่อตัวแปรสำหรับข้อบกพร่อง Use-after-scope) คุณต้องสร้างสัญลักษณ์แบบออฟไลน์
การตั้งค่าครั้งแรก: ติดตั้ง llvm-symbolizer
หากต้องการสร้างสัญลักษณ์ ระบบของคุณต้องติดตั้ง llvm-symbolizer และเข้าถึงได้จาก $PATH ใน Debian คุณสามารถติดตั้งได้โดยใช้ sudo apt install llvm
รับไฟล์สัญลักษณ์
สำหรับการสร้างสัญลักษณ์ เราต้องใช้ไบนารีที่ไม่ได้ลบสัญลักษณ์ออกซึ่งมีสัญลักษณ์ ตำแหน่งของไฟล์จะขึ้นอยู่กับประเภทบิลด์
- สำหรับการสร้างแบบโลคัล ไฟล์สัญลักษณ์จะอยู่ใน
out/target/product/<product>/symbols/ - สำหรับการสร้าง AOSP (เช่น แฟลชจาก
Android Flash Tool) การ
สร้างจะอยู่ใน Android CI ในอาร์ติแฟกต์ สำหรับการสร้างจะมีไฟล์
${PRODUCT}-symbols-${BUILDID}.zip - สำหรับการสร้างภายใน จากองค์กรของคุณ โปรดดูเอกสารประกอบขององค์กรเพื่อขอความช่วยเหลือในการรับไฟล์สัญลักษณ์
สร้างสัญลักษณ์
hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash
ทำความเข้าใจรายงานสแต็ก
สำหรับข้อบกพร่องที่เกิดขึ้นกับตัวแปรสแต็ก รายงาน HWASan จะมีรายละเอียดดังนี้
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) [...]
HWASan จะติดตามเฟรมสแต็กที่ผ่านมาเพื่อช่วยให้คุณเข้าใจข้อบกพร่องของสแต็ก HWASan จะไม่แปลงเฟรมเหล่านี้เป็นเนื้อหาที่มนุษย์เข้าใจได้ในรายงานข้อบกพร่อง และ ต้องมีขั้นตอนการสร้างสัญลักษณ์เพิ่มเติม
การละเมิดกฎการกำหนดครั้งเดียว
ข้อบกพร่อง Use-after-free บางรายการที่ HWASan รายงานอาจบ่งบอกถึงการละเมิดกฎการกำหนดครั้งเดียว (One Definition Rule หรือ ODR) การละเมิด ODR เกิดขึ้นเมื่อมีการกำหนดตัวแปรเดียวกันหลายครั้งในโปรแกรมเดียวกัน ซึ่งหมายความว่าตัวแปรจะถูกทำลายหลายครั้ง ซึ่งอาจทำให้เกิดข้อผิดพลาด Use-after-free
หลังจากการสร้างสัญลักษณ์ การละเมิด ODR จะแสดงข้อผิดพลาด Use-after-free ที่มี __cxa_finalize ทั้งในสแต็กการเข้าถึงที่ไม่ถูกต้องและสแต็กคืนหน่วยความจำที่นี่ สแต็กจัดสรรไว้ก่อนหน้านี้ที่นี่ มี __dl__ZN6soinfo17call_constructorsEv และควรชี้ไปยังตำแหน่งในโปรแกรมที่กำหนดตัวแปรไว้สูงกว่าในสแต็ก
การละเมิด ODR อาจเกิดขึ้นได้หากมีการใช้ไลบรารีแบบคงที่ หากมีการลิงก์ไลบรารีแบบคงที่ที่กำหนดตัวแปรส่วนกลาง C++ ไปยังไลบรารีที่แชร์หรือไฟล์ปฏิบัติการหลายรายการ อาจมีการกำหนดสัญลักษณ์เดียวกันหลายรายการในพื้นที่ที่อยู่เดียวกัน ซึ่งทำให้เกิดข้อผิดพลาด ODR
การแก้ปัญหา
ส่วนนี้อธิบายข้อผิดพลาดบางอย่างและวิธีแก้ไข
HWAddressSanitizer อธิบายแอดเดรสโดยละเอียดเพิ่มเติมไม่ได้
บางครั้ง HWASan อาจมีพื้นที่ไม่เพียงพอสำหรับข้อมูลเกี่ยวกับการจัดสรรหน่วยความจำที่ผ่านมา ในกรณีดังกล่าว รายงานจะมีสแต็กเทรซเพียงรายการเดียวสำหรับการเข้าถึงหน่วยความจำโดยตรง ตามด้วยหมายเหตุ
HWAddressSanitizer can not describe address in more detail.
ในบางกรณี คุณสามารถแก้ไขปัญหานี้ได้โดยเรียกใช้การทดสอบหลายครั้ง อีกตัวเลือกหนึ่งคือการเพิ่มขนาดประวัติ HWASan คุณสามารถทำได้ทั่วโลกใน build/soong/cc/sanitize.go (มองหา hwasanGlobalOptions) หรือในสภาพแวดล้อมของกระบวนการ (ลองใช้ adb shell echo $HWASAN_OPTIONS เพื่อดูการตั้งค่าปัจจุบัน)
ข้อผิดพลาดนี้อาจเกิดขึ้นได้เช่นกันหากหน่วยความจำที่เข้าถึงไม่ได้แมปหรือจัดสรรโดยตัวจัดสรรที่ไม่รู้จัก HWASan ในกรณีนี้ แท็ก mem ที่แสดงในส่วนหัวของข้อขัดข้องโดยทั่วไปจะเป็น 00 หากคุณมีสิทธิ์เข้าถึง Tombstone แบบเต็ม การดูการดัมป์แผนที่หน่วยความจำอาจช่วยให้ทราบว่าที่อยู่เป็นของการแมปใด (หากมี)
ข้อบกพร่องที่ซ้อนกันในเธรดเดียวกัน
หมายความว่าเกิดข้อบกพร่องขณะสร้างรายงานข้อขัดข้อง HWASan ซึ่งมักเกิดจากข้อบกพร่องในรันไทม์ HWASan โปรดรายงานข้อบกพร่องและระบุวิธีการจำลองปัญหา (หากเป็นไปได้)