Linux 内核模块签名

  • Linux 内核模块签名

1.概述

内核模块签名检查是内核内建的一种安全机制和功能,目的是确保内核动态加载的所有内核模块必须要经过签名。

linux内核从3.7 开始加入模块签名检查机制, 校验签名是否与已编译的内核公钥匹配。 模块签名验证并非强制使用, 可在编译内核时配置是否开启。如果内核选项CONFIG_MODULE_SIG和CONFIG_MODULE_SIG_FORCE打开的话,当加载模块时内核会检查模块的签名, 如果签名不存在或者签名内容不一致,会强制退出模块的加载。

签名验证在通过CONFIG_MODULE_SIG使能。打开签名同时还会强制做模块ELF元数据检查,然后再做签名验证。很多 OS 都是通过 UEFI 引导的,而如果 UEFI 里使能 secure boot,那么需要 Signed kernel image 才能加载,对应的 kernel module 也需要是签过名的。即便 UEFI 里没有使能 secure boot,但如果内核按照 CONFIG_MODULE_SIG_FORCE 配置的(也可通过内核启动参数"module.sig_enforce=1" 打开),那么也只有签过名的驱动能加载。如果内核只是设置了 CONFIG_MODULE_SIG,那么未签名的驱动虽可被加载,但会被标记为 taint。

1.1.公钥生成

内核编译时可以指定一系列的公钥。x509.genkey文件用来生成X509密钥。如果没有该文件,系统会自动提供一个默认的配置。Makefile会根据x509.genkey规则在内核编译根目录生成默认配置,用户可以手动更改该文件。由此在内核编译过程中分别生成私钥和公钥文件分别为./signing_key.priv和./signing_key.x509。

默认配置是使用/dev/random生成的。如果/dev/random没有足够数据,在后台运行以下命令可以生成更多的数据:rngd -r /dev/urandom。

1.2.模块签名

在开启该功能之后,内核在加载内核模块时,会对内核模块的签名进行检查。内核模块签名功能的本质是限制root用户载入恶意的内核模块。当root用户加载一个内核模块时,内核在分辨是系统管理员还是攻击者的时候,依靠的就是能够进行身份认证的可信的X.509证书和与之对应的私钥。只要私钥存储妥当不发生泄露,攻击者就无法伪造X.509证书,因此也就不可能提供含有正确签名的内核模块;而系统管理员是唯一合法的X.509证书的使用者,是可以用合法的证书对应的私钥对内核模块进行签名的。

1.2.1.内核配置

c 复制代码
CONFIG_MODULE_SIG	    Y
CONFIG_MODULE_SIG_ALL	N
CONFIG_MODULE_SIG_FORCE	N
  • CONFIG_MODULE_SIG
    如果开启了该选项,在内核在加载内核模块时,会对内核模块的签名进行检查。 配置为'y'后, 默认情况下,在加载没有签名或者是签名不正确的内核模块时,内核仅仅是打印一条提示信息,同时将内核标记为tainted,然后继续正常加载签名有问题的模块。
c 复制代码
 module verification failed: signature and/or required key missing - tainting kernel
  • CONFIG_MODULE_SIG_FORCE

    若配置为'n'时, 对于未签名或者使用无效的key签名的模块, 内核都允许加载, 但是kernel会被标记为被感染(tainted),并且使用商业许可的模块也会被标记为被感染;

    若配置为'y', 则 在加载没有签名或者是签名不正确的内核模块时,内核会直接拒绝加载签名有问题的内核模块。

  • CONFIG_MODULE_SIG_ALL

    若配置为'n', 则在build kernel的过程中, 所有的模块都不会被签名, 需要自己手动调用scripts/sign-file签名工具对内核模块进行签名。

    若被配置为'y', 则在build kernel的过程中自动对模块进行签名,而且该步骤通常无需手动运行,会在module_install时自动执行签名。

1.2.2.内核启动参数

module.sig_enforce:

如果将该参数传给内核,表示强制验证内核模块签名,效果上等价于CONFIG_MODULE_SIG_FORCE=y。如果内核在编译时已经将CONFIG_MODULE_SIG_FORCE设为y,那这里的内核选项是不会起任何作用的。

该选项为内核强制验证功能在策略上提供了一定的灵活性,比如运行系统需要DKMS或者SystemTap支持的话,如果没有实现配套的PKI签名服务机制,最好将CONFIG_MODULE_SIG_FORCE设为n,同时为了保证安全在内核命令行参数中指定module.sig_enforce。在必要时,可以临时去掉module.sig_enforce,以便系统维护或调试。

1.2.3.签名算法配置

c 复制代码
CONFIG_MODULE_SIG_SHA1
CONFIG_MODULE_SIG_SHA224
CONFIG_MODULE_SIG_SHA256
CONFIG_MODULE_SIG_SHA384
CONFIG_MODULE_SIG_SHA512
  • CONFIG_MODULE_SIG_SHA256
    用于启用 SHA-256 哈希算法对内核模块进行签名和验证。

1.2.4.签名所用的key

c 复制代码
CONFIG_MODULE_SIG_KEY=""
CONFIG_MODULE_SIG_KEY_TYPE_RSA=y
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYSTEM_TRUSTED_KEYS="certs/openeuler-cert.pem"
  • CONFIG_MODULE_SIG_KEY

    用于允许使用 ​自定义签名密钥 对内核模块进行签名和验证。CONFIG_MODULE_SIG_KEY的值为默认值certs/signing_key.pem,表示用户希望使用由kbuild自动生成的key文件对内核模块进行签名。

  • CONFIG_SYSTEM_TRUSTED_KEYS

    用于指定系统信任的公钥文件路径,以验证内核模块的签名。

  • 两者区别:

    • CONFIG_MODULE_SIG_KEY:允许动态指定签名密钥(如通过 modprobe 参数),但需要内核支持动态密钥注入。
    • CONFIG_SYSTEM_TRUSTED_KEYS:在编译时静态嵌入公钥路径,更适用于固定信任环境。

编译内核在certs目录生成signing_key.pem和signing_key.x509

2.Makefile:

c 复制代码
CONFIG_MODULE_SIG=n
该变量用于控制内核模块签名的设置。在这里,它被设置为 n,表示禁用模块签名。

refer to

相关推荐
可问 可问春风1 小时前
Linux 找回 Root 密码(多发行版本)
linux·运维·chrome
木子欢儿3 小时前
Debian系统清理垃圾
linux·运维·服务器·debian
谷晓光4 小时前
python中print函数的flush如何使用
linux·服务器·数据库
AdrichPro4 小时前
4、linux c 进程
linux·运维·服务器·c语言
2301_779503766 小时前
K8s的部署
linux·容器·kubernetes
why—空空7 小时前
linux系统CentOS 7版本搭建NFS共享存储
linux·运维·centos
不甘平凡--liang7 小时前
Linux Nginx安装部署、注册服务
linux·运维·服务器
小妖6668 小时前
linux (centos) 的 nodejs 安装全局包后使用命令无效
linux·运维·centos
不穿格子衬衫9 小时前
感受命令行界面的魅力——Linux环境下基础开发工具的使用
linux·运维·centos