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

เมื่อเครื่องมือ HWASan ตรวจพบจุดบกพร่องของหน่วยความจำ กระบวนการจะสิ้นสุดลงด้วยการยกเลิก () และรายงานจะถูกพิมพ์ไปยัง 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 สามารถวินิจฉัยสาเหตุต่อไปนี้:

  • ใช้งานฟรี
  • แท็กสแต็กไม่ตรงกัน: สิ่งนี้อาจเป็นการใช้สแต็กหลังการส่งคืน / ใช้ขอบเขตหลังหรืออยู่นอกขอบเขต
  • ฮีปบัฟเฟอร์ล้น
  • ทั่วโลกล้น

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

อธิบายสิ่งที่ 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  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
(สังเกตการทำงานของแท็ก "ad" ทางด้านซ้ายขนาด 6 × 16 = 96 ไบต์ซึ่งตรงกับแท็กตัวชี้)

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

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

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

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

การแสดงสัญลักษณ์

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

การตั้งค่าครั้งแรก: ติดตั้ง llvm-สัญลักษณ์

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

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

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

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

สำหรับ บิลด์ AOSP (เช่น flashed จาก Flashstation ) บิลด์สามารถพบได้บน Android CI ใน "อาร์ติแฟกต์" สำหรับบิลด์ จะมีไฟล์ `${PRODUCT}-สัญลักษณ์-${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 ยังสามารถบ่งบอกถึงการละเมิดกฎคำจำกัดความเดียว (ODR) ได้อีกด้วย การละเมิด ODR เกิดขึ้นเมื่อตัวแปรเดียวกันถูกกำหนดหลายครั้งในโปรแกรมเดียวกัน นอกจากนี้ยังหมายความว่าตัวแปรถูกทำลายหลายครั้ง ซึ่งอาจนำไปสู่ข้อผิดพลาดที่ไร้การใช้งาน

หลังจากสัญลักษณ์ การละเมิด ODR แสดง use-after-free ด้วย __cxa_finalize ทั้งบนสแต็กการเข้าถึงที่ไม่ถูกต้องและสแต็ก "freed here" สแต็ก "จัดสรรไว้ก่อนหน้านี้ที่นี่" มี __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 หากคุณมีสิทธิ์เข้าถึงแผ่นศิลาหลุมศพแบบเต็ม อาจเป็นประโยชน์หากพิจารณาจากไฟล์แผนที่หน่วยความจำเพื่อดูว่าที่อยู่เป็นของแผนที่ใด (ถ้ามี)

"ข้อผิดพลาดที่ซ้อนกันในเธรดเดียวกัน"

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