ความสมบูรณ์ของโฟลว์การควบคุม (CFI) คือกลไกการรักษาความปลอดภัยที่ไม่อนุญาตให้เปลี่ยนแปลงกราฟโฟลว์การควบคุมเดิมของไบนารีที่คอมไพล์แล้ว ซึ่งทำให้การโจมตีดังกล่าวทำได้ยากขึ้นอย่างมาก
ใน Android 9 เราได้เปิดใช้ CFI ของ LLVM ในคอมโพเนนต์เพิ่มเติมและในเคอร์เนลด้วย CFI ของระบบจะเปิดอยู่โดยค่าเริ่มต้น แต่คุณต้องเปิดใช้ CFI ของเคอร์เนล
CFI ของ LLVM กำหนดให้ต้องคอมไพล์ด้วยการเพิ่มประสิทธิภาพเวลาลิงก์ (LTO) LTO จะเก็บรักษาการนำเสนอบิตโค้ด LLVM ของไฟล์ออบเจ็กต์ไว้จนกว่าจะถึงเวลาลิงก์ ซึ่งช่วยให้คอมไพเลอร์สามารถหาเหตุผลเกี่ยวกับการเพิ่มประสิทธิภาพที่ทำได้ดีขึ้น การเปิดใช้ LTO จะลดขนาดของไบนารีขั้นสุดท้ายและปรับปรุงประสิทธิภาพ แต่จะทำให้เวลาคอมไพล์นานขึ้น ในการทดสอบบน Android พบว่าการใช้ LTO และ CFI ร่วมกันทำให้ขนาดและประสิทธิภาพของโค้ดเพิ่มขึ้นเพียงเล็กน้อย และในบางกรณีก็ทำให้ทั้ง 2 อย่างดีขึ้น
ดูรายละเอียดทางเทคนิคเพิ่มเติมเกี่ยวกับ CFI และวิธีจัดการการตรวจสอบการควบคุมแบบส่งต่ออื่นๆ ได้ที่เอกสารประกอบการออกแบบ LLVM
การใช้งาน
การแก้ไข kCFI มีอยู่ในเคอร์เนล Android ทุกเวอร์ชันที่รองรับ ตัวเลือก CONFIG_CFI_CLANG
จะเปิดใช้ kCFI และตั้งค่าไว้โดยค่าเริ่มต้นใน GKI
การแก้ปัญหา
หลังจากเปิดใช้แล้ว ให้แก้ไขข้อผิดพลาดประเภทไม่ตรงกันซึ่งอาจเกิดขึ้นกับไดรเวอร์ การเรียกใช้ฟังก์ชันโดยอ้อมผ่านตัวชี้ฟังก์ชันที่ใช้ร่วมกันไม่ได้ทำให้ CFI หยุดทำงาน เมื่อตรวจพบข้อผิดพลาด CFI เคอร์เนลจะพิมพ์คำเตือนที่รวมทั้งฟังก์ชันที่เรียกใช้และสแต็กเทรซที่ทําให้เกิดความผิดพลาด แก้ไขโดยตรวจสอบว่าตัวชี้ฟังก์ชันมีประเภทเดียวกับฟังก์ชันที่เรียกใช้เสมอ
หากต้องการช่วยแก้ไขข้อผิดพลาด CFI ให้เปิดใช้ CONFIG_CFI_PERMISSIVE
ซึ่งจะพิมพ์คำเตือนแทนที่จะทำให้เกิด Kernel Panic ต้องไม่ใช้โหมดอนุญาตในเวอร์ชันที่ใช้งานจริง
การตรวจสอบความถูกต้อง
ปัจจุบันยังไม่มีการทดสอบ CTS สำหรับ CFI โดยเฉพาะ แต่ให้ตรวจสอบว่าการทดสอบ CTS ผ่านทั้งที่มีและไม่มีการเปิดใช้ CFI เพื่อยืนยันว่า CFI ไม่ได้ส่งผลต่ออุปกรณ์