深入了解Linux内存检测技术

本文深入探讨Linux内核中的内存检测技术,包括slub_debug、kmemleak和kasan。slub_debug用于内存小对象的调试,kmemleak检测内存泄露,kasan则是动态内存错误检查工具,支持检测越界访问、使用已释放内存等问题。文章通过实例展示了如何启用这些工具并分析测试结果。
摘要由CSDN通过智能技术生成

【推荐阅读】

浅谈linux 内核网络 sk_buff 之克隆与复制

深入linux内核架构--进程&线程

了解Docker 依赖的linux内核技术

Linux常见的内存访问错误有:

越界访问(out of bounds)

访问已经释放的内存(use after free)

重复释放

内存泄露(memory leak)

栈溢出(stack overflow)

不同的工具有不同的侧重点,本章主要从slub_debug、kmemleak、kasan三个工具介绍。

kmemleak侧重于内存泄露问题发现。

slub_debug和kasan有一定的重复,部分slub_debug问题需要借助slabinfo去发现;kasan更快,所有问题独立上报,缺点是需要高版本GCC支持(gcc 4.9.2 or gcc 5.0)。

测试环境准备

更新内核版本到Kernel v4.4,然后编译:

git clone https://github.com/arnoldlu/linux.git -b running_kernel_4.4 export ARCH=arm64 export CROSS_COMPILE=aarch64-linux-gnu- make defconfig make bzImage -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-

slub_debug

关键词:Red Zone、Padding、Object Layout。

Linux内核中,小块内存大量使用slab/slub分配器,slub_debug提供了内存检测小功能。

内存中比较容易出错的地方有:

访问已经释放的内存

越界访问

重复释放内存

编译支持slub_debug内核

首先需要打开General setup -> Enable SLUB debugging support,然后再选择Kernel hacking -> Memory Debugging -> SLUB debugging on by default。

CONFIG_SLUB=y CONFIG_SLUB_DEBUG=y CONFIG_SLUB_DEBUG_ON=y CONFIG_SLUB_STATS=y

测试环境:slabinfo、slub.ko

通过slub.ko模拟内存异常访问,有些可以直接显示,有些需要通过slabinfo -v来查看。

在tools/vm目录下,执行如下命令,生成可执行文件slabinfo。放入_install目录,打包到zImage中。

make slabinfo CFLAGS=-static ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

将编译好的slabinfo放入sbin。

下面三个测试代码:https://github.com/arnoldlu/linux/tree/running_kernel_4.4/test_code/slub_debug

在test_code/slub_debug目录下执行make.sh,将slub.ko/slub2.ko/slub3.ko放入data。

进行测试

启动QEMU:

qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -smp 2 -m 2048 -kernel arch/arm64/boot/Image --append "rdinit=/linuxrc console=ttyAMA0 loglevel=8 slub_debug=UFPZ" -nographic

F:在free的时候会执行检查。

Z:表示Red Zone的意思。

P:是Poison的意思。

U:会记录slab的使用者信息,如果打开,会会显示分配释放对象的栈回溯。

在slub_debug打开SLAB_STORE_USER选项后,可以清晰地看到问题点的backtrace。

测试结果

内存越界访问包括Redzone overwritten和Object padding overwritten。

重复释放对应Object already free。访问已释放内存为Posion overwritten。

Redzone overwritten

执行insmod data/slub.ko,使用slabinfo -v查看结果。

static void create_slub_error(void) { buf = kmalloc(32, GFP_KERNEL); if(buf) { memset(buf, 0x55, 80);-----------------------------------虽然分配32字节,但是对应分配了64字节。所以设置为80字节访问触发异常。从buf开始的80个字节仍然被初始化成功。 } }

虽然kmalloc申请了32字节的slab缓冲区,但是内核分配的是kmalloc-64。所以memset 36字节不会报错,将36改成大于64即可。

一个slub Debug输出包括四大部分:

BUG kmalloc-64 (Tainted: G O ): Redzone overwritten-------------------------------------------------------------1. 问题描述:slab名称-kmalloc-64,什么错误-Redzone overwritten。
-----------------------------------------------------------------------------

Disabling lock debugging due to kernel taint
INFO: 0xeddb3640-0xeddb3643. First byte 0x55 instead of 0xcc------------------------------------------------1.1 问题起始和结束地址,这里一共4字节。
INFO: Allocated in 0x55555555 age=1766 cpu=0 pid=771---------------------------------------------------------1.2 slab的分配栈回溯
0x55555555
0xbf002014
do_one_initcall+0x90/0x1d8
do_init_module+0x60/0x38c
load_module+0x1bac/0x1e94
SyS_init_module+0x14c/0x15c
ret_fast_syscall+0x0/0x3c
INFO: Freed in do_one_initcall+0x78/0x1d8 age=1766 cpu=0 pid=771-----------------------------------------1.3 slab的释放栈回溯
do_one_initcall+0x78/0x1d8
do_init_module+0x60/0x38c
load_module+0x1bac/0x1e94
SyS_init_module+0x14c/0x15c
ret_fast_syscall+0x0/0x3c
INFO: Slab 0xefdb5660 objects=16 used=14 fp=0xeddb3700 flags=0x0081-----------------------------------1.4 slab的地址,以及其它信息。
INFO: Object 0xeddb3600 @offset=1536 fp=0x55555555-----------------------------------------------------------1.5 当前Object起始,及相关信息

Bytes b4 eddb35f0: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ------------2. 问题slab对象内容。2.1 打印问题slab对象内容之前一些字节。
Object eddb3600: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 UUUUUUUUUUUUUUUU---------2.2 slab对象内容,全部为0x55。
Object eddb3610: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 UUUUUUUUUUUUUUUU
Object eddb3620: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 UUUUUUUUUUUUUUUU
Object eddb3630: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 UUUUUUUUUUUUUUUU
Redzone eddb3640: 55 55 55 55 UUUU----------------------------------------------------------------------------------2.3 Redzone内容,问题出在这里。
Padding eddb36e8: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ------------2.4 Padding内容,为了对象对齐而补充。
Padding eddb36f8: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ
CPU: 2 PID: 773 Comm: slabinfo Tainted: G B O 4.4.0+ #93--------------------------------------------------------3. 检查问题点的栈打印,这里是由于slabinfo找出来的。
Hardware name: ARM-Versatile Express
[] (unwind_backtrace) from [] (show_stack+0x10/0x14)
[] (show_stack) from [] (dump_stack+0x78/0x88)
[] (dump_stack) from [] (check_bytes_and_report+0xd0/0x10c)
[] (check_bytes_and_report) from [] (check_object+0x164/0x234)
[] (check_object) from [] (validate_slab_slab+0x198/0x1bc)
[] (validate_slab_slab) from [] (validate_store+0xac/0x190)
[] (validate_store) from [] (kernfs_fop_write+0xb8/0x1b4)
[] (kernfs_fop_write) from [] (__vfs_write+0x1c/0xd8)
[] (__vfs_write) from [] (vfs_write+0x90/0x170)
[] (vfs_write) from [] (SyS_wri
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值