modulename: loading out-of-tree module taints kernel

  • Post author:
  • Post category:其他




问题描述

使用

insmod

命令加载编写的驱动模块时,出现提示信息:

loading out-of-tree module taints kernel

。不过,模块还是能够被加载。并且卸载后再次加载时,该提示信息没有再次出现。然而整个系统重启后再加载模块,仍然会出现该提示信息。也就是说,在linux的一次运行期间,加载自己编写的驱动模块时,出现了上述提示信息。



原因分析

提示信息中的

taint



污染

的意思,整个提示信息的意思是

加载树外模块污染内核

。先简单说一下内核污染,当内核受到污染意味着内核

处于社区不支持的状态

,并且内核提供的某些功能可能会被禁用。此时,如果内核运行出现问题,内核开发者是不会理会的。

为什么要搞这样一个机制呢?简单点说,有一个对linux感兴趣的同学下载了kernel的源码并移植到自己的开发板上,然后自己写驱动,并加载到内核。之后的一个时间点,假如内核运行出现了问题,此时该同学是不应该向内核开发者反应问题的。因为很有可能内核本身没问题,而是这个同学自己写的驱动存在问题,导致了内核的崩溃。内核开发者仅仅只审核了位于内核源码树中的代码,因而只对源码树中的代码负责。换句话说,一个被污染的内核出现问题可能不是内核的bug;一个没有被污染的内核的错误报告更可能蕴含内核bug。有了这个机制,内核开发者就可以确定哪些错误报告是需要处理的,不然查半天发现不是自己的问题,这就耽误工夫了。

这里列部分内核被污染的原因:

  • 加载非GPL兼容的内核模块

  • staging

    驱动程序的使用,它们是内核源代码的一部分,但尚未经过全面测试
  • 使用内核源代码未包含的树外模块
  • 强制加载不是为当前内核版本构建的模块
  • 某些严重错误,例如

    machine check exceptions

    (MCE)和

    kernel oopses

显然,本文所述的内核被污染的原因是加载了树外模块,也就是加载自己写的驱动,不在内核源码树中。更多关于内核污染的信息,可以参考这个问答:

What is a tainted kernel in Linux?

现在,我们再来思考一个问题,内核是怎么知道这个模块是树外的?对此,有人讨论过:

Marking loadable kernel module as in-tree

。这里我简单总结一下,我们在编译驱动模块的Makefile中使用

M=$(PWD)

来指定驱动源码所在的目录,内核的顶层Makefile在检查到

M

非空时,会设置

KBUILD_EXTMOD

变量,最终导致内核的编译体系不会在

modulename.mod.c

中添加

MODULE_INFO(intree, "Y");

,也就是说不会给我们自己的驱动打上属于树内的

标记



解决方案

大多数情况下,我们可以忽略内核污染的情况,不能忽略的只是某些严重的系统问题导致的内核。事实上,尽管加载内核时会有上述提示,但终究成功加载了模块,驱动也能工作。

强迫症患者可能非要寻找一个解决方法,那么我们对症下药,可以使用这么几种解决方案:

  • 向内核提交patch,让内核的开发者将你的驱动并入内核源码树(对于只是学习驱动的情况,这个方法并不合适)
  • 自己把驱动程序拷贝到本地的源码树中,并自己添加相应的内核配置项,然后在树内编译驱动模块(保持

    M

    为空,这样做也挺麻烦的)
  • 自己在驱动源码种添加一句

    MODULE_INFO(intree, "Y");

    ,以欺骗内核本模块为树内模块(最好不要这么搞)

综上,强迫症患者还是忍忍吧,对于自己学习驱动从而产生一些树外模块的情况,忽略上述提示信息就可以了^_^!!

最后的最后,我看到网上有同学说这个跟模块的签名有关,但就我找到的资料来看,好像不是这么回事,毕竟当前我并未启用linux内核中的模块签名验证:

# CONFIG_MODULE_SIG is not set

既然提到了模块签名,就再丢一个链接:

Signed kernel module support

。这里对模块签名有更多的说明,感兴趣的同学可以去看看。



版权声明:本文为gzxb1995原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。