內核位址消毒器 (KASan)

與使用者空間元件的基於 LLVM 的清理程式類似,Android 包含核心位址清理程式 (KASAN)。 KASAN 是核心和編譯時修改的組合,形成了一個允許更簡單的錯誤發現和根本原因分析的儀表化系統。

KASAN 可以偵測核心中多種類型的記憶體違規。它還可以檢測堆疊、堆疊和全域變數上的越界讀寫,並且可以偵測釋放後使用和雙重釋放。

與 ASAN 類似,KASAN 使用編譯時記憶體函數檢測和影子記憶體的組合來追蹤執行時間的記憶體存取。在 KASAN 中,八分之一的核心內存空間專用於影子內存,它決定內存存取是否有效。

x86_64 和 arm64 架構支援 KASAN。自 4.0 起,它一直是上游核心的一部分,並已向後移植到基於 Android 3.18 的核心。

除了 KASAN 之外,kcov 是另一個對測試有用的核心修改。 kcov 的開發是為了允許在核心中進行覆蓋引導的模糊測試。它根據系統呼叫輸入來測量覆蓋範圍,並且對於模糊測試系統(例如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)
...

這就是 bug 的樣子:

[   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 很有用。