ดู การทำความเข้าใจรายงาน HWASan สำหรับข้อมูลเกี่ยวกับวิธีการอ่านข้อขัดข้องของ HWASan!
AddressSanitizer ที่ได้รับความช่วยเหลือจากฮาร์ดแวร์ (HWASan) เป็นเครื่องมือตรวจจับข้อผิดพลาดของหน่วยความจำที่คล้ายกับ AddressSanitizer HWASan ใช้ RAM น้อยกว่ามากเมื่อเทียบกับ ASan ซึ่งทำให้เหมาะสำหรับการฆ่าเชื้อทั้งระบบ HWASan ใช้งานได้บน Android 10 ขึ้นไปเท่านั้น และบนฮาร์ดแวร์ AArch64 เท่านั้น
แม้ว่า HWASan จะมีประโยชน์เป็นหลักสำหรับโค้ด C/C++ แต่ HWASan ยังสามารถช่วยแก้ไขข้อบกพร่องโค้ด Java ที่ทำให้เกิดข้อขัดข้องใน C/C++ ที่ใช้ในการปรับใช้อินเทอร์เฟซ Java มีประโยชน์เพราะจะตรวจจับข้อผิดพลาดของหน่วยความจำเมื่อเกิดขึ้น โดยชี้ให้คุณไปที่โค้ดที่รับผิดชอบโดยตรง
คุณสามารถแฟลชรูปภาพ HWASan ที่สร้างไว้ล่วงหน้าไปยังอุปกรณ์ Pixel ที่รองรับได้จาก ci.android.com ( คำแนะนำการตั้งค่าโดยละเอียด )
เมื่อเปรียบเทียบกับ ASan แบบคลาสสิก HWASan มี:
- โอเวอร์เฮด CPU ที่คล้ายกัน (~ 2x)
- ค่าใช้จ่ายที่มีขนาดโค้ดใกล้เคียงกัน (40 – 50%)
- ค่าใช้จ่าย RAM น้อยกว่ามาก (10% – 35%)
HWASan ตรวจพบชุดข้อบกพร่องเดียวกันกับ ASan:
- สแต็กและฮีปบัฟเฟอร์ล้น/อันเดอร์โฟลว์
- ใช้กองหลังจากฟรี
- สแต็กใช้นอกขอบเขต
- ฟรีสองเท่า/ฟรีแบบไวด์
นอกจากนี้ HWASan ยังตรวจจับการใช้สแต็กหลังจากส่งคืน
HWASan (เหมือนกับ ASan) เข้ากันได้กับ UBSan ทั้งสองสามารถเปิดใช้งานบนเป้าหมายได้ในเวลาเดียวกัน
รายละเอียดการดำเนินการและข้อจำกัด
HWASan ยึดตามแนวทาง การแท็กหน่วยความจำ โดยที่ค่าแท็กสุ่มขนาดเล็กจะสัมพันธ์กับทั้งพอยน์เตอร์และช่วงของที่อยู่หน่วยความจำ เพื่อให้การเข้าถึงหน่วยความจำถูกต้อง ตัวชี้และแท็กหน่วยความจำจะต้องตรงกัน HWASan อาศัยคุณสมบัติ ARMv8 แบบละเว้นไบต์บนสุด (TBI) หรือที่เรียกว่า การแท็กที่อยู่เสมือน เพื่อจัดเก็บแท็กตัวชี้ในบิตสูงสุดของที่อยู่
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ การออกแบบ HWASan ได้จากไซต์เอกสารประกอบของ Clang
จากการออกแบบ HWASan ไม่มีโซนสีแดงขนาดจำกัดของ ASan สำหรับการตรวจจับโอเวอร์โฟลว์ หรือการกักกันความจุจำกัดของ ASan สำหรับการตรวจจับการใช้งานหลังจากใช้งานฟรี ด้วยเหตุผลนี้ HWASan จึงสามารถตรวจจับจุดบกพร่องได้ไม่ว่าหน่วยความจำล้นจะใหญ่แค่ไหนหรือหน่วยความจำถูกจัดสรรคืนมานานแค่ไหนแล้ว สิ่งนี้ทำให้ HWASan ได้เปรียบเหนือ ASan อย่างมาก
อย่างไรก็ตาม HWASan มีค่าแท็กที่เป็นไปได้ในจำนวนจำกัด (256) ซึ่งหมายความว่ามีความน่าจะเป็น 0.4% ที่จะพลาดจุดบกพร่องใดๆ ในระหว่างการทำงานของโปรแกรมหนึ่งครั้ง
ความต้องการ
เคอร์เนล Android ทั่วไป เวอร์ชันล่าสุด (4.14+) รองรับ HWASan ทันทีที่แกะกล่อง สาขาเฉพาะของ Android 10 ไม่รองรับ HWASan
การสนับสนุน Userspace สำหรับ HWASan นั้นมีให้ตั้งแต่ Android 11
หากคุณกำลังทำงานกับเคอร์เนลอื่น HWASan ต้องใช้เคอร์เนล Linux เพื่อยอมรับพอยน์เตอร์ที่แท็กในอาร์กิวเมนต์การเรียกของระบบ การสนับสนุนสำหรับสิ่งนี้ถูกนำไปใช้ในชุดแพตช์อัปสตรีมต่อไปนี้:
- ที่อยู่ที่ติดแท็ก arm64 ABI
- arm64: ปลดแท็กตัวชี้ผู้ใช้ที่ส่งผ่านไปยังเคอร์เนล
- mm: หลีกเลี่ยงการสร้างนามแฝงที่อยู่เสมือนใน brk()/mmap()/mremap()
- arm64: ตรวจสอบที่อยู่ที่ติดแท็กใน access_ok() ที่ถูกเรียกจากเธรดเคอร์เนล
หากคุณกำลังสร้างด้วย toolchain แบบกำหนดเอง ตรวจสอบให้แน่ใจว่ารวมทุกอย่างจนถึง LLVM commit c336557f
การใช้ HWASan
ใช้คำสั่งต่อไปนี้เพื่อสร้างแพลตฟอร์มทั้งหมดโดยใช้ HWASan:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
เพื่อความสะดวก คุณสามารถเพิ่มการตั้งค่า SANITIZE_TARGET ให้กับคำจำกัดความของผลิตภัณฑ์ ซึ่งคล้ายกับ aosp_coral_hwasan
สำหรับผู้ใช้ที่คุ้นเคยกับ AddressSanitizer ความซับซ้อนในการสร้างจำนวนมากได้หมดไป:
- ไม่จำเป็นต้องเรียกใช้ make สองครั้ง
- งานสร้างส่วนเพิ่มทำงานนอกกรอบ
- ไม่จำเป็นต้องแฟลชข้อมูลผู้ใช้
ข้อจำกัดของ 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()
บน delete()
ed mutex)
ไม่จำเป็นต้องเปลี่ยนแปลงไฟล์บิลด์ใดๆ หากทั้งแพลตฟอร์มสร้างโดยใช้ HWASan
แฟลชสเตชั่น
เพื่อวัตถุประสงค์ในการพัฒนา คุณสามารถแฟลชบิลด์ AOSP ที่เปิดใช้งาน HWASan บนอุปกรณ์ Pixel พร้อมตัวโหลดบูตที่ปลดล็อคได้โดยใช้ Flashstation เลือกเป้าหมาย _hwasan เช่น aosp_flame_hwasan-userdebug ดู เอกสาร NDK สำหรับ HWASan สำหรับนักพัฒนาแอปสำหรับรายละเอียดเพิ่มเติม
สแต็กเทรซดีกว่า
HWASan ใช้ตัวถอดรหัสแบบเฟรมพอยน์เตอร์ที่รวดเร็วเพื่อบันทึกการติดตามสแต็กสำหรับการจัดสรรหน่วยความจำและการจัดสรรคืนทุกเหตุการณ์ในโปรแกรม Android เปิดใช้งานตัวชี้เฟรมในโค้ด AArch64 เป็นค่าเริ่มต้น ดังนั้นจึงใช้งานได้ดีในทางปฏิบัติ หากคุณต้องการคลายโค้ดที่ได้รับการจัดการ ให้ตั้งค่า HWASAN_OPTIONS=fast_unwind_on_malloc=0
ในสภาวะแวดล้อมกระบวนการ โปรดทราบว่าการติดตามสแต็กการเข้าถึงหน่วยความจำที่ไม่ดีจะใช้ตัวคลาย "ช้า" ตามค่าเริ่มต้น การตั้งค่านี้ส่งผลต่อการจัดสรรและการติดตามการจัดสรรคืนเท่านั้น ตัวเลือกนี้อาจใช้ CPU มาก ขึ้นอยู่กับโหลด
การแสดงสัญลักษณ์
ดู สัญลักษณ์ ใน "การทำความเข้าใจรายงาน HWASan"
HWASan ในแอพ
เช่นเดียวกับ AddressSanitizer HWASan ไม่สามารถมองเห็นโค้ด Java ได้ แต่สามารถตรวจจับจุดบกพร่องในไลบรารี JNI ได้ จนถึง Android 14 ไม่ รองรับการเรียกใช้แอป HWASan บนอุปกรณ์ที่ไม่ใช่ HWASan
บนอุปกรณ์ HWASan สามารถตรวจสอบแอปด้วย HWASan ได้โดยสร้างโค้ดด้วย SANITIZE_TARGET:=hwaddress
ใน Make หรือ -fsanitize=hwaddress
ในแฟล็กคอมไพเลอร์ บนอุปกรณ์ที่ไม่ใช่ HWASan (ใช้ Android 14 หรือใหม่กว่า) จะต้องเพิ่มการตั้งค่าไฟล์ wrap.sh LD_HWASAN=1
ดู เอกสารประกอบสำหรับนักพัฒนาแอป สำหรับรายละเอียดเพิ่มเติม