ทำความเข้าใจรายงานของ HWASan

เมื่อเครื่องมือ HWASan ตรวจพบจุดบกพร่องของหน่วยความจำ กระบวนการจะถูกยกเลิกด้วย abort() และรายงานจะถูกพิมพ์ไปยัง stderr และ logcat เช่นเดียวกับการแครชดั้งเดิมทั้งหมดบน Android ข้อผิดพลาด HWASan สามารถพบได้ภายใต้ /data/tombstones

เมื่อเปรียบเทียบกับการแครชแบบปกติ HWASan จะมีข้อมูลเพิ่มเติมในช่อง "ยกเลิกข้อความ" ใกล้กับด้านบนสุดของศิลาหน้าหลุมฝังศพ ดูตัวอย่างการหยุดทำงานตามฮีปด้านล่าง (สำหรับข้อบกพร่องของสแต็ก โปรดดู หมายเหตุด้านล่าง สำหรับส่วนเฉพาะของสแต็ก)

ตัวอย่างรายงาน

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

สิ่งนี้คล้ายกับรายงาน AddressSanitizer มาก ข้อบกพร่องของ HWASan เกือบทั้งหมดนั้น “แท็กไม่ตรงกัน” กล่าวคือ การเข้าถึงหน่วยความจำโดยที่แท็กพอยน์เตอร์ไม่ตรงกับแท็กหน่วยความจำที่เกี่ยวข้อง นี่อาจเป็นหนึ่งใน

  • การเข้าถึงนอกขอบเขตบนสแต็กหรือฮีป
  • ใช้หลังจากกองฟรี
  • ใช้หลังจากกลับมากอง

ส่วน

คำอธิบายของแต่ละส่วนของรายงาน HWASan อยู่ด้านล่าง:

ข้อผิดพลาดในการเข้าถึง

มีข้อมูลเกี่ยวกับการเข้าถึงหน่วยความจำที่ไม่ดี รวมถึง:

  • ประเภทการเข้าถึง ("อ่าน" กับ "เขียน")
  • ขนาดการเข้าถึง (จำนวนไบต์ที่พยายามเข้าถึง)
  • หมายเลขเธรดของการเข้าถึง
  • ตัวชี้และแท็กหน่วยความจำ (สำหรับการดีบักขั้นสูง)

เข้าถึงการติดตามสแต็ก

ติดตามสแต็กของการเข้าถึงหน่วยความจำที่ไม่ดี ดู ส่วนสัญลักษณ์ เพื่อเป็นสัญลักษณ์

สาเหตุ

สาเหตุที่เป็นไปได้สำหรับการเข้าถึงที่ไม่ดี หากมีผู้สมัครหลายคน จะเรียงตามลำดับความน่าจะเป็น นำหน้าข้อมูลรายละเอียดเกี่ยวกับสาเหตุที่เป็นไปได้ HWASan สามารถวินิจฉัยสาเหตุต่อไปนี้:

  • ใช้หลังจากฟรี
  • stack tag-mismatch: นี่อาจเป็น stack use-after-return / use after-scope หรือ out of bounds
  • กองบัฟเฟอร์ล้น
  • ล้นโลก

ข้อมูลหน่วยความจำ

อธิบายสิ่งที่ HWASan รู้เกี่ยวกับหน่วยความจำที่กำลังเข้าถึง และอาจแตกต่างกันไปตามประเภทข้อบกพร่อง

ประเภทข้อผิดพลาด สาเหตุ รูปแบบรายงาน
แท็กไม่ตรงกัน ใช้หลังจากฟรี
<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:
แท็กสแต็คไม่ตรงกัน รายงานสแต็กไม่ได้แยกความแตกต่างระหว่างบั๊กที่มากเกินไป/อันเดอร์โฟลว์และการใช้หลังการส่งคืน นอกจากนี้ หากต้องการค้นหาการจัดสรรสแต็กที่เป็นสาเหตุของข้อผิดพลาด จำเป็นต้องมีขั้นตอนการทำสัญลักษณ์แบบออฟไลน์ ดูส่วน การทำความเข้าใจรายงานสแต็ก ด้านล่าง
ไม่ถูกต้องฟรี ใช้หลังจากฟรี นี่เป็นจุดบกพร่องฟรีสองเท่า หากสิ่งนี้เกิดขึ้นระหว่างการปิดกระบวนการ อาจบ่งบอกถึง การละเมิด ODR
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
ไม่สามารถอธิบายที่อยู่ได้ อาจเป็นแบบอิสระ (ไม่มีหน่วยความจำที่ไม่เคยมีการจัดสรรมาก่อน) หรือเพิ่มเป็นสองเท่าหลังจากหน่วยความจำที่จัดสรรถูกขับออกจากบัฟเฟอร์ว่างของ HWASan
0x… คือหน่วยความจำเงา HWAsan นี่เป็นแอปฟรีอย่างแน่นอนเนื่องจากแอปพลิเคชันพยายามเพิ่มหน่วยความจำภายใน HWASan

การติดตามสแต็กที่ตั้งดีล

การติดตามสแต็กของตำแหน่งที่หน่วยความจำถูกยกเลิกการจัดสรร แสดงเฉพาะสำหรับข้อบกพร่องที่ใช้งานหลังจากใช้งานฟรีหรือไม่มีข้อผิดพลาด ดู ส่วนสัญลักษณ์ เพื่อเป็นสัญลักษณ์

การติดตามสแต็กการจัดสรร

การติดตามสแต็กของตำแหน่งที่จัดสรรหน่วยความจำ ดู ส่วนสัญลักษณ์ เพื่อเป็นสัญลักษณ์

ข้อมูลการดีบักขั้นสูง

รายงาน HWASan ยังนำเสนอข้อมูลการดีบักขั้นสูงบางส่วน ซึ่งรวมถึง (ตามลำดับ):

  1. รายการเธรดในกระบวนการ
  2. รายการเธรดในกระบวนการ
  3. ค่าของแท็กหน่วยความจำใกล้กับหน่วยความจำที่บกพร่อง
  4. การถ่ายโอนข้อมูลของการลงทะเบียนที่จุดเข้าถึงหน่วยความจำ

ดัมพ์แท็กหน่วยความจำ

สามารถใช้การถ่ายโอนข้อมูลหน่วยความจำแท็กเพื่อค้นหาการจัดสรรหน่วยความจำใกล้เคียงด้วยแท็กเดียวกันกับแท็กตัวชี้ สิ่งเหล่านี้อาจชี้ให้เห็นถึงการเข้าถึงนอกขอบเขตด้วยออฟเซ็ตขนาดใหญ่ หนึ่งแท็กสอดคล้องกับหน่วยความจำ 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  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
(สังเกตการเรียกใช้แท็ก "โฆษณา" ขนาด 6 × 16 = 96 ไบต์ทางด้านซ้ายที่ตรงกับแท็กตัวชี้)

หากขนาดของการจัดสรรไม่ใช่ผลคูณของ 16 ขนาดที่เหลือจะถูกจัดเก็บเป็น แท็กหน่วยความจำ และแท็กจะถูกจัดเก็บเป็น แท็กแบบเม็ดสั้น ในตัวอย่างด้านบนหลังจากโฆษณาที่มีแท็กการจัดสรรเป็นตัวหนา เรามีการจัดสรรแท็ก 5c เป็น 5 × 16 + 4 = 84 ไบต์

แท็กหน่วยความจำเป็นศูนย์ (เช่น tags: ad/ 00 (ptr/mem) ) มักจะบ่งชี้ถึงข้อผิดพลาดแบบใช้สแต็กหลังจากส่งคืน

ลงทะเบียนการถ่ายโอนข้อมูล

การถ่ายโอนข้อมูลการลงทะเบียนในรายงาน HWASan สอดคล้องกับคำสั่งจริงที่ทำการเข้าถึงหน่วยความจำที่ไม่ถูกต้อง ตามมาด้วยรีจิสเตอร์ดัมพ์อื่นจากตัวจัดการสัญญาณ Android ปกติ - ไม่ต้องสนใจตัวที่สอง มันถูกเรียกเมื่อ HWASan เรียกว่า abort() และไม่เกี่ยวข้องกับบั๊ก

สัญลักษณ์

ในการรับชื่อฟังก์ชันและหมายเลขบรรทัดในการติดตามสแต็ก (และรับชื่อตัวแปรสำหรับบั๊กที่ใช้หลังขอบเขต) จำเป็นต้องมีขั้นตอนการใช้สัญลักษณ์ออฟไลน์

การตั้งค่าครั้งแรก: ติดตั้ง llvm- symbolizer

เพื่อให้เป็นสัญลักษณ์ ระบบของคุณต้องติดตั้ง llvm- symbolizer และเข้าถึงได้จาก $PATH บน Debian คุณสามารถติดตั้งได้โดยใช้ sudo apt install llvm

รับไฟล์สัญลักษณ์

สำหรับการแสดงสัญลักษณ์ เราต้องการไบนารีที่ไม่ได้ถอดรหัสที่มีสัญลักษณ์ จะพบสิ่งเหล่านี้ได้ที่ไหนขึ้นอยู่กับประเภทของงานสร้าง:

สำหรับ บิลด์ในเครื่อง ไฟล์สัญลักษณ์สามารถพบได้ใน out/target/product/<product>/symbols/

สำหรับ บิลด์ AOSP (เช่น แฟลชจาก Flashstation ) บิลด์ดังกล่าวสามารถพบได้ใน 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 ไม่ได้แปลงเนื้อหานี้เป็นเนื้อหาที่มนุษย์เข้าใจได้ในรายงานข้อบกพร่อง และต้องมี ขั้นตอนการใช้สัญลักษณ์ เพิ่มเติม

การละเมิด ODR

ข้อบกพร่องบางอย่างที่รายงานโดย HWASan ยังสามารถบ่งบอกถึงการละเมิด One Definition Rule (ODR) การละเมิด ODR เกิดขึ้นเมื่อมีการกำหนดตัวแปรเดียวกันหลายครั้งในโปรแกรมเดียวกัน นอกจากนี้ยังหมายความว่าตัวแปรถูกทำลายหลายครั้ง อาจทำให้เกิดข้อผิดพลาด use-after-free

หลังจากสัญลักษณ์ การละเมิด ODR จะแสดง use-after-free ด้วย __cxa_finalize ทั้งบนสแต็กการเข้าถึงที่ไม่ถูกต้องและสแต็ก "อิสระที่นี่" สแต็ก "ที่จัดสรรไว้ก่อนหน้านี้" มี __dl__ZN6soinfo17call_constructorsEv และควรชี้ไปที่ตำแหน่งในโปรแกรมของคุณซึ่งกำหนดตัวแปรที่สูงกว่าในสแต็ก

เหตุผลหนึ่งที่ ODR อาจถูกละเมิดคือเมื่อมีการใช้ไลบรารีแบบสแตติก ถ้าสแตติกไลบรารีที่กำหนด C++ global ถูกลิงก์ไปยังไลบรารีที่ใช้ร่วมกันหรือไฟล์เรียกทำงานหลายรายการ คำจำกัดความหลายรายการของสัญลักษณ์เดียวกันอาจลงเอยด้วยการมีอยู่ในพื้นที่ที่อยู่เดียวกัน ซึ่งจะทำให้เกิดข้อผิดพลาด ODR

การแก้ไขปัญหา

"HWAddressSanitizer ไม่สามารถอธิบายที่อยู่โดยละเอียดได้"

บางครั้ง HWASan อาจใช้พื้นที่ไม่เพียงพอสำหรับข้อมูลเกี่ยวกับการจัดสรรหน่วยความจำที่ผ่านมา ในกรณีดังกล่าว รายงานจะมีเพียงสแต็กเทรซเดียวสำหรับการเข้าถึงหน่วยความจำทันที ตามด้วยหมายเหตุ:

  HWAddressSanitizer can not describe address in more detail.

ในบางกรณีสามารถแก้ไขได้โดยการรันการทดสอบหลายๆ ครั้ง อีกทางเลือกหนึ่งคือเพิ่มขนาดประวัติ HWASan ซึ่งสามารถทำได้ทั่วโลกใน build/soong/cc/sanitize.go (มองหา hwasanGlobalOptions ) หรือในสภาพแวดล้อมกระบวนการของคุณ (ลองใช้ adb shell echo $HWASAN_OPTIONS เพื่อดูการตั้งค่าปัจจุบัน)

"บั๊กที่ซ้อนอยู่ในเธรดเดียวกัน"

ซึ่งหมายความว่ามีข้อบกพร่องขณะสร้างรายงานข้อขัดข้องของ HWASan ซึ่งมักเกิดจากข้อบกพร่องในรันไทม์ HWASan โปรด แจ้งข้อบกพร่อง และให้คำแนะนำเกี่ยวกับวิธีการทำให้เกิดปัญหาซ้ำหากเป็นไปได้