Linux:如何突破内核模块验证的限制?

1、要解决的问题

Linux的内核模块(即ko文件)在编译时指定了可以运行在哪个内核版本。
例如,使用Ubuntu 16.04内核4.8.0-42-generic头文件编译的ko文件,只能运行这个内核版本中。

这就有个麻烦,Ubuntu内核版本更新速度非常快,如何内核更新为4.8.0-58-generic,那么这个ko文件就不能运行了,需要重新编译ko文件。

能否有简单的方法,让已有的ko文件运行不同的内核版本中呢?
有,本文介绍一种方法。

2、Linux内核是如何限制ko文件的执行?

ko文件运行在Linux内核中,运行时会调用Linux内核提供的接口。
由于Linux内核版本演进非常快,内核提供的接口可能经常发生变动。

为了保持Linux内核运行稳定,Linux采用的策略是:

  • 编译ko文件时,确定了它调用的所有Linux内核接口的版本。
  • 装载ko文件时,检查它调用的Linux内核接口版本,如果与当前Linux内核提供的接口版本完全致,则可以装载,否则拒绝装载。

2、内核接口版本是什么?

Linux内核为每个接口计算一个CRC整数值
例如:vfs_create 0xba70d5ae

编译ko时,针对是某个内核版本,把每个接口的CRC值都记录在ko文件中,即接口的版本信息。
装载ko时,与当前内核的接口CRC值进行比较,即接口版本比较。

参考:《Linux内核模块符号CRC检查机制》

3、修改ko文件中的CRC值能突破运行限制吗?

可以。

我在Ubuntu和CentOS上实验,通过修改ko文件中的接口CRC值,能够使之运行在不同的内核版本中。

4、如何实现呢?

Ubuntu和CentOS中有有相应的文本文件记录了指定版本内核的所有接口CRC值。

  • Ubuntu:/boot目录下有所有已安装版本的abi文件,例如abi-4.8.0-58-generic。
  • CentOS:/boot目录下前缀是symvers的文件。

只要把ko文件中所有使用的内核接口的CRC值改为与上述文件中的值,就能让ko文件运行了。

github上有一个开源程序能够修改ko文件的CRC值:
https://github.com/romeroperezabel/vermagic

我们可以修改这个程序,实现如下功能:

  • 列出ko文件调用的所有内核接口
  • 在记录CRC值的文件中,找到接口对应的CRC值
  • 修改ko文件中接口的CRC值

这样,ko文件就能运行在相应的内核版本中了。

5、注意

有可能修改成功,也有可能修改失败,例如新版本把某个接口取消了。
如果修改失败,就得重新编译ko文件了。

即使修改成功,也可能运行失败,严重的会导致系统无法启动,所以要特别注意,可以先在虚拟机上测试。
如果运行失败,也得重新编译ko文件了。

6、其它

最近遇到一个编译后ko文件无法运行的问题,解决方法如下。
repoline的问题:insmod一个简单ko,出现错误

猜你喜欢

转载自blog.csdn.net/ddk3001/article/details/80229418
今日推荐