與使用者空間元件的 LLVM 型清除工具類似,Android 包含 Kernel AddressSanitizer (KASan)。KASan 結合了核心和編譯時間修改項目,可產生經過檢測的系統,方便您找出錯誤並分析根本原因。
KASan 可偵測核心中的多種記憶體違規行為。還能偵測堆疊、堆積和全域變數的越界讀取和寫入,以及偵測釋放後使用和重複釋放。
與 ASan 類似,KASan 會在編譯時間使用記憶體函式檢測功能,並使用陰影記憶體追蹤執行階段的記憶體存取作業。在 KASan 中,八分之一的核心記憶體空間專用於陰影記憶體,可判斷記憶體存取是否有效。
KASan 支援 x86_64 和 arm64 架構。自 4.0 版起,這項功能已納入上游核心,並向後移植到以 Android 3.18 為基礎的核心。
除了 KASan,kcov 也是另一項有助於測試的 Kernel 修改項目。kcov 的開發目的是為了在 Kernel 中進行涵蓋範圍導向模糊測試。這項指標會根據系統呼叫輸入內容測量涵蓋範圍,適用於模糊測試系統,例如 syzkaller。
導入作業
如要編譯啟用 KASan 和 kcov 的核心,請在核心建構設定中新增下列建構標記:
CONFIG_KASAN CONFIG_KASAN_INLINE CONFIG_TEST_KASAN CONFIG_KCOV CONFIG_SLUB CONFIG_SLUB_DEBUG CONFIG_CC_OPTIMIZE_FOR_SIZE
並移除下列項目:
CONFIG_SLUB_DEBUG_ON CONFIG_SLUB_DEBUG_PANIC_ON CONFIG_KASAN_OUTLINE CONFIG_KERNEL_LZ4
接著,請照常建構及刷入核心。KASan 核心比原始核心大得多,如有需要,請修改任何開機參數和系統啟動載入程式設定,將此情況納入考量。
刷寫核心後,請檢查核心啟動記錄,確認 KASan 是否已啟用並執行。核心會啟動,並提供 KASan 的記憶體對應資訊,例如:
... [ 0.000000] c0 0 Virtual kernel memory layout: [ 0.000000] c0 0 kasan : 0xffffff8000000000 - 0xffffff9000000000 ( 64 GB) [ 0.000000] c0 0 vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000 ( 182 GB) [ 0.000000] c0 0 vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000 ( 8 GB maximum) [ 0.000000] c0 0 0xffffffbdc0000000 - 0xffffffbdc3f95400 ( 63 MB actual) [ 0.000000] c0 0 PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000 ( 16 MB) [ 0.000000] c0 0 fixed : 0xffffffbffbdfd000 - 0xffffffbffbdff000 ( 8 KB) [ 0.000000] c0 0 modules : 0xffffffbffc000000 - 0xffffffc000000000 ( 64 MB) [ 0.000000] c0 0 memory : 0xffffffc000000000 - 0xffffffc0fe550000 ( 4069 MB) [ 0.000000] c0 0 .init : 0xffffffc001d33000 - 0xffffffc001dce000 ( 620 KB) [ 0.000000] c0 0 .text : 0xffffffc000080000 - 0xffffffc001d32284 ( 29385 KB) ...
錯誤的樣子如下:
[ 18.539668] c3 1 ================================================================== [ 18.547662] c3 1 BUG: KASAN: null-ptr-deref on address 0000000000000008 [ 18.554689] c3 1 Read of size 8 by task swapper/0/1 [ 18.559988] c3 1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G W 3.18.24-xxx #1 [ 18.569275] c3 1 Hardware name: Android Device [ 18.577433] c3 1 Call trace: [ 18.580739] c3 1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4 [ 18.586985] c3 1 [<ffffffc00008b600>] show_stack+0x10/0x1c [ 18.592889] c3 1 [<ffffffc001481194>] dump_stack+0x74/0xc8 [ 18.598792] c3 1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0 [ 18.605038] c3 1 [<ffffffc00020286c>] __asan_load8+0x20/0x80 [ 18.611115] c3 1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024 [ 18.617976] c3 1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c [ 18.624832] c3 1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678 [ 18.631082] c3 1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac [ 18.637676] c3 1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364 [ 18.644625] c3 1 [<ffffffc001478e20>] kernel_init+0x10/0xd8 [ 18.650613] c3 1 ==================================================================
此外,如果核心中已啟用模組,您可以載入 test_kasan 核心模組,進行進一步測試。這個模組會嘗試存取超出範圍的記憶體,以及釋放後使用,有助於確保您在目標裝置上正確啟用 KASan。