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);
1. 测试内存泄露:
注释掉 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)
2. double free
在 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);
}
卸载 模块的时候,log为:
#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
可以看到,第一次free的时候,内核填写的 特征字符 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
5. redzone 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;
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