Linux 内存管理之 SLUB分配器(6):slub debug 实例测试
1. Object layout
slub object layout 之前已经有专门的一小节进行介绍了,这里直接将其结果拿来:
2. 配置开关
默认情况下上述的layout中debug信息是没有打开的,毕竟会增加太多的内容,增加内存的压力,所以需要打开如下部分内容:
-
Config:
CONFIG_SLUB=y
CONFIG_SLUB_DEBUG=y
CONFIG_SLUB_DEBUG_ON=y
CONFIG_SLUB_CPU_PARTIAL=y
-
kernel cmd:
bootargs 中添加slub_debug=UFPZ
这部分内容的目的就是打开debug开关,将我们申请的object配置为上述图示的样子
3. 实例测试
一般来讲我们常见的内存问题,主要包含如下几个类别:
- 内存越界
- 左侧越界
- 右侧越界
- 未申请内存即使用
- 释放后使用
- 重复释放
- 释放后使用
3.1 内存越界
任意找一个可以运行的驱动,申请一个buf,进行赋值即可:
分段分析运行结果:
-
错误类型提示打印:Redzone overwritten
(220110_11:38:07.257)[ 20.693618]<1>E=============================================================================
(220110_11:38:07.257)[ 20.693622]<1>EBUG kmalloc-128 (Tainted: G B ): Redzone overwritten
(220110_11:38:07.257)[ 20.693623]<1>E-----------------------------------------------------------------------------由于此case为越界检测,在object中实际分配空间的两侧,均被标记为redzone,所以这里看到的是 Redzone overwritten
-
问题object打印:First byte 0x23 instead of 0xcc
这里有告诉我们是哪一个object,地址和偏移是怎样的,发生了怎样的错误,这里是检测到应该为0xcc的数值被写为了0x23,所以认为发生了越界;
-
object layout的实际打印:
对比这张图来看:
很明确,左侧redzone被篡改
-
调用堆栈打印:
这里有两个点需要注意:
- 检测是在alloc或者free时进行,即我们篡改后当时是没有主动上报信息的;
- 检测到异常后会将该值修复,即将0x23修复为0xcc,并将信息打印;
以上即为内存越界,左侧越界的测试和信息打印;
3.2 重复释放
与上述测试相同,我们申请一块buf,释放两次,code如下:
测试结果与上述内存越界形式基本相同,在内容上有些许差异:
-
错误类型:Object already free
-
问题object打印:
-
object layout的实际打印:注意被释放后redzone中为bb,实际空间内容为6b
-
调用堆栈打印:
3.3 释放后使用
-
错误类型:Poison overwritten
-
问题object打印:被释放后object空间应该为0x6b,而这里我们将其修改为0x11,被检测到;
-
object layout的实际打印
-
调用堆栈打印:
上述几个case的话,基本上可以看到存在异常时的信息打印形式,其检测依据就是我们开篇的那个图,另外这里有个缺陷是相关检测都是在alloc和kfree时进行的,即在错误发生时并不会打印内容;
4. 核心API
检测逻辑:
会依次检测到slab、pointer、object,上述几个例子都是object的类型;
check object中即会依次检查red zone和poison