linux内核 · 2023年10月30日 0

RedHat自定义内核模块编译记录

自定义内核模块的编译与加载

不同环境下的编译

linux内核模块vermagic修改

在自己的内核编译环境下编译的内核模块,需要加载到其他环境的内核中时,insmod报错“Invalid module format”

运行一下cat /var/log/messages dmesg查看详细信息:

可以看到是version magic不匹配导致的。

在编译内核树下修改下面的信息:

1、./include/config/kernel.release

2、./include/generated/utsrelease.h

3、./include/linux/vermagic.h

4、./Makefile

根据需要修改为对应目标的版本号即可。

编译模块所在的目录:

make -C ./ M=./drivers/char/ modules

查看模块信息:

modinfo ./drivers/char/hello.ko

可以看到已经修改成功了。

现在加载到目标内核中不会报错“Invalid module format”了,但是3.7后的内核可能会加入模块签名校验机制,在编译内核时可以选择是否开启:

而RedHat7.9刚好就开了这个校验,加载模块报错:

在目标系统下编译

redhat7.9下编译自定义内核模块

在目标系统(Redhat7.9)下编译对应目标内核的模块。

安装依赖(yum源替换方法见这里):

yum install kernel-devel-$(uname -r) gcc elfutils-libelf-devel

创建测试文件:

mkdir /home/admin/test
vi /home/admin/test/test.c

#include <linux/module.h>

#include <linux/kernel.h>

int init_module(void)

    { printk("Hello World\n This is a test\n"); return 0; }

void cleanup_module(void)

    { printk("Good Bye World"); }

MODULE_LICENSE("GPL");

创建Makefile文件:

vi /home/admin/test/Makefile
obj-m := test.o

编译内核模块,注意内核目录和模块目录都用绝对路径:

make -C /lib/modules/$(uname -r)/build M=/home/admin/test modules

把编译好的ko文件复制到/lib/modules/$(uname -r)/目录下:

cp /home/admin/test/test.ko /lib/modules/$(uname -r)/

更新模块依赖项列表:

depmod -a

载入内核模块,-f选项强制载入模块:

modprobe -v -f test

列举已加载的模块:

lsmod

dmesg查看输出:

如果直接用insmod加载模块的话会报错:

说是没有对应的符号文件,如果用modprob 不带-f参数也是类似的报错:

尝试了把/usr/src/kernels/3.10.0-1160.el7.x86_64/Module.symvers 文件复制到test目录下,仍有相同的报错出现。

除非是重新编译整个内核,否则没法消除这个报错。

那么还是认定用下面的命令来加载吧:

modprobe -v -f test

卸载模块使用:

modprobe -r test

从内核源码编译

安装包:

yum install mock
yum install rpm-build

安装完后会创建/root/rpmbuild/SPECS目录,运行命令安装源码树:

rpmbuild -bp --tartget=$(uname -m) kernel.spec

提示缺失下面的依赖包,yum安装即可:

yum install m4 net-tools xmlto  asciidoc hmaccalc python-devel newt-devel perl pesign elfutils-libelf-devel elfutils-devel binutils-devel bison audit-libs-devel java-devel numactl-devel pciutils-devel ncurses-devel python-docutils flex

安装完后进入源码树,重新编译内核:

cd /root/rpmbuild/BUILD/kernel-3.10.0-1160.el7/linux-3.10.0-1160.el7.x8
make menuconfig
make -j2

之后就能用这个源码树来编译内核模块了。

Makefile:
obj-m += test.o

KERNEL_PATH:=/root/rpmbuild/BUILD/kernel-3.10.0-1160.el7/linux-3.10.0-1160.el7.x86_64

all:

make -C $(KERNEL_PATH) M=$(shell pwd) modules

clean:

make -C $(KERNEL_PATH) M=$(shell pwd) clean

可直接insmod模块,虽然会报错没过签名验证,但能正常执行: