AddressSanitizer ที่ทำงานด้วยความช่วยเหลือของฮาร์ดแวร์

ดูข้อมูลเกี่ยวกับวิธีอ่านข้อขัดข้องของ HWASan ได้ที่ทำความเข้าใจรายงาน HWASan

Hardware-assisted AddressSanitizer (HWASan) เป็นเครื่องมือตรวจหาข้อผิดพลาดเกี่ยวกับหน่วยความจำ ซึ่งคล้ายกับ AddressSanitizer HWASan ใช้ RAM น้อยกว่า ASan มาก จึงเหมาะสำหรับ การแซนิไทซ์ทั้งระบบ HWASan ใช้ได้ใน Android 10 ขึ้นไป และใช้ได้เฉพาะในฮาร์ดแวร์ AArch64 เท่านั้น

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

HWASan มีข้อดีดังนี้เมื่อเทียบกับ ASan แบบคลาสสิก

  • ค่าใช้จ่าย CPU ที่คล้ายกัน (~2 เท่า)
  • ค่าใช้จ่ายเพิ่มเติมด้านขนาดโค้ดที่คล้ายกัน (40-50%)
  • ค่าใช้จ่ายด้าน RAM น้อยลงมาก (10% - 35%)

HWASan ตรวจหาข้อบกพร่องชุดเดียวกับ ASan ได้

  • บัฟเฟอร์ล้น/ขาดในสแต็กและฮีป
  • การใช้ฮีปหลังจากปล่อย
  • การใช้สแต็กนอกขอบเขต
  • ดับเบิลฟรี/ไวลด์ฟรี

นอกจากนี้ HWASan ยังตรวจหาการใช้สแต็กหลังจากกลับมาด้วย

HWASan (เช่นเดียวกับ ASan) ใช้ได้กับ UBSan และเปิดใช้ทั้ง 2 อย่างในเป้าหมายพร้อมกันได้

รายละเอียดการใช้งานและข้อจำกัด

HWASan ใช้แนวทางการติดแท็ก หน่วยความจำ ซึ่งค่าแท็กแบบสุ่มขนาดเล็กจะเชื่อมโยง ทั้งกับพอยน์เตอร์และช่วงของที่อยู่หน่วยความจำ หากต้องการให้การเข้าถึงหน่วยความจำ ถูกต้อง แท็กพอยน์เตอร์และหน่วยความจำต้องตรงกัน HWASan อาศัยฟีเจอร์ไบต์บนสุดของ ARMv8 ที่ละเว้น (TBI) หรือที่เรียกว่าการติดแท็กที่อยู่เสมือน เพื่อจัดเก็บแท็กพอยน์เตอร์ใน บิตสูงสุดของที่อยู่

อ่านเพิ่มเติมเกี่ยวกับการออกแบบ HWASan ได้ในเว็บไซต์เอกสารประกอบของ Clang

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

อย่างไรก็ตาม HWASan มีค่าแท็กที่เป็นไปได้แบบจำกัด (256) ซึ่งหมายความว่ามีโอกาส 0.4% ที่จะพลาดข้อบกพร่อง ในระหว่างการเรียกใช้โปรแกรม 1 ครั้ง

ข้อกำหนด

เคอร์เนล Android ทั่วไปเวอร์ชันล่าสุด (4.14 ขึ้นไป) รองรับ HWASan ทันที สาขาเฉพาะของ Android 10 ไม่รองรับ HWASan

การรองรับ Userspace สำหรับ HWASan พร้อมใช้งานแล้วตั้งแต่ Android 11 เป็นต้นไป

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

หากคุณสร้างด้วย Toolchain ที่กำหนดเอง โปรดตรวจสอบว่า Toolchain นั้นมีทุกอย่างจนถึงคอมมิต LLVM c336557f

ใช้ HWASan

ใช้คำสั่งต่อไปนี้เพื่อสร้างแพลตฟอร์มทั้งหมดโดยใช้ HWASan

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

คุณสามารถเพิ่มการตั้งค่า SANITIZE_TARGET ลงในคำจำกัดความผลิตภัณฑ์ได้เพื่อความสะดวก คล้ายกับ aosp_coral_hwasan

สำหรับผู้ใช้ที่คุ้นเคยกับ AddressSanitizer ความซับซ้อนในการสร้างจะลดลงอย่างมาก

  • ไม่จำเป็นต้องเรียกใช้ make 2 ครั้ง
  • บิลด์แบบเพิ่มจะทำงานได้ทันที
  • ไม่จำเป็นต้องแฟลชข้อมูลผู้ใช้

นอกจากนี้ ข้อจำกัดบางอย่างของ AddressSanitizer ก็หายไปด้วย

  • รองรับไฟล์ที่เรียกใช้งานแบบคงที่
  • คุณจะข้ามการล้างข้อมูลเป้าหมายอื่นๆ ที่ไม่ใช่ libc ก็ได้ ซึ่งต่างจาก ASan ตรงที่ไม่มีข้อกำหนดว่าหากมีการล้างข้อมูลไลบรารีแล้ว ไฟล์ปฏิบัติการที่ลิงก์กับไลบรารีนั้นจะต้องได้รับการล้างข้อมูลด้วย

คุณสามารถสลับระหว่าง HWASan กับอิมเมจปกติที่หมายเลขบิลด์เดียวกัน (หรือสูงกว่า) ได้อย่างอิสระ คุณไม่จำเป็นต้องล้างข้อมูลในอุปกรณ์

หากต้องการข้ามการล้างข้อมูลของโมดูล ให้ใช้ LOCAL_NOSANITIZE := hwaddress (Android.mk) หรือ sanitize: { hwaddress: false } (Android.bp)

ล้างข้อมูลเป้าหมายแต่ละรายการ

คุณเปิดใช้ HWASan ต่อเป้าหมายได้ในการสร้างปกติ (ที่ไม่ได้แซนิตไทซ์) ตราบใดที่ libc.so ได้รับการแซนิตไทซ์ด้วย เช่นกัน เพิ่ม hwaddress: true ไปยังบล็อกการล้างข้อมูลใน "libc_defaults" ใน bionic/libc/Android.bp จากนั้นทำเช่นเดียวกันในเป้าหมายที่คุณกำลังดำเนินการ

โปรดทราบว่าการล้างข้อมูล libc จะช่วยให้ติดแท็กการจัดสรรหน่วยความจำฮีพได้ทั่วทั้งระบบ รวมถึง การตรวจสอบแท็กสำหรับการดำเนินการหน่วยความจำภายใน libc.so ซึ่งอาจตรวจพบข้อบกพร่องแม้ในไบนารี ที่ไม่ได้เปิดใช้ HWASan หากการเข้าถึงหน่วยความจำที่ไม่ถูกต้องอยู่ใน libc.so (เช่น pthread_mutex_unlock() ใน Mutex ที่delete()

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

สแต็กเทรซที่ดีขึ้น

HWASan ใช้โปรแกรมยกเลิกการเรียกที่รวดเร็วซึ่งอิงตามตัวชี้เฟรมเพื่อบันทึก Stack Trace สำหรับเหตุการณ์การจัดสรรและการยกเลิกการจัดสรรหน่วยความจำทุกรายการใน โปรแกรม Android จะเปิดใช้ตัวชี้เฟรมในโค้ด AArch64 โดยค่าเริ่มต้น จึงใช้งานได้ดีในทางปฏิบัติ หากต้องการยกเลิกการดำเนินการผ่าน โค้ดที่มีการจัดการ ให้ตั้งค่า HWASAN_OPTIONS=fast_unwind_on_malloc=0 ในสภาพแวดล้อมของกระบวนการ โปรดทราบว่าสแต็กการเข้าถึงหน่วยความจำที่ไม่ถูกต้อง จะใช้ Unwinder "ช้า" โดยค่าเริ่มต้น การตั้งค่านี้มีผลกับ การติดตามการจัดสรรและการยกเลิกการจัดสรรเท่านั้น ตัวเลือกนี้อาจใช้ CPU มาก ขึ้นอยู่กับภาระงาน

การแทนที่ด้วยสัญลักษณ์

ดูการสร้างสัญลักษณ์ ใน "ทำความเข้าใจรายงาน HWASan"

HWASan ในแอป

HWASan ไม่สามารถดูโค้ด Java ได้เช่นเดียวกับ AddressSanitizer แต่ ตรวจหาข้อบกพร่องในไลบรารี JNI ได้ จนถึง Android 14 ระบบไม่รองรับการเรียกใช้แอป HWASan ในอุปกรณ์ที่ไม่ใช่ HWASan

ในอุปกรณ์ HWASan คุณสามารถตรวจสอบแอปด้วย HWASan ได้โดยการสร้างโค้ดด้วย SANITIZE_TARGET:=hwaddress ใน Make หรือ -fsanitize=hwaddress ในแฟล็กคอมไพเลอร์ ในอุปกรณ์ที่ไม่ใช่ HWASan (ที่ใช้ Android 14 ขึ้นไป) คุณต้องเพิ่มการตั้งค่าไฟล์ wrap.sh LD_HWASAN=1 ดูรายละเอียดเพิ่มเติมได้ใน เอกสารประกอบสำหรับนักพัฒนาแอป