1。 测试代码如下:
#include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/delay.h> MODULE_LICENSE("GPL"); struct slab_obj { int aa; int bb; int cc; }; typedef struct slab_obj *slab_obj_t; slab_obj_t memblk = NULL; struct kmem_cache *myslabobj; static void mm_create(void) { myslabobj = kmem_cache_create("my_slab_obj", sizeof(struct slab_obj), 0, SLAB_HWCACHE_ALIGN, NULL); memblk = kmem_cache_alloc(myslabobj, GFP_KERNEL); memblk->aa = 0xabcd; memblk->bb = 0x1234; memblk->cc = 0x6879; } static void mm_destroy(void) { kfree(memblk); kmem_cache_destroy(myslabobj); } static int __init slub_debug_init(void) { mm_create(); return 0; } static void __exit slub_debug_exit(void) { mm_destroy(); } module_init(slub_debug_init); module_exit(slub_debug_exit);
注释掉 mm_destroy()里的 Kfree()函数,然后测试
在 rmmod的时候,会有log 报告:
#rmmod slub_debug ============================================================================= BUG my_slab_obj (Tainted: G O): Objects remaining in my_slab_obj on kmem_cache_close() ----------------------------------------------------------------------------- Disabling lock debugging due to kernel taint INFO: Slab 0xc06798e0 objects=128 used=1 fp=0xc7b47fe0 flags=0x0080 CPU: 3 PID: 599 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c00c8768>] (slab_err+0x74/0x84) [<c00c8768>] (slab_err+0x74/0x84) from [<c00ca78c>] (free_partial+0xf8/0x200) [<c00ca78c>] (free_partial+0xf8/0x200) from [<c00ca8d4>] (__kmem_cache_shutdown+0x40/0xd4) [<c00ca8d4>] (__kmem_cache_shutdown+0x40/0xd4) from [<c00acf78>] (kmem_cache_destroy+0x60/0xf0) [<c00acf78>] (kmem_cache_destroy+0x60/0xf0) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30) INFO: Object 0xc7b47000 @offset=0 kmem_cache_destroy my_slab_obj: Slab cache still has objects CPU: 3 PID: 599 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c00ad004>] (kmem_cache_destroy+0xec/0xf0) [<c00ad004>] (kmem_cache_destroy+0xec/0xf0) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30)
在 mm_destroy()里,加上 kfree(memblk),
static void mm_destroy(void) { kfree(memblk); kfree(memblk); kmem_cache_destroy(myslabobj); }
然后,卸载模块:
#rmmod slub_debug ============================================================================= BUG my_slab_obj (Tainted: G B O): Object already free ----------------------------------------------------------------------------- INFO: Slab 0xc0666660 objects=128 used=0 fp=0xc71b3000 flags=0x0081 INFO: Object 0xc71b3000 @offset=0 fp=0xc71b3fe0 Object c71b3000: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5 kkkkkkkkkkk. Redzone c71b300c: bb bb bb bb .... Padding c71b3014: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ CPU: 3 PID: 602 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c036d018>] (free_debug_processing+0x1c0/0x278) [<c036d018>] (free_debug_processing+0x1c0/0x278) from [<c036d838>] (__slab_free+0x38/0x2d0) [<c036d838>] (__slab_free+0x38/0x2d0) from [<bf00401c>] (slub_debug_exit+0x1c/0x28 [slub_debug]) [<bf00401c>] (slub_debug_exit+0x1c/0x28 [slub_debug]) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30) FIX my_slab_obj: Object at 0xc71b3000 not freed
3. use after free:
修改代码如下:
static void mm_destroy(void) { kfree(memblk); memblk->aa=0xabcd; memblk->bb=0x1234; memblk->cc=0x8789; kmem_cache_destroy(myslabobj); }
#rmmod slub_debug ============================================================================= BUG my_slab_obj (Tainted: G B O): Poison overwritten ----------------------------------------------------------------------------- INFO: 0xc71ed000-0xc71ed00a. First byte 0xcd instead of 0x6b INFO: Slab 0xc0666da0 objects=128 used=0 fp=0xc71ed000 flags=0x0080 INFO: Object 0xc71ed000 @offset=0 fp=0xc71edfe0 Object c71ed000: cd ab 00 00 34 12 00 00 89 87 00 00 ....4....... Redzone c71ed00c: bb bb bb bb .... Padding c71ed014: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ CPU: 2 PID: 614 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) from [<c00c7f30>] (check_object+0x1b4/0x240) [<c00c7f30>] (check_object+0x1b4/0x240) from [<c00c8cb0>] (__free_slab+0xf8/0x138) [<c00c8cb0>] (__free_slab+0xf8/0x138) from [<c00ca718>] (free_partial+0x84/0x200) [<c00ca718>] (free_partial+0x84/0x200) from [<c00ca8d4>] (__kmem_cache_shutdown+0x40/0xd4) [<c00ca8d4>] (__kmem_cache_shutdown+0x40/0xd4) from [<c00acf78>] (kmem_cache_destroy+0x60/0xf0) [<c00acf78>] (kmem_cache_destroy+0x60/0xf0) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30) FIX my_slab_obj: Restoring 0xc71ed000-0xc71ed00a=0x6b
4. memory overwritten
修改代码如下:
static void mm_create(void) { myslabobj = kmem_cache_create("my_slab_obj", sizeof(struct slab_obj), 0, SLAB_HWCACHE_ALIGN, NULL); memblk = kmem_cache_alloc(myslabobj, GFP_KERNEL); memblk->aa = 0xabcd; memblk->bb = 0x1234; memblk->cc = 0x6879; slab_obj_t next_addr = memblk + 1; next_addr->cc = 0xdeadbeef; }
#rmmod slub_debug ============================================================================= BUG my_slab_obj (Tainted: G B O): Object padding overwritten ----------------------------------------------------------------------------- INFO: 0xc71ed014-0xc71ed017. First byte 0xef instead of 0x5a INFO: Slab 0xc0666da0 objects=128 used=1 fp=0xc71edfe0 flags=0x0081 INFO: Object 0xc71ed000 @offset=0 fp=0xc71ed020 Object c71ed000: cd ab 00 00 34 12 00 00 79 68 00 00 ....4...yh.. Redzone c71ed00c: cc cc cc cc .... Padding c71ed014: ef be ad de 5a 5a 5a 5a 5a 5a 5a 5a ....ZZZZZZZZ CPU: 3 PID: 638 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) from [<c00c7e20>] (check_object+0xa4/0x240) [<c00c7e20>] (check_object+0xa4/0x240) from [<c036cf18>] (free_debug_processing+0xc0/0x278) [<c036cf18>] (free_debug_processing+0xc0/0x278) from [<c036d838>] (__slab_free+0x38/0x2d0) [<c036d838>] (__slab_free+0x38/0x2d0) from [<bf00c014>] (slub_debug_exit+0x14/0x20 [slub_debug]) [<bf00c014>] (slub_debug_exit+0x14/0x20 [slub_debug]) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30) FIX my_slab_obj: Restoring 0xc71ed014-0xc71ed017=0x5a
修改代码如下:
static void mm_create(void) { myslabobj = kmem_cache_create("my_slab_obj", sizeof(struct slab_obj), 0, SLAB_HWCACHE_ALIGN, NULL); memblk = kmem_cache_alloc(myslabobj, GFP_KERNEL); memblk->aa = 0xabcd; memblk->bb = 0x1234; memblk->cc = 0x6879; int *p = &memblk->cc; p++; *p = 0x12345678; //slab_obj_t next_addr = memblk + 1; // next_addr->cc = 0xdeadbeef; }卸载模块时:
#rmmod slub_debug ============================================================================= BUG my_slab_obj (Tainted: G B O): Redzone overwritten ----------------------------------------------------------------------------- INFO: 0xc71bc00c-0xc71bc00f. First byte 0x78 instead of 0xcc INFO: Slab 0xc0666780 objects=128 used=1 fp=0xc71bcfe0 flags=0x0081 INFO: Object 0xc71bc000 @offset=0 fp=0xc71bc020 Object c71bc000: cd ab 00 00 34 12 00 00 79 68 00 00 ....4...yh.. Redzone c71bc00c: 78 56 34 12 xV4. Padding c71bc014: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ CPU: 0 PID: 656 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) from [<c00c7ee8>] (check_object+0x16c/0x240) [<c00c7ee8>] (check_object+0x16c/0x240) from [<c036cf18>] (free_debug_processing+0xc0/0x278) [<c036cf18>] (free_debug_processing+0xc0/0x278) from [<c036d838>] (__slab_free+0x38/0x2d0) [<c036d838>] (__slab_free+0x38/0x2d0) from [<bf010014>] (slub_debug_exit+0x14/0x20 [slub_debug]) [<bf010014>] (slub_debug_exit+0x14/0x20 [slub_debug]) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30) FIX my_slab_obj: Restoring 0xc71bc00c-0xc71bc00f=0xcc ============================================================================= BUG my_slab_obj (Tainted: G B O): Redzone overwritten ----------------------------------------------------------------------------- INFO: 0xc71bc00c-0xc71bc00f. First byte 0xcc instead of 0xbb INFO: Slab 0xc0666780 objects=128 used=0 fp=0xc71bc000 flags=0x0080 INFO: Object 0xc71bc000 @offset=0 fp=0xc71bcfe0 Object c71bc000: cd ab 00 00 34 12 00 00 79 68 00 00 ....4...yh.. Redzone c71bc00c: cc cc cc cc .... Padding c71bc014: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ CPU: 0 PID: 656 Comm: rmmod Tainted: G B O 3.10.28 #6 [<c0014ac0>] (unwind_backtrace+0x0/0xf4) from [<c00119d8>] (show_stack+0x10/0x14) [<c00119d8>] (show_stack+0x10/0x14) from [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) [<c00c7d60>] (check_bytes_and_report+0xbc/0xd8) from [<c00c7ee8>] (check_object+0x16c/0x240) [<c00c7ee8>] (check_object+0x16c/0x240) from [<c00c8cb0>] (__free_slab+0xf8/0x138) [<c00c8cb0>] (__free_slab+0xf8/0x138) from [<c00ca718>] (free_partial+0x84/0x200) [<c00ca718>] (free_partial+0x84/0x200) from [<c00ca8d4>] (__kmem_cache_shutdown+0x40/0xd4) [<c00ca8d4>] (__kmem_cache_shutdown+0x40/0xd4) from [<c00acf78>] (kmem_cache_destroy+0x60/0xf0) [<c00acf78>] (kmem_cache_destroy+0x60/0xf0) from [<c0066314>] (SyS_delete_module+0x124/0x210) [<c0066314>] (SyS_delete_module+0x124/0x210) from [<c000df40>] (ret_fast_syscall+0x0/0x30) FIX my_slab_obj: Restoring 0xc71bc00c-0xc71bc00f=0xbb
上面这些问题都是在 QEMU 下测试, 命令为:
sudo ./qemu-1.7.0/arm-softmmu/qemu-system-arm -M vexpress-a9 -kernel ./linux-3.10.28/arch/arm/boot/zImage -sd rootfs.img -hda vfat.img --append "root=/dev/mmcblk0 rw rootfs=ext3 rootdelay=3 physmap.enabled=0 console=ttyAMA0 console=tty0 slub_debug=PZ" -net nic,vlan=0 -net tap,vlan=0 -nographic -smp 4,sockets=1,cores=4
其中
slub_debug=PZ为 传递slub调试的参数。 P, Z等的意义如下:
F Sanity checks on (enables SLAB_DEBUG_FREE. Sorry SLAB legacy issues) Z Red zoning P Poisoning (object and padding) U User tracking (free and alloc) T Trace (please only use on single slabs) A Toggle failslab filter mark for the cache O Switch debugging off for caches that would have caused higher minimum slab orders - Switch all debugging off (useful if the kernel is configured with CONFIG_SLUB_DEBUG_ON)
1. Documentation/vm/slub.txt
2. http://lp007819.wordpress.com/2012/01/25/%E4%BD%BF%E7%94%A8slubslab%E7%9A%84%E8%B0%83%E8%AF%95%E5%8A%9F%E8%83%BD%E2%80%8F/