kasan (Kernel Address Sanitizer)是内核的内存检查工具,用来定位内核memory corruption等问题。后面还有一个kfence工具,算是一个后起之秀。
kasan的原理是,每8个字节,使用一个字节,来表示这个8字节内存的状态。然后通过gcc编译选项,生成指令,在每个内存读写的时候,进行检查。判断是否是非法的读写访问。内核一起来的时候,kasan就会保留1/8的内存,因此在内存紧张的设备上,可能kasan跑不起来。
为了支持越界写检查,kasan还修改slab,在分配的内存后面添加red zone。写入red zone意味着越界写。
开启内核KASAN支持:
Kernel hacking --->
Memory Debugging --->
[*] KASAN: runtime memory debugger --->
编写一个test.ko,他分配10个字节,然后写第20个字节,构造一个越界写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> static void out_of_bound_write( void ) { char *a; a = kmalloc(10, GFP_KERNEL); a[20] = 0; } static int __init test_init( void ) { /* * Temporarily enable multi-shot mode. Otherwise, KASAN would only * report the first detected bug and panic the kernel if panic_on_warn * is enabled. */ bool multishot = kasan_save_enable_multi_shot(); out_of_bound_write(); kasan_restore_multi_shot(multishot); return -1; } static void __exit test_exit( void ) { } module_init(test_init); module_exit(test_exit); MODULE_LICENSE( "GPL" ); MODULE_AUTHOR( "Jianpeng Yuan" ); MODULE_DESCRIPTION( "test module" ); |
将ko上传到设备,然后安装 insmod ./test.ko,可以看到kasan成功的检测了到slab out of bound write
[ 36.876948] ==================================================================
[ 36.877022] BUG: KASAN: slab-out-of-bounds in test_init+0x40/0x1000 [test]
[ 36.883101] Write of size 1 at addr 8612f094 by task insmod/193
[ 36.889957]
[ 36.895772] CPU: 1 PID: 193 Comm: insmod Tainted: G O 5.15.38+ #2
[ 36.897510] Hardware name: Generic DT based system
[ 36.904895] [<81314f74>] (unwind_backtrace) from [<8130ea14>] (show_stack+0x10/0x14)
[ 36.909494] [<8130ea14>] (show_stack) from [<81c725c0>] (dump_stack_lvl+0x40/0x4c)
[ 36.917395] [<81c725c0>] (dump_stack_lvl) from [<81c6fa58>] (print_address_description.constprop.0+0x5c/0x2bc)
[ 36.924773] [<81c6fa58>] (print_address_description.constprop.0) from [<8153eaf0>] (kasan_report+0x1b4/0x1d0)
[ 36.934756] [<8153eaf0>] (kasan_report) from [<7f156040>] (test_init+0x40/0x1000 [test])
[ 36.944739] [<7f156040>] (test_init [test]) from [<813027dc>] (do_one_initcall+0xbc/0x3d4)
[ 36.952897] [<813027dc>] (do_one_initcall) from [<81415918>] (do_init_module+0xbc/0x328)
[ 36.960972] [<81415918>] (do_init_module) from [<81419514>] (load_module+0x38b4/0x3d90)
[ 36.969216] [<81419514>] (load_module) from [<81419d18>] (sys_finit_module+0x124/0x170)
[ 36.976942] [<81419d18>] (sys_finit_module) from [<81300060>] (ret_fast_syscall+0x0/0x48)
[ 36.984926] Exception stack(0x8666bfa8 to 0x8666bff0)
[ 36.993267] bfa0: 000fc190 ffffffff 00000003 000fc190 00000000 6e75df7e
[ 36.998307] bfc0: 000fc190 ffffffff 00000077 0000017b 0001caf4 00000000 00000000 000fbb74
[ 37.006462] bfe0: 6e75dcb8 6e75dca8 00034620 66c95820
[ 37.014613]
[ 37.019640] Allocated by task 193:
[ 37.021205] test_init+0x24/0x1000 [test]
[ 37.024416] do_one_initcall+0xbc/0x3d4
[ 37.028495] do_init_module+0xbc/0x328
[ 37.032141] load_module+0x38b4/0x3d90
[ 37.035961] sys_finit_module+0x124/0x170
[ 37.039694] ret_fast_syscall+0x0/0x48
[ 37.043773] 0x6e75dca8
[ 37.047416]
[ 37.049760] The buggy address belongs to the object at 8612f080
[ 37.049760] which belongs to the cache kmalloc-64 of size 64
[ 37.051509] The buggy address is located 20 bytes inside of
[ 37.051509] 64-byte region [8612f080, 8612f0c0)
[ 37.063053] The buggy address belongs to the page:
[ 37.073290] page:3b0e1a95 refcount:1 mapcount:0 mapping:00000000 index:0x0 pfn:0x4612f
[ 37.077894] flags: 0x200(slab|zone=0)
[ 37.085810] raw: 00000200 00000000 00000122 80801200 00000000 80200020 ffffffff 00000001
[ 37.089526] page dumped because: kasan: bad access detected
[ 37.097682]
[ 37.102971] Memory state around the buggy address:
[ 37.104719] 8612ef80: fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc fc
[ 37.109321] 8612f000: 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 37.115830] >8612f080: 00 02 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 37.122335] ^
[ 37.128848] 8612f100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 37.131890] 8612f180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 37.138394] ==================================================================
参考:
The Kernel Address Sanitizer (KASAN)
https://www.kernel.org/doc/html/v4.14/dev-tools/kasan.html
KASAN: WHAT IS IT? HOW DOES IT WORK? AND WHAT ARE THE STRANGE NUMBERS AT THE END?