0%

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
2
3
4
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SLUB_DEBUG_ON=y
CONFIG_SLUB_STATS=y

修改了上述配置文件之后,需要重新编译内核并更新根文件系统。

添加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
2
3
4
5
6
<arch/arm64/configs/debian_defconfig>
CONFIG_HAVE_ARCH_KASAN=y
CONFIG_KASAN=y
CONFIG_KASAN_OUTLINE=y
CONFIG_KASAN_INLINE=y
CONFIG_TEST_KASAN=m

使用起来比较简单,不需要像slab_debug一样还有单独运行slabinfo程序。KASAN启动后会动态监测内存访问,如果出错会打印相关log信息。

KASAN总体效率比slub_debug要高得多,并且支持的内存错误访问类型更多。缺点是KASAN需要较新的内核(Linx4.4内核才支持ARM64版本的KASAN)和较新的GCC编译 器(GCC-4.9.2以上)。

参考文献

《奔跑吧Linux内核》