ความสมบูรณ์ของการควบคุมเคอร์เนลโฟลว์

Control Flow Integrity (CFI) เป็นกลไกความปลอดภัยที่ไม่อนุญาตให้มีการเปลี่ยนแปลงกราฟการควบคุมโฟลว์ดั้งเดิมของไบนารีที่คอมไพล์แล้ว ทำให้การโจมตีดังกล่าวทำได้ยากขึ้นอย่างมาก

ใน Android 9 เราได้เปิดใช้งานการใช้งาน CFI ของ LLVM ในส่วนประกอบเพิ่มเติมและในเคอร์เนลด้วย System CFI เปิดอยู่ตามค่าเริ่มต้น แต่คุณต้องเปิดใช้งาน Kernel CFI

CFI ของ LLVM จำเป็นต้องคอมไพล์ด้วย Link-Time Optimization (LTO) LTO จะรักษาการแสดงบิตโค้ด LLVM ของไฟล์อ็อบเจ็กต์ไว้จนกระทั่งถึงเวลาลิงก์ ซึ่งช่วยให้คอมไพลเลอร์ให้เหตุผลได้ดีขึ้นเกี่ยวกับการปรับปรุงประสิทธิภาพที่สามารถทำได้ การเปิดใช้งาน LTO จะลดขนาดของไบนารีสุดท้ายและปรับปรุงประสิทธิภาพ แต่จะเพิ่มเวลาในการคอมไพล์ ในการทดสอบบน Android การรวมกันของ LTO และ CFI ส่งผลให้มีค่าใช้จ่ายเล็กน้อยต่อขนาดและประสิทธิภาพของโค้ด ในบางกรณีก็ดีขึ้นทั้งคู่

สำหรับรายละเอียดทางเทคนิคเพิ่มเติมเกี่ยวกับ CFI และวิธีจัดการการตรวจสอบควบคุมไปข้างหน้าอื่นๆ โปรดดู เอกสารประกอบการออกแบบ LLVM

การนำไปปฏิบัติ

แพตช์ kCFI อยู่ในเคอร์เนล Android เวอร์ชันที่รองรับทั้งหมด ตัวเลือก CONFIG_CFI_CLANG เปิดใช้งาน kCFI และตั้งค่าเป็นค่าเริ่มต้นใน GKI

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

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

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

การตรวจสอบ

ปัจจุบันไม่มีการทดสอบ CTS สำหรับ CFI โดยเฉพาะ โปรดตรวจสอบให้แน่ใจว่าการทดสอบ CTS ผ่านหรือไม่เปิดใช้งาน CFI เพื่อตรวจสอบว่า CFI จะไม่ส่งผลกระทบต่ออุปกรณ์