Linux kernel slub debug

本文介绍了Linux内核slub调试机制,用于检测设备驱动中的内存问题,如内存泄漏、越界访问、双重释放等。slub通过在内存对象周围设置红色区域来监控异常访问,并在内存释放后检查是否被非法使用。当遇到问题时,可以使用slabinfo工具进行即时检查。文章还提供了一些使用slub调试的实际例子,帮助开发者定位和修复内存错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在device driver开发的过程中,有时候会碰到memory相关的问题,比如memory leak,use after free,out of boundary,double free等等。因为device driver运行在kernel环境,kernel是一个global的runtime,driver分配或者释放的memory都是由kernel负责管理,而且所有的device driver,kernel sub system共享这些memory,一旦device driver使用memory不当,就会导致整个kernel的memory管理出现问题。举个简单的例子,比如device driver写buffer发生了越界,那就可能把别人的memory写坏,如果正巧kernel或者别的driver正在使用这块memory,那就立刻会发生oops,或者kernel panic;如果不够幸运,被写坏的memory目前没人在用,而是将来的某个时刻才触发oops或者kernel panic,那就非常麻烦了,因为stack是当前正在运行的上下文的stack,真正的锅应该由写坏别人buffer的driver来背。

kernel中提供了这样一种机制,当访问memory出现问题时,通过记录的track,找到始作俑者,这个机制就是slub debug。

碰巧,最近测试unbind driver的时候,碰到了几个memory相关的问题,比如use after free,double free,甚至是free了栈里的memory :(,unbind driver是要把driver之前分配的所有resource全部释放,中间就会涉及到大量的memory free的操作,自然容易出现问题。

slub debug的实现原理很简单,就是在要分的memory周围放上围栏,正常的memory访问都只会集中在memory object里面,不可能在外面,这样只要监视memory object周围的读写,就能发现不正常的memory访问,尤其是oob,也就是out of boundary,越界访问,这个围栏就是red zone。此外,为了检查use after free,kernel把当前未被使用的object里的内容全部填成特殊值,一旦发现有人在没有分配的情况下,写了object的值,就会报错,从而发现肇事者。

下面介绍slub debug的使用方法,因为debug功能默认是关闭的,所以使用slub debug之前要build kernel。

1. 先下载kernel的source code,可以直接下载kernel official的code

2. 修改config,把自己机器里的config copy到kernel code根目录下,重命名为.config,然后make menuconfig

Kernel hacking -> Memory debugging -> Slub debugging on by default

General setup -> Enable SLUB debugging support

3. build kernel,推荐使用如下命令:

 export DEB_BUILD_OPTIONS='nostrip noopt debug'
 make -j8 bindeb-pkg LOCALVERSION=-debug

这样可以build出来linux headers,Linux image和linux kenrel symbol,这些debug用都是需要的。

4,安装刚刚build 出来的kernel,然后就可以安装driver运行了。

slub可以检测到double  free,out of boundary等,但是并不是实时的,最开始的时候并不知道,所以当看到slub的call stack时一脸懵逼,这stack压根就不是现在跑的啊。没办法,slub的debug就是有它先天的滞后性,因为它是在free memory的时候去检查,而且不是free完马上去检查,而是等到后面有人再去使用的时候才检查,这就导致看不到出问题的现场。针对这个问题,kernel提供了自己的解决办法-slabinfo,这是kernel自己提供的工具,code在tools/vm下,通过slabinfo -v,可以马上对memory进行检查,一旦发现问题,立即打印,这就要求driver developer知道memory是在哪个阶段出现问题的,才能有针对性的使用slub debug。

所以,我一般在怀疑有可能出现问题的时候,手动运行一次slabinfo -v检查当前所有的slab object,下面看几个例子。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/slab.h>

static int oob(void)
{
    char *buf = kmalloc(8, GFP_KERNEL);

    printk(KERN_INFO "test oob.\n");

    //这里写越界,分了8个byte,写了第9个byte
    buf[8] = 'a';

    kfree(buf);

    return 0;
}

static int __init hello_init(void)
{
    printk(KERN_INFO "module init.\n");

    oob();

    return 0;
}

static void hello_exit(void)
{
    printk(KERN_INFO "module exit.\n");
}


module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

在insmod这个module之后,手动执行slabinfo -v,在dmesg中就可以看到log了:

[  204.459596] module init.
[  204.462197] test oob.
[  204.464700] =============================================================================
[  204.473065] BUG kmalloc-8 (Tainted: P           OE    ): Redzone overwritten
[  204.480077] -----------------------------------------------------------------------------

[  204.489899] INFO: 0x00000000e7a736f4-0x00000000e7a736f4. First byte 0x61 instead of 0xcc
[  204.498151] INFO: Allocated in hello_init+0x2c/0x1000 [hello] age=0 cpu=3 pid=2120
[  204.505695] 	__slab_alloc+0x20/0x40
[  204.509308] 	kmem_cache_alloc_trace+0x238/0x270
[  204.513898] 	hello_init+0x2c/0x1000 [hello]
[  204.518199] 	do_one_initcall+0x52/0x1d7
[  204.522081] 	do_init_module+0x5f/0x221
[  204.525799] 	load_module+0x2697/0x2b30
[  204.529524] 	__do_sys_finit_module+0xe5/0x120
[  204.534063] 	__x64_sys_finit_module+0x1a/0x20
[  204.538428] 	do_syscall_64+0x5a/0x110
[  204.542140] 	entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  204.547264] INFO: Slab 0x000000003ae1cdd1 objects=23 used=2 fp=0x000000001974d745 flags=0x17ffffc0008101
[  204.556900] INFO: Object 0x000000003fa16067 @offset=1384 fp=0x          (null)

[  204.565545] Redzone 00000000c5553bcc: cc cc cc cc cc cc cc cc                          ........
[  204.574360] Object 000000003fa16067: 6b 6b 6b 6b 6b 6b 6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值