可装载内核模块-Loadable Kernel Module (LKM)

2023-05-16

0x01 可装载模块分类
设备驱动
文件系统
系统调用

0x02 版本检查
Linux 的迅速发展致使相邻版本的内核之间亦存在较大的差异,即在版本补丁号(Patch Level,即内核版本号的第四位数)相邻的内核之间。为此 Linux 的开发者为了保证内核的稳定,Linux 在加载模块到内核时对模块采用了版本校验机制。

1,Invalid module format -> disagrees about version of symbol module_layout
由于模块中 module_layout 的导出符号的版本信息与当前内核中的不符
函数 module_layout 的第二个参数 ver 存储了模块的版本校验信息。结构体 modversion_info 中保存了用于模块校验的 CRC(Cyclic Redundancy Check,即循环冗余码校验)值

2,Linux 对可装载模块采取了两层验证:模块的 CRC 值校验和 vermagic 的检查
CRC 值校验针对模块(内核)导出符号,是一种简单的 ABI(即 Application Binary Interface)一致性检查(1中的disagrees about version of symbol module_layout 就有由于没有通过 CRC 值校验,即 module_layout 的 CRC 值与当前内核中的不符)

模块 vermagic(即 Version Magic String)则保存了模块编译时的内核版本以及 SMP 等配置信息3,模块的 vermagic 信息

# uname – r
2.6.38-10-generic

# modinfo ./hello/hello.ko
filename: ./hello/hello.ko
license: Dual BSD/GPL
srcversion: 31FE72DA6A560C890FF9B3F
depends:
vermagic: 2.6.38-9-generic SMP mod_unload modversions

4,modversion保存位置
通常,内核与模块的导出符号的 CRC 值被保存在文件 Module.symvers 中,该文件需在开启内核配置选项 CONFIG_MODVERSIONS 之后并完全编译内核获得
或者也可在编译外部模块后获得该文件,保存的是模块的导出符号的 CRC 信息

5,校验
Linux 内核在进行模块装载时先完成模块的 CRC 值校验,再核对 vermagic 中的字符信息
从用户空间装载模块到内核时,Linux 还对用户权限进行了检查。模块的装载须是获得 CAP_SYS_MODULE 权限的超级用户,这正是模块装载时最先检查的内容


6,module版本信息保存在ko文件的哪里?
Linux 使用 GCC 中的声明函数属性 attribute 完成对模块的版本信息附加。构建的模块存在几个 section,如 .modinfo、.gnu.linkonce.this_module 和 __versions 等,这些 ELF 小节(即 section)保存了模块校验所需的信息(关于这些 section 信息的附加过程,您可查看模块构建时生成的文件 .mod.c 及工具 modpost
模块 CRC 值校验查看的是就是模块 __versions 小节的内容,即是附加的 struct modversion_info 信息
模块的 CRC 校验过程在函数 setup_load_info 中完成
Linux 使用 .gnu.linkonce.this_module 小节来解决模块对 struct module 信息的附加
模块 vermagic 信息则被保存在了 ELF 的 .modinfo 小节中7,vermagic与内核版本号
vermagic 信息来自内核头文件 include/linux/vermagic.h 中的宏 VERMAGIC_STRING,其中宏 UTS_RELEASE 保存了内核版本信息。与其关联的头文件 include/generated/utsrelease.h 需经内核预编译生成,即通过命令 make 或 make modules_prepare 等

/* kernel/module.c */
static const char vermagic[] = VERMAGIC_STRING;

/* include/linux/vermagic.h */
#define VERMAGIC_STRING \
UTS_RELEASE ” ” \
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \
MODULE_ARCH_VERMAGICLINE

0x03 装载与卸载
在 Linux 2.6 中,工具 insmod 被重新设计并作为工具集 module-init-tools 中的一个程序,其通过系统调用 sys_init_module(您可查看头文件 include/asm-generic/unistd.h)衔接了模块的版本检查,模块的装载等功能

0x04 编译时的版本信息添加
1,.mod.c
文件 .o 是模块代码(即 .c 文件)经编译后获得的目标文件,文件 .mod.o 则对应文件 .mod.c。文件 [module].mod.c 是对 [modulue].c 的扩展,清单展示了文件 kobject-example.mod.c 的内容 ( 即模块 kobject-example.ko 的 .mod.c 文件 ),可见到与模块版本检查相关三个小节:

# cat ./kobject/kobject-example.mod.c
…

MODULE_INFO(vermagic, VERMAGIC_STRING);

struct module __this_module
attribute((section(“.gnu.linkonce.this_module”))) = {
…
};

static const struct modversion_info ____versions[]
__used
attribute((section(“__versions”))) = {
…
};

static const char __module_depends[]
__used
attribute((section(“.modinfo”))) =
“depends=”;

MODULE_INFO(srcversion, “B06F9B8B7AB52AEED247B9F”);

2,ko来自.o与.mod.o
.ko 的附加信息合并自文件 .o 与文件 .mod.o。内核工具 modpost 完成了一这步骤

3,内核版本号在哪里?
经上述,我们可知内核树的顶层 Makefile 文件包含了内核版本的信息,且该信息经编译后被添加到模块的(头文件 include/generated/utsrelease.h 保存的内核版本信息来自顶层 Makefile)

4,/proc/modules
lsmod 打开文件 /proc/modules 查询当前内核中已装载的模块,文件 /proc/modules 还被 rmmod 在卸载模块时使用

5,模块CRC信息生成
Linux 2.6 构建模块时工具 modpost 被 scripts/Makefile.modpost 调用,生成 [module].mod.c 及文件 Module.symvers。在开启内核选项 CONFIG_MODVERSIONS 之后,文件 Makefile.Build 会调用工具 genksyms(现位于内核树 scripts/genksyms 目录下,在 Linux 2.4 时是模块工具集 Modutils 的一部分)生成 CRC 信息

0x05 模块的构建与测试
1,预编译内核模块
# make menuconfig
# make modules_prepare

2,使内核支持模块的版本检查

CONFIG_MODULES=y
CONFIG_MODVERSIONS=y

另须注意的是,模块预编译并不生成 Module.symvers 文件,即使开启了 CONFIG_MODVERSIONS 选项。因此最好的方式是完全编译 Linux 内核
————————————————
版权声明:本文为CSDN博主「萝卜2305」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/luobo2305/article/details/50899372

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可装载内核模块-Loadable Kernel Module (LKM) 的相关文章

随机推荐

  • golang之路--时间格式化

    有人问了问go的时间格式化问题 xff0c 于是乎自己尝试了下 xff0c 发现巨坑爹 xff0c 不按常理出牌啊 format的竟然模版必须如下面的每个数字 fuck t 61 time Unix 1362984425 0 nt 61 t
  • 生产者消费者模式C++程序模拟实现

    关于生产者和消费者的分析可以参考 xff1a http blog csdn net kenden23 article details 16340673 这里是利用C 43 43 简单模拟一个生产者消费者的工作模式 没有考虑到同步问题 操作了
  • Active MQ C++实现通讯

    Active MQ C 43 43 实现通讯 Kagula 2011 9 13 简介 在参考资料 2 的基础上介绍如何用C 43 43 调用Active MQ的客户端API 环境 xff1a 1 Windows XP SP3 2 Visua
  • OA工作流设计思路——请大神点评啊

    lt p gt OA工作流设计思路 请大神点评啊 xff0c 很多可能想的不是很到位 lt p gt lt p gt 此设计思路暂时没有包含详细的设计 xff0c 就是一个方向 xff0c 请大神指正下 xff0c 然方案更加完善 xff0
  • 解决Spring AOP 事务 配置 失效原因

    采用AOP配置声明式事务有5种方式 xff0c 下面只说关于采用TransactionInterceptor事务拦截器的方式 xff0c 配置程序如下 xff1a transactionManager xff1a lt bean id 61
  • 兼容chrome与firefox使用offsetWidth得到不同值的问题

    Ext3 x Ext MessageBox alert 在chrome与firefox显示的宽度不一致问题 究其原因是因为msgEl getWidth 得到的值不一致导致的 修正宽度应方法 xff1a chrome xff1a rect 6
  • 内嵌标志表达式

    对应的内嵌标志表达式是 i xff0c 它有四种形式 xff1a 1 xff0c i 2 xff0c i 3 xff0c i X 4 xff0c i X 不带有 的是开标志 xff0c 带有 的是关标志 把上面的代码改成这样 xff1a J
  • LoadRunner 90 Percent设置

    90 Percent 的设置 xff1a tools xff08 工具 xff09 options xff08 选项 xff09 General选项卡最下面有个Summary Report
  • 高通8155平台YOCTO CMAKE 编译问题解决方法

    硬件平台 xff1a 高通8155 软件平台 xff1a yocoto linux 43 ubuntu16 04 最近开始接触8155平台 xff0c 发现编译阶段出现cmake编译失败 xff0c 网上搜了一下没有相关的解决方案 xff0
  • 解决Ext.Grid单元格不能被选择

    ExtJs3 x版本 xff0c Ext grid GridPanel单元格数据不能被选择 xff0c 在不同浏览器环境下的解决方法不同 xff1a 1 Chrome Safari xff1a ext webkit x grid panel
  • Hadoop-1.2 单机部署

    准备相关资源环境 运行环境工具 Linux Centos 6 3 JDK 1 7 0 51 SSH Secure Shell 1 下载Hadoop1 2 http mirrors cnnic cn apache hadoop common
  • Hbase-0.94.19 单机部署

    准备相关环境 运行环境工具 Linux Centos 6 3 JDK 1 7 0 60 Hadoop 1 2 1 SSH Secure Shell Hbase需建立在Hadoop环境之上运行 xff0c 参考Hadoop1 2 1单机部署
  • Android Beam:引领未来的NFC数据交换

    还记得吗 xff1f 惠普曾经将TouchPad平板电脑与Pre 3接触就实现了网页交换 也许那时大家都在想 xff1a 太酷啦 xff0c 要是我有TouchPad和pre3就好了 昨天新发布的Android 4 0Ice Cream S
  • TabHost设置选项卡被选中时背景颜色

    TabHost设置选项卡被选中时背景颜色 xff0c 通过给每个选项卡的Button设置背景样式实现 文件名 xff1a bottom btn first bg billboard xml 内容如下 xff1a lt xml version
  • 如何从文件中检索关键字出现的次数

    首先得到文件的完整路径 然后从流中读取每个字符 如果读出的字符和关键字的第一个字符相同 xff0c 则按照关键字长度读取相同个数的字符 分别判断是否相同 xff0c 若有一个不相同则break 否则计数器count 43 43 xff0c
  • 被其他Activity覆盖不触发onStop的情况

    被其他Activity覆盖不触发onStop的情况 xff1a 一般情况下当一个Activity被其他Activity覆盖时 被覆盖的Activity都会调用onStop xff08 xff09 方法 但是有两种情况除外 一个是上层Acti
  • 如何找到一个数组中第三大数字并输出它所在的位置

    面试题 如何找到一个数组中第三大数字并输出它所在的位置 延伸问题 xff1a 如何找到一个数组中第N大元素并输出它所在的位置 br public class FindThirdLarge br public static void getT
  • 输出出一个数组中出现次数最多的数字以及它出现的次数

    查找一个数组中出现次数最多的数字以及它出现的次数并输出出来 br public class FindMostAppearTime br public static void getMostAppearNumber int array br
  • Activity的四种启动模式

    color 61 red Standard color 默认启动模式 标准模式 每次启动Activity都会创建新的Activity对象实例 color 61 red SingleInstance color 只要在当前应用中启动过该Act
  • 可装载内核模块-Loadable Kernel Module (LKM)

    0x01 可装载模块分类 设备驱动 文件系统 系统调用 0x02 版本检查 Linux 的迅速发展致使相邻版本的内核之间亦存在较大的差异 xff0c 即在版本补丁号 xff08 Patch Level xff0c 即内核版本号的第四位数 x