一、原理

为什么 Secure Boot 会导致驱动失效?

开启 Secure Boot 后,Linux 内核会进入 Lockdown(锁定)模式,要求所有被加载的内核模块(.ko.ko.xz)必须附带受主板 UEFI 信任的密钥签名。

  • 自带模块(如 KVM):由 Fedora 官方密钥签名,默认受信任,无需干预。
  • 第三方模块(如 NVIDIA、VMware):属于本地动态编译,没有任何数字签名,直接被内核拒绝加载。
  • 解决方案:在本地生成自己的机器所有者密钥(MOK,Machine Owner Key),将公钥注入主板 NVRAM 信任库,并用私钥对这些第三方模块进行签名。

二、BIOS环境

在进行任何签名操作前,必须确保主板固件的信任链支持现代 Linux 引导组件。老旧的 BIOS 会直接拒绝 Fedora 现代版本的 Shim 引导器。否则折腾半天发现是 BIOS 太旧的缘故.

  1. 升级主板 BIOS
  1. 同步 UEFI 安全数据库 在 Linux 终端中,拉取微软最新的第三方 CA 证书库,覆盖主板中老旧的数据库:
1
2
sudo fwupdmgr refresh --force
sudo fwupdmgr update
  1. 确保版本已更新至最新年份
1
fwupdmgr get-devices | grep -A3 "UEFI CA"

三、MOK 自动签名体系

生成全局 MOK 密钥与自动签名体系 (Akmods 方案). 当然也可以手动签名.

在 Fedora 下,我们直接利用官方工具 kmodgenca 生成密钥,它能无缝对接 akmods,实现 NVIDIA 驱动在每次内核更新后的全自动编译与签名

  1. 生成 Akmods 专属密钥对
1
2
3
4
5
# 确保安装了底层构建与密钥管理工具
sudo dnf install -y akmods mokutil

# 自动生成 MOK 密钥对(存放在 /etc/pki/akmods/ 目录下)
sudo kmodgenca -a
  1. 将公钥注册到主板 UEFI MOK 数据库
1
2
3
4
# 提取生成的 DER 格式公钥并请求导入主板
sudo mokutil --import /etc/pki/akmods/certs/public_key.der

# 此时系统会提示设置一个临时密码(例如 12345678),仅供稍后重启时验证使用。
  1. 重启并物理确认
1
选择 Enroll MOK → Continue → Yes → 输入刚才设置的临时密码 → Reboot。
  1. 验证
1
mokutil --list-enrolled | grep -A3 "Issuer"

四、NVIDIA 驱动的编译与签名

  1. 安装驱动并强制触发重编
1
2
3
4
5
# 安装驱动包
sudo dnf install -y akmod-nvidia xorg-x11-drv-nvidia-cuda

# 强制 akmods 调用刚才生成的密钥,重新编译并签名驱动模块
sudo akmods --force --kernel $(uname -r) --rebuild
  1. 严格校验签名状态
1
2
# 查找 nvidia 模块并验证是否包含 signer 信息
modinfo $(find /lib/modules/$(uname -r)/extra/ -name "nvidia.ko*") | grep -E "signer|sig_key"

看到 signer: Fedora... 等字样,确认签名打上后,方可开启 Secure Boot

五、模块的手动签名

对于不归属 akmods 管理的纯第三方虚拟化软件(如 VMware Workstation),其生成的 vmmonvmnet 需要手动使用刚刚生成的密钥进行签名。

⚠️ 避坑警告: 绝对不能使用通配符在整个 /lib/modules/ 目录下盲目遍历 .ko* 进行签名,这会破坏系统原生经过 xz 压缩的模块(如 vsock.ko.xz)。必须精准定位到 /misc 或对应的独立目录。

执行安全的手动签名脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
KVER=$(uname -r)
SIGN_FILE="/usr/src/kernels/$KVER/scripts/sign-file"
PRIV_KEY="/etc/pki/akmods/private/private_key.priv"
PUB_KEY="/etc/pki/akmods/certs/public_key.der"

# 仅精确查找 misc 目录下的 VMware 模块
for mod in vmmon vmnet; do
MOD_PATH=$(find /lib/modules/$KVER/misc -name "${mod}.ko*" 2>/dev/null | head -1)
if [ -n "$MOD_PATH" ]; then
echo "Signing VMware module: $mod..."
sudo $SIGN_FILE sha256 "$PRIV_KEY" "$PUB_KEY" "$MOD_PATH"
fi
done

# 重新加载模块使签名生效
sudo modprobe vmmon
sudo modprobe vmnet

六、排障指南

故障 1

开启 Secure Boot 后,NVIDIA 驱动依然丢失

  • 排查逻辑:使用 modinfo nvidia | grep signer 确认驱动本身是否带有签名。
  • 场景 A(模块无签名)akmods 命中了本地 RPM 缓存。需执行 sudo rm -f /var/cache/akmods/nvidia/*.rpm 清除缓存,并加上 --rebuild 参数重新执行 akmods 命令。
  • 场景 B(模块有签名,但仍被拒):主板 BIOS 被升级或重置,导致 NVRAM 中的 MOK 列表被清空。无需重新编译驱动,直接再次执行 sudo mokutil --import /etc/pki/akmods/certs/public_key.der 并重启导入即可。

故障 2

执行 depmod 时提示 vsock.ko.xz: File is corrupt

  • 原因:误操作损坏了 Fedora 内核的原生压缩模块。

  • 修复方案:锁定该模块所属的 RPM 包并进行手术级别重装。

    Bash

    1
    2
    3
    4
    # 重装核心内核模块包
    sudo dnf reinstall kernel-modules-core-$(uname -r)
    # 重新生成依赖树
    sudo depmod -a $(uname -r)

故障 3

开机顶部闪过 prohibited by secure boot policy 报错

  • 原因分析:这是 GRUB 的非致命警告(Cosmetic Warning)。通常是因为系统中安装了非官方签名的第三方美化主题(如 Vimix)或 Btrfs 快照探测脚本(如 grub-btrfs)。Shim 校验器在严格模式下拦截了这些边缘脚本的加载请求。
  • 系统影响完全不影响后续 Linux 内核与 NVIDIA 驱动的正常引导加载。
  • 处理建议:无需处理。如强迫症需要彻底消除该报错,需编辑 /etc/default/grub,注释掉 GRUB_THEME 相关行,并执行 sudo grub2-mkconfig -o /boot/grub2/grub.cfg 恢复纯净版黑白引导界面。