內核控制流完整性

控制流完整性(CFI) 是一種安全機制,它不允許對已編譯二進製文件的原始控制流圖進行更改,從而大大提高了執行此類攻擊的難度。

在 Android 9 中,我們在更多組件和內核中啟用了 LLVM 的 CFI 實現。系統 CFI默認開啟,但您需要啟用內核 CFI。

LLVM 的 CFI 需要使用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 ,它會打印出警告而不是導致內核崩潰。生產環境中不得使用許可模式。

驗證

目前,沒有專門針對 CFI 的 CTS 測試。相反,請確保在啟用或不啟用 CFI 的情況下通過 CTS 測試,以驗證 CFI 不會影響設備。