Linux内核Section Mismatch详解

by falcon [email protected] of TinyLab.org
2014/01/22

Section Mismatch简介

Section Mismatch是非常严重的Bug,可能会导致无法预测的内存访问问题,建议谨慎对待,如果添加的驱动中有类似Warning,可能需要密切关注并解决掉。

下面就该问题的检测、原因、解决思路以及最新前沿进行分析。

Section Mismatch的检测

CONFIG_DEBUG_SECTION_MISMATCH=y

打开上述选项,内核就会调用modpost检测类似问题。

Section Mismatch的原因

Linux为了减少不必要的内存消耗,对于一些仅仅在内核初始化时使用的资源(包括函数和变量等),会放在init sections中,这些init sections会在内核初始化完成以后被内核Free掉。除此之外,考虑到不同模块或者子系统的差异,它们的代码和数据也会放在各自的Section中,交叉的引用也可能出现潜在的问题。

如果一个Section引用了另外一个Section中的变量,就会出现Section Mismatch警告。如果是一个运行时函数引用了一个Init Section段中的函数,那么问题就出现了。

当Linux内核启动完成后,Init Section占用的内存已经被Free掉,如果这部分内存被其他的设备申请,写进了不可预知的内容,那么系统就会存在不可预知的风险,也许有些时候会很幸运,这部分内存从来都没有被其他设备引用,所以,即使编译时看到了Warning,系统也没有崩溃,但是炸弹放在枕头边,很危险,早点搬走为好。

Section Mismatch的解决

有几种情况:

  • 如果运行时函数引用了Init Section中的函数或者变量

如果该运行时函数是必须要在运行时用到的,不能放到Init Section中,那么就把Init Section中的函数的__init*标记去掉,否则给前者加上相应的Init声明。

相关的init标记请参考:include/linux/init.h

  • 如果不同的Section之间存在交叉引用,这个交叉引用是安全的,则用__ref标记让Section Mismatch Detector(modpost)忽略相关检查

比如在cpu hotplug中,__cpuinit不会放在Init section中,在运行时访问是安全的,如果有一个外部函数(无__cpuinit标记)访问了用__cpuinit标记的函数,这个时候就存在交叉引用。因为这种访问是安全的,所以可以让内核忽略对它的检测,用__ref标记该函数即可。

Section Mismatch的近况

在最新的ARM内核中,引入了一个智能检测,该检测是针对Free掉的内存被运行时函数访问的情况,前面的分析提到类似的情况会导致无法预测的风险,而该智能检测则会明确地报告出具体的问题。

该检测的原理是把所有Init Section的内存区域在内核初始化时把这些内存区域初始化为0xe7fddef0 (an undefined instruction (ARM) or a branch to an undefined instruction (Thumb)),如果运行时函数非法访问到了这些区域,会触发一个undef instruction的异常并打印相应的回调,从而辅助开发人员更快地解决相关问题。

当然,这并不意味着我们不需要解决编译时的Warning,把问题Delay到运行时解决是更耗费精力的,应该在编码或者编译等早期开发过程中就解决掉,这样会提高开发效率,这个思路对其他的问题同样适用。

这部分的代码请参考:arch/arm/mm/init.c: poison_init_mem()

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。