目录

1. Linux模块(LKM)简介
2. 使用Linux模块
3. LKM模块加载原理
4. LKM模块卸载原理
5. Monitor init_module syscall By Kprobe

 

1. Linux模块(LKM)简介

模块是一种向linux内核添加"设备驱动程序"、"文件系统"、"其他组件"的有效方法,而无须重新编译内核或重启系统,这消除了许多限制,同时带来了很多的优点

1. 通过使用模块,内核程序员能够预先编译大量驱动程序,而不会致使内核映像的尺寸发生膨胀。在自动检测硬件或用户提示后,安装例程会选择适当的模块并将其添加到内核中
2. 内核开发者可以将试验性的代码打包到模块中,模块可疑卸载,修改代码或重新打包后再重新加载,这使得可以快速测试新特性,无需每次都重启系统
3. 模块(LKM)可疑无缝地插入到内核中,同时模块也可以导出一些函数,可以由其他核心模块(以及持久编译到内核中的代码)使用。在模块代码需要卸载时,模块和内核剩余部分之间的关联会自动终止

Linux Kernel Module(LKM) Init、Delete Code Principle、Kprobe Hooking Principle Learning

0x1: 模块的依赖关系和引用

如果模块B使用了模块A提供的函数,那么模块A和模块B之间就存在关系,可以从两个方面来看这种关系

1. 模块B依赖模块A
除非模块A已经驻留在内核内存,否则模块B无法装载

2. 模块B引用模块A
除非模块B已经移除,否则模块A无法从内核移除,在内核中,这种关系称之为"模块B使用模块A"

"struct module_use"和"struct module->module_which_use_me"这两个结果共同组合和保证了内核模块中的依赖关系。
如果模块B使用了模块A提供的函数,那么模块A和模块B之间就存在关系,可以从两个方面来看这种关系

1. 模块B依赖模块A
除非模块A已经驻留在内核内存,否则模块B无法装载

2. 模块B引用模块A
除非模块B已经移除,否则模块A无法从内核移除,在内核中,这种关系称之为"模块B使用模块A"

对每个使用了模块A中函数的模块B,都会创建一个module_use结构体实例,该实例将被添加到模块A(被依赖的模块)的module实例中的modules_which_use_me链表中,modules_which_use_me指向模块B的module实例

Linux Kernel Module(LKM) Init、Delete Code Principle、Kprobe Hooking Principle Learning

我们在编写并加载LKM模块的时候,一定要注意模块间的依赖关系,有时候还需要分步骤单独进行指定模块的加载,才能保证模块间的依赖关系的正确连接

 

2. 使用Linux模块

0x1: 模块的添加

从用户的角度来看,模块可以通过以下两个"指令”进行添加

1. modprobe
它考虑了各个模块之间可能出现的依赖性(在一个模块依赖于一个或多个合作者模块的功能时),modprobe在识别出目标模块所依赖的模块之后,在内核也会使用insmod(即modprobe只是对insmod的一个包装)

2. insmod
insmod只加载一个单一的模块到内核中,且该模块只信赖内核中已经存在的代码(不管是通过模块动态加载的、还是持久编译到内核中的)

从内核系统的角度来看,模块的加载可以通过以下方法完成

1. init_module()
init_module()是一个系统调用,用户空间的工具只需要提供二进制数据,所有其他工作(重定位、解决引用问题)由内核自身完成

2. request_module()
request_module()不是系统调用,它用于从内核端加载模块,它不仅用于加载模块,还用于实现热插拔功能

0x2: 模块的移除

从用户的角度来看,模块可以通过以下"指令”进行删除

1. rmmod

从内核系统的角度来看,模块的卸载可以通过以下方法完成

1. delete_module()
delete_module()是一个系统调用,它用于从内核移除一个模块,前提是该模块代码不再使用,且其他模块也不再使用该模块导出的函数(即不能有依赖关系)

 

3. LKM模块加载原理

LKM模块的加载的大部分逻辑都在init_module()中,ring3的insmod、modprobe仅仅负责传递一个二进制数据,本文只关注init_module这个系统调用的代码逻辑,关于整个insmod模块加载过程的原理分析,请参阅

http://files.cnblogs.com/LittleHann/Modultils%E5%B7%A5%E5%85%B7%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E2%80%94%E2%80%94insmod%E7%AF%87.pdf

0x1: 代码流程

init_module()系统调用是用户空间和内核之间用于装载新模块的接口,它的大致流程如下

Linux Kernel Module(LKM) Init、Delete Code Principle、Kprobe Hooking Principle Learning

相关文章: