Linux 内核调试(二)内存检测
一般的内存访问错误如下。
- 越界访问(out-of-bounds)
- 访问已经被释放的内存(use after free)
- 重复释放(double free)
- 内存泄漏(memory leak)
- 栈溢出(stack overflow)
本节主要介绍 Linux 内核中常用的内存检测的工具和方法。
slub_debug
在 Linux 内核中,对于小块内存分配,大量使用 slab/slub 分配器。slab/slub 分配器提供了一个内存检测功能,很方便在产品开发阶段进行内存检查。内存访问中比较容易出现错误的地方如下。
- 访问己经被释放的内存
- 越界访问
- 释放己经释放过的内存
配置和编译内核
首先,需要重新配置内核选项,打开 CONFIG_SLUB、CONFIG_SLUB_DEBUG_ON 以及 CONFIG_SLUB_STATS 选项。
1 | # CONFIG_SLAB is not set |
修改了上述配置文件之后,需要重新编译内核并更新根文件系统。
添加 slub_debug 选项
在内核 commandline 中添加 slub_debug 字符串来打开该功能。
1 | -append "nointrd root=/dev/vda rootfstype=ext4 rw loglevel=8 slub_debug=UFPZ" \ |
编译 slabinfo 工具
在 Linux-5.0 内核的 tools/vm 目录下编译 slabinfo 工具。
1 | # gcc slabinfo.c -o slabinfo |
运行
加载驱动或运行程序,启动 slabinfo:
1 | $ slabinfo -v |
之后如果有内存越界访问就会有异常 log 输出。
KASAN 内存检测
KASAN 在 Linux4.0 内核中被合并到官方 Linux 内核,他是一个动态检测内存错误的工具,可以检查内存越界访问和使用已经被释放的内存等问题。Linux 内核早期有一个类似的工具 kmemcheck,KASAN 比 kmemeheck 的检测速度更快。要使用 KASAN,必须打开 CONFIG_KASAN 等选项。
1 | <arch/arm64/configs/debian_defconfig> |
使用起来比较简单,不需要像 slab_debug 一样还有单独运行 slabinfo 程序。KASAN 启动后会动态监测内存访问,如果出错会打印相关 log 信息。
KASAN 总体效率比 slub_debug 要高得多,并且支持的内存错误访问类型更多。缺点是 KASAN 需要较新的内核(Linx4.4 内核才支持 ARM64 版本的 KASAN)和较新的 GCC 编译 器(GCC-4.9.2 以上)。
参考文献
《奔跑吧 Linux 内核》