momo zone

调核人的blog

使用slub(slab)的调试功能‏

在日常开发工作中最容易发生的错误十有八九都是出在线性空间的操作方面。(这里指的线性空间可以认为等同于虚拟地址或虚拟内存,但其他场合并不一 定适用)

主要的问题体现在:
1. 访问了未初始化的线性空间。 这类问题还是相对比较容易发现,因为内核立即会告警并打印堆栈。
2. 释放了错误的线性空间,或者对某个线性空间进行了双重释放。这种情况如果测试充分也能被发现,但即使被发现也很难判定就是因为误释放线性空间而发生错误。 因为内核无法判断你要释放的线性空间是不是就是你要释放的,所以也不会有任何告警。如果测试过程中未被发现那么它将是埋在产品中的一颗定时炸弹, 也许连续run 几个小时内核就会挂掉,也许run 几天几十天才会挂掉。
3. 已分配的线性空间没有释放,其实就是常说的内存泄露,如果某个类型的内存对象很小,或者被分配的几率很低,这通常不是什么非常大的问题,尤其是在拥有海量 内存的系统上。如果情况不是这样,那么写代码的时候就要小心了,因为后续补救起来是件非常耗时和麻烦的工作。

使用slub(slab) API 并配合debug(posion 内存毒药)功能能够大幅降低上述问题的发生。

准备内核:

1. 如果分配器使用的是slab, kernel configuration:
CONFIG_SLAB=y
CONFIG_SLAB_DEBUG=y
CONFIG_DEBUG_SLAB_LEAK=y
CONFIG_DEBUG_SLABINFO=y
CONFIG_DEBUG_INFO=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y

2. 如果分配器使用的是slub 那么就简单了,无需重新编译内核,slub默认就内嵌了debug的相关代码,只不过这项功能默认是禁用的。
最好仍然增加如下kernel configuration:
CONFIG_DEBUG_SLABINFO=y
CONFIG_DEBUG_INFO=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y

启用方法:

个人仅使用过slub debug,下文均以slub分配器来说明:

1. 如果需要启用全局的slub debug 需要在内核启动参数中加入 slub_debug

2. 有时候在全局启用了debug后 内核消息输出会增加很多,对于debug 特定的slub(slab) 对象而言看起来很不方便,并大幅降低分配器的效率。 这种情况下可以选择特定的对象来调试,而且可以在内核运行时打开/关闭 调试对象,不需要重启。步骤如下:

#cat /proc/slabinfo

slabinfo – version: 2.1
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
fat_inode_cache       23    253    688   23    4 : tunables    0    0    0 : slabdata     11     11      0
fat_cache            102    204     40  102    1 : tunables    0    0    0 : slabdata      2      2      0
fuse_request          26     52    608   26    4 : tunables    0    0    0 : slabdata      2      2      0
fuse_inode             1     23    704   23    4 : tunables    0    0    0 : slabdata      1      1      0
kcopyd_job             0      0   3240   10    8 : tunables    0    0    0 : slabdata      0      0      0
dm_uevent              0      0   2608   12    8 : tunables    0    0    0 : slabdata      0      0      0
dm_rq_target_io        0      0    408   20    2 : tunables    0    0    0 : slabdata      0      0      0
ip6_dst_cache          7     25    320   25    2 : tunables    0    0    0 : slabdata      1      1      0
UDPLITEv6              0      0   1024   16    4 : tunables    0    0    0 : slabdata      0      0      0
UDPv6                 16     32   1024   16    4 : tunables    0    0    0 : slabdata      2      2      0
tw_sock_TCPv6          0     16    256   16    1 : tunables    0    0    0 : slabdata      1      1      0
TCPv6                 19     34   1856   17    8 : tunables    0    0    0 : slabdata      2      2      0
flow_cache             0      0    104   39    1 : tunables    0    0    0 : slabdata      0      0      0
cfq_queue            225    238    232   17    1 : tunables    0    0    0 : slabdata     14     14      0
bsg_cmd                0      0    312   26    2 : tunables    0    0    0 : slabdata      0      0      0
journal_handle       340    340     24  170    1 : tunables    0    0    0 : slabdata      2      2      0
journal_head          72    288    112   36    1 : tunables    0    0    0 : slabdata      8      8      0
revoke_record        256    256     32  128    1 : tunables    0    0    0 : slabdata      2      2      0
ext4_inode_cache   21466  21618    904   18    4 : tunables    0    0    0 : slabdata   1201   1201      0
ext4_free_data       146    146     56   73    1 : tunables    0    0    0 : slabdata      2      2      0
ext4_allocation_context    870    870    136   30    1 : tunables    0    0    0 : slabdata     29     29      0
ext4_io_end           58    319   1128   29    8 : tunables    0    0    0 : slabdata     11     11      0
ext4_io_page         516   1792     16  256    1 : tunables    0    0    0 : slabdata      7      7      0
ext3_inode_cache       0      0    792   20    4 : tunables    0    0    0 : slabdata      0      0      0
ext3_xattr             0      0     88   46    1 : tunables    0    0    0 : slabdata      0      0      0
arp_cache             36     36    448   18    2 : tunables    0    0    0 : slabdata      2      2      0
RAW                  461    475    832   19    4 : tunables    0    0    0 : slabdata     25     25      0
UDP                   38     38    832   19    4 : tunables    0    0    0 : slabdata      2      2      0
tw_sock_TCP           21     42    192   21    1 : tunables    0    0    0 : slabdata      2      2      0
TCP                   42    209   1664   19    8 : tunables    0    0    0 : slabdata     11     11      0
blkdev_queue          20     36   1816   18    8 : tunables    0    0    0 : slabdata      2      2      0
blkdev_requests       52    220    368   22    2 : tunables    0    0    0 : slabdata     10     10      0
sock_inode_cache     554    675    640   25    4 : tunables    0    0    0 : slabdata     27     27      0
net_namespace          1     12   2560   12    8 : tunables    0    0    0 : slabdata      1      1      0
shmem_inode_cache  11296  11448    656   24    4 : tunables    0    0    0 : slabdata    477    477      0
shared_policy_node  21143  22440     48   85    1 : tunables    0    0    0 : slabdata    264    264      0
numa_policy          203    210    136   30    1 : tunables    0    0    0 : slabdata      7      7      0
radix_tree_node     7248   8456    568   28    4 : tunables    0    0    0 : slabdata    302    302      0
idr_layer_cache      872    900    544   30    4 : tunables    0    0    0 : slabdata     30     30      0
dma-kmalloc-8192       0      0   8192    4    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-4096       0      0   4096    8    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-2048       0      0   2048   16    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-1024       0      0   1024   16    4 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-512        0     16    512   16    2 : tunables    0    0    0 : slabdata      1      1      0
dma-kmalloc-256        0      0    256   16    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-128        0      0    128   32    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-64         0      0     64   64    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-32         0      0     32  128    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-16         0      0     16  256    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-8          0      0      8  512    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-192        0      0    192   21    1 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-96         0      0     96   42    1 : tunables    0    0    0 : slabdata      0      0      0
kmalloc-8192          41     44   8192    4    8 : tunables    0    0    0 : slabdata     11     11      0
kmalloc-4096         109    120   4096    8    8 : tunables    0    0    0 : slabdata     15     15      0
kmalloc-2048         597    672   2048   16    8 : tunables    0    0    0 : slabdata     42     42      0
kmalloc-1024         787    864   1024   16    4 : tunables    0    0    0 : slabdata     54     54      0
kmalloc-512        10975  11088    512   16    2 : tunables    0    0    0 : slabdata    693    693      0
kmalloc-256         1439   1488    256   16    1 : tunables    0    0    0 : slabdata     93     93      0
kmalloc-128         1886   3232    128   32    1 : tunables    0    0    0 : slabdata    101    101      0
kmalloc-64         21988  23040     64   64    1 : tunables    0    0    0 : slabdata    360    360      0
kmalloc-32         20129  20992     32  128    1 : tunables    0    0    0 : slabdata    164    164      0
kmalloc-16          3341   3584     16  256    1 : tunables    0    0    0 : slabdata     14     14      0
kmalloc-8          22202  23040      8  512    1 : tunables    0    0    0 : slabdata     45     45      0
kmalloc-192        17809  17955    192   21    1 : tunables    0    0    0 : slabdata    855    855      0
kmalloc-96          6222   6342     96   42    1 : tunables    0    0    0 : slabdata    151    151      0
kmem_cache            32     32    256   16    1 : tunables    0    0    0 : slabdata      2      2      0
kmem_cache_node      153    192     64   64    1 : tunables    0    0    0 : slabdata      3      3      0

然后记下需要调试的对象名称(第一列)
echo 1 > /sys/kernel/slab/<对象名称>/poison

最后cat /sys/kernel/slab/<对象名称>/poison

如果显示为1 则说明针对此对象的debug poison 已经打开
注意:实际情况下并不是所有<对象名称>都可以在运行时开启/关闭debug poison 比如kmalloc-x

测试:

示例代码:

#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 mmbug_init(void){
mm_create();
return 0;
}

static void __exit mmbug_exit(void){
mm_destroy();
}

module_init(mmbug_init);
module_exit(mmbug_exit);

这段代码是没有内存方面的问题的,针对自定义的“slab_obj” 创建了slub  cache “my_slab_obj” 。由于是非内核数据结构,所以my_slab_obj不会在/proc/slabinfo 中新开一行,而是根据sizeof(struct slab_ojb) 的大小合并到kmalloc-8 。又因为kmalloc-8 不能在运行时开启debug poison ,所以只能启动时加内核参数slub_debug来开启。

1. 检测内存泄露:

在mm_destroy() 函数中把kfree(memblk); 注释掉 。 这样在模块卸载时调用到kmem_cache_destroy(myslabobj) 就会触发slub debug ,告警:

Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943251] =============================================================================
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943254] BUG my_slab_obj: Objects remaining on kmem_cache_close()
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943256] —————————————————————————–
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943256]
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943258] INFO: Slab 0xffffea000039f200 objects=24 used=1 fp=0xffff88000e7c9e30 flags=0x20000000004080
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943261] Pid: 4842, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943263] Call Trace:
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943269]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943272]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943275]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943279]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943283]  [<ffffffff8116e28f>] slab_err+0x8f/0xa0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943286]  [<ffffffff81173e9e>] list_slab_objects.constprop.65+0x5e/0x200
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943289]  [<ffffffff81174117>] free_partial+0xd7/0x110
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943291]  [<ffffffff81174270>] kmem_cache_destroy+0x120/0x230
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943296]  [<ffffffffa028f039>] mmbug_exit+0x39/0x1000 [mmbug]
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943300]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943304]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943311]  [<00007f0966db7b27>] 0x7f0966db7b26
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943314] INFO: Object 0xffff88000e7c8000 @offset=0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943317] INFO: Allocated in 0xffffffffa0005033 age=1316 cpu=1 pid=4841
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943319]       set_track+0x5d/0x1a0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943321]       alloc_debug_processing+0x8d/0xfb
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943322]       __slab_alloc.isra.60+0x20c/0x25b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943324]       kmem_cache_alloc+0x141/0x150
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943326]       0xffffffffa0005033
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943328]       do_one_initcall+0x3b/0x180
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943329]       sys_init_module+0x113/0x380
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943331]       system_call_fastpath+0x16/0x1b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943333]       0x7f491185cc8a
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943346] SLUB my_slab_obj: kmem_cache_destroy called for cache that still has objects.
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943348] Pid: 4842, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943350] Call Trace:
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943352]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943355]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943357]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943360]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943362]  [<ffffffff81174295>] kmem_cache_destroy+0x145/0x230
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943366]  [<ffffffffa028f039>] mmbug_exit+0x39/0x1000 [mmbug]
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943368]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943371]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:14:55 linux-9ffj kernel: [ 7880.943374]  [<00007f0966db7b27>] 0x7f0966db7b26

2. 检测错误释放线性空间(这里表现为重复释放):

在原来的kfree(memblk) 后面再加一个kfree(memblk) 进行重复释放,卸载模块时告警:

Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831862] =============================================================================
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831866] BUG my_slab_obj: Object already free
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831867] —————————————————————————–
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831868]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831875] INFO: Allocated in 0xffffffffa0005033 age=4621 cpu=1 pid=5196
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831879]       set_track+0x5d/0x1a0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831882]       alloc_debug_processing+0x8d/0xfb
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831884]       __slab_alloc.isra.60+0x20c/0x25b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831886]       kmem_cache_alloc+0x141/0x150
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831887]       0xffffffffa0005033
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831890]       do_one_initcall+0x3b/0x180
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831893]       sys_init_module+0x113/0x380
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831895]       system_call_fastpath+0x16/0x1b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831897]       0x7f569ec49c8a
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831899] INFO: Freed in mmbug_exit+0x10/0x1000 [mmbug] age=0 cpu=0 pid=5198
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831901]       set_track+0x5d/0x1a0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831903]       free_debug_processing+0x137/0x1a7
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831904]       __slab_free+0x2c/0x30b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831906]       kfree+0x140/0x170
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831907]       mmbug_exit+0x10/0x1000 [mmbug]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831909]       sys_delete_module+0x191/0x380
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831911]       system_call_fastpath+0x16/0x1b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831912]       0x7f41cf78bb27
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831913] INFO: Slab 0xffffea0001483e00 objects=24 used=0 fp=0xffff8800520f8000 flags=0x20000000004081
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831915] INFO: Object 0xffff8800520f8000 @offset=0 fp=0xffff8800520f9e30
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831916]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831917]   Object 0xffff8800520f8000:  6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5             kkkkkkkkkkk�
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831925]  Redzone 0xffff8800520f800c:  bb bb bb bb                                     ����
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831932]  Padding 0xffff8800520f8148:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831940] Pid: 5198, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831941] Call Trace:
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831945]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831948]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831951]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831954]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831957]  [<ffffffff8116f1cb>] print_trailer+0xfb/0x160
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831960]  [<ffffffff81663d49>] free_debug_processing+0x11a/0x1a7
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831962]  [<ffffffff81663e02>] __slab_free+0x2c/0x30b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831965]  [<ffffffff8116fed0>] kfree+0x140/0x170
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831968]  [<ffffffffa02c701c>] mmbug_exit+0x1c/0x1000 [mmbug]
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831971]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831974]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831977]  [<00007f41cf78bb27>] 0x7f41cf78bb26
Jan 16 14:20:15 linux-9ffj kernel: [ 8200.831979] FIX my_slab_obj: Object at 0xffff8800520f8000 not freed

注意最后一行的 “FIX” 他的意思是第二次释放无效,这样其实避免了内核panic的可能性。

3. 访问已释放的线性空间

对于写操作:
增加kfree后面的代码如下
memblk->aa=0xabcd;
memblk->bb=0x1234;
memblk->cc=0x8789;
卸载模块时告警:

Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313558] =============================================================================
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313562] BUG my_slab_obj: Poison overwritten
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313563] —————————————————————————–
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313564]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313565] INFO: 0xffff88000aace000-0xffff88000aace00a. First byte 0xcd instead of 0x6b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313572] INFO: Allocated in 0xffffffffa0005033 age=1607 cpu=1 pid=5369
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313577]       set_track+0x5d/0x1a0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313579]       alloc_debug_processing+0x8d/0xfb
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313581]       __slab_alloc.isra.60+0x20c/0x25b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313583]       kmem_cache_alloc+0x141/0x150
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313584]       0xffffffffa0005033
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313587]       do_one_initcall+0x3b/0x180
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313590]       sys_init_module+0x113/0x380
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313592]       system_call_fastpath+0x16/0x1b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313594]       0x7f3ce0bbbc8a
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313596] INFO: Freed in mmbug_exit+0x10/0x1000 [mmbug] age=0 cpu=1 pid=5370
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313598]       set_track+0x5d/0x1a0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313600]       free_debug_processing+0x137/0x1a7
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313601]       __slab_free+0x2c/0x30b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313603]       kfree+0x140/0x170
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313604]       mmbug_exit+0x10/0x1000 [mmbug]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313606]       sys_delete_module+0x191/0x380
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313608]       system_call_fastpath+0x16/0x1b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313609]       0x7f8e151a2b27
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313611] INFO: Slab 0xffffea00002ab380 objects=24 used=0 fp=0xffff88000aace000 flags=0x20000000004080
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313612] INFO: Object 0xffff88000aace000 @offset=0 fp=0xffff88000aacfe30
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313613]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313614]   Object 0xffff88000aace000:  cd ab 00 00 34 12 00 00 89 87 00 00             ͫ..4…….
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313622]  Redzone 0xffff88000aace00c:  bb bb bb bb                                     ����
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313629]  Padding 0xffff88000aace148:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313637] Pid: 5370, comm: rmmod Not tainted 3.1.0-1.5-yamu-kmem #2
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313639] Call Trace:
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313643]  [<ffffffff81005fd9>] try_stack_unwind+0x179/0x1a0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313646]  [<ffffffff81004857>] dump_trace+0x97/0x2e0
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313648]  [<ffffffff810060c8>] show_trace+0x58/0x70
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313652]  [<ffffffff8165cbe3>] dump_stack+0x72/0x7b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313655]  [<ffffffff8116f1cb>] print_trailer+0xfb/0x160
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313658]  [<ffffffff8116f356>] check_bytes_and_report+0x126/0x160
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313661]  [<ffffffff8116f852>] check_object+0x242/0x290
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313664]  [<ffffffff8116f9e4>] __free_slab+0x144/0x190
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313667]  [<ffffffff811740ed>] free_partial+0xad/0x110
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313670]  [<ffffffff81174270>] kmem_cache_destroy+0x120/0x230
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313673]  [<ffffffffa028f045>] mmbug_exit+0x45/0x1000 [mmbug]
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313676]  [<ffffffff810a6ae1>] sys_delete_module+0x191/0x380
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313679]  [<ffffffff81681f92>] system_call_fastpath+0x16/0x1b
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313682]  [<00007f8e151a2b27>] 0x7f8e151a2b26
Jan 16 14:26:02 linux-9ffj kernel: [ 8548.313684] FIX my_slab_obj: Restoring 0xffff88000aace000-0xffff88000aace00a=0x6b

同样最后的 “FIX” 指示第二次访问无效,内核不会panic。

对于读操作 不会出现告警,但如果用printk 打印这段地址,会输出多个字节的0x6b。看到这个就说明正在访问已经释放过的线性空间。

原理:

slub 实现poison debug 其实是简单的,正如刚才的debug 信息中所示slub(slab)会在恰当的时候放置单字节poison  0x6b  来占据实际分配的空间 ,并以单字节0xa5 结束。后续填充一定数量的单字节0xbb 作为Redzone (具体用意不明),最后还有单纯的填充字节0x5a 。 当发生重复释放,错误访问等情况时这些放置的“毒药”就会起作用,slab 也会采取措施纠正错误的操作。
有关内存毒药的字节定义可以查看 /lib/modules/$(uname -r)/build/include/linux/poison.h

其他说明:

尽管示例代码演示的是直接使用slab API 分配线性空间 ,但使用kmalloc来分配线性空间也可以配合slub(slab) debug ,因为kmalloc 实际分配的slab 对象是kmalloc-64 。不过因为无法使用kmem_cache_destroy这样的函数来释放slab cache 所以无法检测出内存泄露这样的问题。
如果操作线性空间分配与释放的层次不属于slub(slab) 而是位于伙伴系统(分页管理) 则需要开启page poison debug 。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s

%d 博主赞过: