动态模块加载异常
背景
动态模块加载,出现以下异常
1
| disagrees about version of symbol module_layout"
|
原理
kernel编译会生成vmlinux.symvers和Module.symvers两部分记录vmlinuz和模块的接口的symbol,动态模块编译时会生成xxx.mod.c,其中记录了动态模块用到的接口symbol,在加载模块时会去匹配接口的symbol是否和Module.symvers记录的一致,如果不一致,则提示错误。
分析
动态模块xxx.mod.c中的module_layout symbol
1 2 3 4 5 6
| static const struct modversion_info ____versions[] __used __section("__versions") = { { 0x97f53857, "module_layout" }, { 0x92997ed8, "_printk" }, { 0xbdfb6dbb, "__fentry__" }, };
|
内核vmlinux.symvers中的module_layout symbol
1
| 0x4709b79f module_layout vmlinux EXPORT_SYMBOL
|
内核Module.symvers中的module_layout symbol
1
| 0x97f53857 module_layout vmlinux EXPORT_SYMBOL
|
发现动态模块中的和Module.symvers的一致,但是和vmlinux.symvers的不一致,而每一次make bzImage都会导致vmlinux.symvers更新,不会去生成更新Module.symvers,导致Module.symvers symbol过旧,因此需要重新make modules
代码部分
实现逻辑见kernel/module.c ,通过CONFIG_MODVERSIONS来编译控制
1
| return check_version(info, "module_layout", mod, fsa.crc);
|
解决
- 第一种:make modules,重新动态模块编译
- 第二种:更新.config,删除CONFIG_MODVERSIONS
验证
插入模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| ➜ initramfs modinfo /github/busybox/initramfs/x86-busybox-rootfs/hello.ko filename: /github/busybox/initramfs/x86-busybox-rootfs/hello.ko license: Dual BSD/GPL srcversion: 89A8475A71641B4AAA82542 depends: retpoline: Y name: hello vermagic: 5.17.0+ SMP preempt mod_unload
➜ initramfs qemu-system-x86_64 -m 1024 -smp 2 -hda rootfs.img -kernel /github/busybox/initramfs/x86-busybox-rootfs/vmlinuz-5.17.0+ -s -append "root=/dev/sda rdinit=init crashkernel=128M console=ttyS0 rw" -nographic ... / # ./init
Boot took 15.51 seconds
/ # insmod hello.ko [ 22.306823] random: fast init done [ 22.322005] hello: loading out-of-tree module taints kernel. [ 22.323224] hello: module verification failed: signature and/or required key missing - tainting kernel [ 22.327473] Hello, world
/ # lsmod | grep -n "hello" 1:hello 16384 0 - Live 0xffffffffc00bb000 (OE) / # cat /proc/modules hello 16384 0 - Live 0xffffffffc0369000 (OE)
|
卸载模块
modprobe -r 会在/lib/module/$(uname -r) 下去寻找卸载的模块
1 2 3 4 5
| / # mkdir -p /lib/modules/5.17.0+ / # cd /lib/modules/5.17.0+ # /lib/modules/5.17.0+ # cp /hello.ko . # /lib/modules/5.17.0+ # modprobe -r hello [ 487.404929] Goodbey, cruel world
|