必须同时启用内核编译选项config_module_sig_force=y和启动参数module.sig_enforce=1,缺一不可;仅改grub参数而内核未编译进该选项时,会静默降级为非强制模式,仅打taint标记而不阻止未签名模块加载。

必须在内核启动参数中加 module.sig_enforce=1,且内核本身要编译进 CONFIG_MODULE_SIG_FORCE=y,二者缺一不可。
为什么只改 GRUB 参数还不够
很多用户改完 /etc/default/grub 加上 module.sig_enforce=1 并 update-grub 后仍能加载未签名模块——根本原因是当前运行的内核没启用强制签名支持。该参数只是“开关”,不是“功能补丁”。内核必须在编译时打开 CONFIG_MODULE_SIG_FORCE,否则启动时会忽略 module.sig_enforce=1 并静默降级为普通验证模式(即仅打 taint 标记)。
验证方式:zcat /proc/config.gz | grep CONFIG_MODULE_SIG_FORCE(若不可用,查 /boot/config-$(uname -r))。输出应为 CONFIG_MODULE_SIG_FORCE=y。
如何确认内核已支持并启用强制模式
- 检查内核配置:运行
grep "CONFIG_MODULE_SIG_FORCE" /boot/config-$(uname -r),必须返回CONFIG_MODULE_SIG_FORCE=y - 检查运行时状态:
cat /proc/sys/kernel/modules_disabled返回0是正常;真正生效靠的是加载行为,不是这个值 - 实测验证:用
insmod尝试加载一个未签名的.ko文件,应直接报错Operation not permitted,且dmesg显示类似module: signature verification failed的拒绝日志 - 注意:如果系统启用了 Secure Boot,
module.sig_enforce=1通常已被固件隐式强制,此时删掉该参数也不会恢复宽松模式
常见错误现象和对应排查点
典型失败场景不是“配了不生效”,而是“以为生效了,其实没拦住”:
– 模块仍能加载,但 dmesg 里有 tainted 提示 → 说明内核只开了 CONFIG_MODULE_SIG,没开 CONFIG_MODULE_SIG_FORCE,或启动参数写成了 module.sig_enforce=0
– insmod 报 Invalid module format → 不是签名问题,是模块编译内核版本与当前运行内核不匹配(vermagic 不符),先用 modinfo xxx.ko 对比 vermagic 字段
– 签名后仍被拒,dmesg 提示 PKCS#7 signature not signed with a trusted key → 公钥没导入内核信任链,需用 mokutil --import 注册证书,并在重启后进 MOK 管理界面确认
– 使用 rmmod 卸载后重试,发现“上次居然加载成功了” → 某些发行版(如 RHEL/CentOS)默认把 module.sig_enforce=1 写死在内核镜像里,你删掉 GRUB 参数也没用;得反向确认是否真需要关(生产环境不建议关)
签名模块时最容易被忽略的细节
签名本身不是终点,而是链条的一环:
– scripts/sign-file 必须用内核源码树里的脚本,不能用 OpenSSL 自行生成 PKCS#7;否则内核解析失败
– 私钥格式必须是 PEM,公钥 DER;命令形如:./scripts/sign-file sha256 mykey.pem mykey.der mymodule.ko
– 若模块依赖其他模块(如 crypto-api),依赖链上所有模块都必须签名,否则加载时因依赖检查失败而中断
– CONFIG_MODULE_SIG_ALL=y 只影响 make modules_install 阶段自动签名,对 out-of-tree 模块无效;自研驱动必须手动签,且签名密钥要和内核内置公钥配对
真正卡住人的从来不是“怎么加参数”,而是“为什么加了还不拦”。核心就两条:内核编译选项没开 CONFIG_MODULE_SIG_FORCE,或签名密钥没进信任链。其余都是表象。











