linux module

Linux内核模块

内核模块的一些基本概念

内核模块是实现某一个功能的一段内核代码,这段代码可以在内核的运行过程中动态加载到内核,从而增加内核功能。这段代码可以单独编译,不用对整个内核重新进行编译。内核模块不能独立运行, 在运行时它被链接到内核作为内核的一部分在内核空间运行。编译好的模块在本质上是一个elf可重定位文件,后缀名为.ko。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
myslqyr@myslqyr-ubuntu:~/Desktop/module$ readelf -h hello.ko
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 176672 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 48
Section header string table index: 47

一个简单的内核模块示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("myslqyr");
MODULE_DESCRIPTION("A simple hello world kernel module");
MODULE_VERSION("1.0");

static int __init hello_init(void)
{
printk(KERN_INFO "Hello World kernel module loaded.\n");
return 0;
}

static void __exit hello_exit(void)
{
printk(KERN_INFO "Hello World kernel module unloaded.\n");
}

module_init(hello_init);
module_exit(hello_exit);

makefile如下:

1
2
3
4
5
6
7
8
9
10
obj-m += hello.o

DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
make -C $(DIR) M=$(PWD) modules

clean:
make -C $(DIR) M=$(PWD) clean

sudo insmod hello.ko可以加载模块,sudo rmmod hello卸载模块。

内核模块签名

大多数发行版在编译内核时没有添加CONFIG_MODULE_SIG_FORCE这个内核配置项,这个配置项用于检查内核模块的签名。如果内核模块的签名无效,内核将拒绝加载该模块。大部分的电脑也默认没有使用uefi security boot,开启security boot也会强制模块签名。当强制开启内核模块签名时,会拒绝加载没有签名或者签名预期值不符的模块。

1
2
3
4
5
6
7
cat /boot/config-$(uname -r) | grep MODULE_SIG
...
CONFIG_MODULE_SIG=y
# CONFIG_MODULE_SIG_FORCE is not set
...
mokutil --sb-state
SecureBoot disabled

内核模块签名的流程

首先生成一对公钥和私钥。

1
2
3
4
5
6
openssl req -new -x509 -newkey rsa:2048 \ #生成自签名证书 -new:创建新请求 -x509:输出 X.509 格式证书  -newkey:生成新密钥对  rsa:2048:使用rsa算法密钥长度2048bit
-keyout MOK.key \
-out MOK.crt \
-nodes \ #生成不加密私钥
-days 36500 \
-subj "/CN=My Kernel Module Signing/"

然后对hello.ko进行签名。签名工具使用的是/usr/src/linux-headers-$(uname -r)/scripts/sign-file。

1
2
3
4
5
/usr/src/linux-headers-$(uname -r)/scripts/sign-file \
sha256 \
MOK.key \
MOK.crt \
hello.ko

这时候我们运行modinfo hello.ko可以看到hello.ko带上了签名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
modinfo hello.ko
filename: ?
version: 1.0
description: A simple hello world kernel module
author: myslqyr
license: GPL
srcversion: D98FC66A28194B60CF68194
depends:
name: hello
retpoline: Y
vermagic: 6.14.0-33-generic SMP preempt mod_unload modversions
sig_id: PKCS#7
signer: My Kernel Module Signing
sig_key: 2E:65:EA:52:3B:75:...
sig_hashalgo: sha256
signature: 13:87:A6:A7:6C:32:...

之后要给内核导入公钥。

1
2
openssl x509 -in MOK.crt -outform DER -out MOK.der #将公钥从PEM格式转换成DER格式
sudo mokutil --import MOK.der #将公钥导入内核(应该是先写入uefi)

linux module
http://example.com/2026/05/13/linux module/
作者
myslqyr
发布于
2026年5月13日
许可协议