ส่วนโค้ดปฏิบัติการสำหรับไบนารีของระบบ AArch64 จะทำเครื่องหมายโดยค่าเริ่มต้น ปฏิบัติการเท่านั้น (อ่านไม่ได้) เป็นการลดช่องโหว่จากโค้ดแบบทันท่วงที ใช้การโจมตีซ้ำ โค้ดที่ผสมผสานข้อมูลและการเขียนโค้ดเข้าด้วยกันและเขียนโค้ดอย่างมีจุดมุ่งหมาย ตรวจสอบส่วนเหล่านี้ (โดยไม่ต้องแมปส่วนหน่วยความจำใหม่ให้อ่านได้ก่อน) ใช้งานไม่ได้ แอปที่มี SDK เป้าหมายเป็น 10 (API ระดับ 29 ขึ้นไป) จะได้รับผลกระทบหากแอปพยายามอ่านส่วนโค้ดของ ไลบรารีระบบที่เปิดใช้หน่วยความจำที่ดำเนินการเท่านั้น (XOM) ในหน่วยความจำโดยไม่มีการเรียกใช้ก่อน ทำเครื่องหมายส่วนว่าอ่านได้
เพื่อให้ได้รับประโยชน์สูงสุดจากการลดปัญหานี้ การสนับสนุนทั้งฮาร์ดแวร์และเคอร์เนล ต้องระบุ หากไม่มีการรองรับนี้ การผ่อนปรนชั่วคราวอาจบังคับใช้เพียงบางส่วนเท่านั้น เคอร์เนลทั่วไปของ Android 4.9 มีแพตช์ที่เหมาะสมเพื่อให้บริการเต็มรูปแบบ รองรับสิ่งนี้ในอุปกรณ์ ARMv8.2
การใช้งาน
ไบนารี AArch64 ที่สร้างโดยคอมไพเลอร์จะถือว่าโค้ดและข้อมูลไม่ใช่ ที่มีการผสมรวมเข้าด้วยกัน การเปิดใช้ฟีเจอร์นี้จะไม่ส่งผลเสียต่อประสิทธิภาพของ อุปกรณ์
สำหรับโค้ดที่ต้องตรวจสอบหน่วยความจำโดยเจตนาใน
กลุ่มที่ดำเนินการได้ ขอแนะนำให้เรียกใช้ mprotect
ใน
ส่วนของโค้ดที่ต้องมีการตรวจสอบเพื่อให้อ่านได้ง่าย จากนั้น
ลดความอ่านง่ายเมื่อตรวจสอบเสร็จสมบูรณ์
การใช้งานนี้จะทําให้อ่านลงในกลุ่มหน่วยความจำที่ทําเครื่องหมายเป็น
ดำเนินการเท่านั้นจะทำให้เกิดข้อผิดพลาดการแบ่งกลุ่ม (SEGFAULT
)
ซึ่งอาจเป็นผลจากข้อบกพร่อง ช่องโหว่ และข้อมูล
(การรวมตามตัวอักษร) หรือการตรวจสอบหน่วยความจำโดยเจตนา
การรองรับอุปกรณ์และผลกระทบ
อุปกรณ์ที่มีฮาร์ดแวร์รุ่นเก่าหรือเคอร์เนลรุ่นก่อนหน้า (ต่ำกว่า 4.9) ที่ไม่มี
แพตช์ที่จำเป็นอาจไม่รองรับหรือใช้ประโยชน์จากฟีเจอร์นี้อย่างเต็มที่ อุปกรณ์
ที่ไม่มีการสนับสนุนเคอร์เนลไม่สามารถบังคับใช้การเข้าถึงของผู้ใช้สำหรับหน่วยความจำเฉพาะการดำเนินการ
แต่รหัสเคอร์เนลซึ่งตรวจสอบอย่างชัดเจนว่าหน้าเว็บสามารถอ่านได้
บังคับใช้พร็อพเพอร์ตี้นี้ เช่น process_vm_readv()
ต้องตั้งค่าแฟล็กเคอร์เนล CONFIG_ARM64_UAO
ในเคอร์เนลเป็น
ตรวจสอบว่าเคอร์เนลดำเนินการตามหน้า Userland ที่ทำเครื่องหมายว่า "เรียกใช้งานเท่านั้น" ARMv8 รุ่นก่อนหน้า
หรืออุปกรณ์ ARMv8.2 ที่ปิดใช้การลบล้างการเข้าถึงของผู้ใช้ (UAO) ต้องไม่
ได้รับประโยชน์อย่างเต็มที่จากวิธีนี้ และอาจยังคงสามารถอ่านหน้าสำหรับการดำเนินการเท่านั้นได้โดยใช้
Syscalls
เปลี่ยนโครงสร้างภายในโค้ดที่มีอยู่
โค้ดที่มีการย้ายมาจาก AArch32 อาจมีข้อมูลผสมและ
ซึ่งทำให้เกิดปัญหาขึ้นได้ ในหลายกรณี การแก้ไขปัญหาเหล่านี้ทำได้ง่ายๆ
เป็นการย้ายค่าคงที่ไปยังส่วน .data
ในไฟล์การประกอบ
ชิ้นส่วนประกอบที่เขียนด้วยลายมืออาจต้องเปลี่ยนโครงสร้างภายในโค้ดเพื่อแยกระหว่างเครื่อง ค่าคงที่นี้
ตัวอย่าง
ไบนารีที่สร้างโดยคอมไพเลอร์ Clang ไม่ควรมีปัญหาเกี่ยวกับข้อมูล ที่มีการสอดประสานกันในโค้ด หากโค้ดที่สร้างโดย GNU Compiler Collection (GCC) รวม (จากไลบรารีแบบคงที่) ให้ตรวจสอบไบนารีของเอาต์พุตเพื่อ เพื่อให้มั่นใจว่าค่าคงที่ไม่ได้ถูกรวบรวมไว้ในส่วนโค้ด
หากจำเป็นต้องตรวจสอบโค้ดในส่วนโค้ดสั่งการ
เรียก mprotect
ครั้งแรกเพื่อทำเครื่องหมายว่าอ่านโค้ดได้ หลังจากดำเนินการแล้ว
เสร็จแล้ว โปรดโทรหา mprotect
อีกครั้งเพื่อทำเครื่องหมายว่าอ่านไม่ได้
เปิดใช้ XOM
การดำเนินการเท่านั้นเปิดใช้โดยค่าเริ่มต้นสำหรับไบนารี 64 บิตทั้งหมดในบิลด์ ระบบ
ปิดใช้ XOM
คุณสามารถปิดใช้งานการดำเนินการเท่านั้นในระดับโมดูล ตามโครงสร้างไดเรกทอรีย่อยทั้งหมด หรือ ทั่วทั้งงานสร้าง
สามารถปิดใช้ XOM สำหรับแต่ละโมดูลที่ไม่สามารถเปลี่ยนโครงสร้างภายในโค้ดหรือต้องอ่าน
โค้ดสั่งการ โดยการตั้งค่า LOCAL_XOM
และ xom
ตัวแปรไปยัง false
// Android.mk LOCAL_XOM := false // Android.bp cc_binary { // or other module types ... xom: false, }
หากปิดใช้หน่วยความจำสำหรับการดำเนินการเท่านั้นในไลบรารีแบบคงที่ ระบบจะใช้ระบบบิลด์
นี้กับโมดูลที่ขึ้นต่อกันทั้งหมดของไลบรารีแบบคงที่ คุณสามารถลบล้าง
โดยใช้ xom: true,
หากต้องการปิดใช้หน่วยความจำสำหรับการดำเนินการเท่านั้นในไดเรกทอรีย่อยหนึ่งๆ (ตัวอย่างเช่น
foo/bar/) ส่งค่าไปยัง XOM_EXCLUDE_PATHS
make -j XOM_EXCLUDE_PATHS=foo/bar
หรือคุณสามารถตั้งค่า PRODUCT_XOM_EXCLUDE_PATHS
ในการกำหนดค่าผลิตภัณฑ์ของคุณได้
คุณสามารถปิดใช้ไบนารีสำหรับการดำเนินการเท่านั้นทั่วโลกได้โดยการส่งผ่าน
ENABLE_XOM=false
ลงในคำสั่ง make
make -j ENABLE_XOM=false
การตรวจสอบความถูกต้อง
ไม่มี CTS หรือการทดสอบการยืนยันที่พร้อมใช้งานสำหรับการดำเนินการเท่านั้น
ความทรงจำ คุณสามารถตรวจสอบไบนารีด้วยตนเองได้โดยใช้ readelf
และการตรวจสอบ
สถานะกลุ่มเป้าหมาย