作者:libvirt 项目贡献者。本文依据官方知识库 Secure Boot 翻译整理,核对日期为 2026 年 10 月 5 日。示例中的固件路径取自原文,只用于说明 XML 结构,实际路径由宿主发行版、架构和已安装固件决定。
给虚拟机使用支持 Secure Boot 的 UEFI 固件,并不意味着启动签名验证已经启用。还必须提供可用于验证操作系统签名的密钥。libvirt 用 secure-boot 和 enrolled-keys 两个固件特性表达这两个条件;理解它们的区别,才能正确创建新虚拟机,也才能判断修改既有虚拟机时为什么只改 XML 还不够。

新虚拟机:同时指定支持和密钥
在 libvirt 8.6.0 或更高版本,创建虚拟机时可用下面的 os 片段请求启用 Secure Boot。它是域 XML 的一部分,并非完整的虚拟机定义。
<os firmware='efi'>
<firmware>
<feature enabled='yes' name='secure-boot'/>
<feature enabled='yes' name='enrolled-keys'/>
</firmware>
</os>
firmware='efi' 请求 UEFI 固件自动选择;第一个特性要求固件支持 Secure Boot,第二个要求用带有适当密钥的模板初始化变量存储。在原文描述的默认密钥模板条件下,这种组合会拒绝未签名的来宾操作系统。宿主必须实际安装符合所选架构和机器类型的固件及描述文件,声明需求并不能凭空生成所缺的固件。
两个“允许未签名系统启动”的配置为何不同
官方文档同时列出两种关闭验证的方式。第一种选择根本不支持 Secure Boot 的固件构建:
<os firmware='efi'>
<firmware>
<feature enabled='no' name='secure-boot'/>
</firmware>
</os>
第二种仍选用支持 Secure Boot 的固件,但要求变量模板不预置密钥:
<os firmware='efi'>
<firmware>
<feature enabled='yes' name='secure-boot'/>
<feature enabled='no' name='enrolled-keys'/>
</firmware>
</os>
这两种设置都会允许未签名系统启动,但后者还保留日后注册自有密钥、运行自行构建并签名系统的能力。对于只计划使用现成操作系统镜像的场景,原文将二者视为功能上相当。
编辑安全说明:上面两段是原文对配置语义的解释,不应成为遇到签名失败就关闭验证的默认处理方式。签名失败时,应先检查镜像来源、签名、信任密钥和来宾启动链;无密钥状态不能被当成已受 Secure Boot 保护。
旧版 libvirt 的差异
原文对早于 8.6.0、晚于 7.2.0 的版本给出更完整的写法,需要额外的 loader secure='yes':
<os firmware='efi'>
<loader secure='yes'/>
<firmware>
<feature enabled='yes' name='secure-boot'/>
<feature enabled='yes' name='enrolled-keys'/>
</firmware>
</os>
更早版本需要手动提供全部固件信息,不在这篇知识库的操作范围内。可参阅 域 XML 的操作系统启动文档。实际遇到 7.2.0 边界版本、发行版回移补丁或特殊固件包时,应按已安装版本的文档与能力信息核实,而不要仅依据一个版本字符串推定支持情况。
既有虚拟机:固件选择结果已经固定
定义虚拟机时,libvirt 会选择最符合条件的固件,并将选择结果写进 XML,供后续启动继续使用。原文给出两类结果。第一类使用只读 pflash 固件和 NVRAM 文件:
<os firmware='efi'>
<firmware>
<feature enabled='yes' name='enrolled-keys'/>
<feature enabled='yes' name='secure-boot'/>
</firmware>
<loader readonly='yes' secure='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd</loader>
<nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/vm_VARS.fd</nvram>
</os>
另一类使用 ROM 固件以及 varstore:
<os firmware='efi'>
<firmware>
<feature enabled='yes' name='enrolled-keys'/>
<feature enabled='yes' name='secure-boot'/>
</firmware>
<loader type='rom' format='raw'>/usr/share/edk2/aarch64/QEMU_EFI.qemuvars.fd</loader>
<varstore template='/usr/share/edk2/aarch64/vars.secboot.json' path='/var/lib/libvirt/qemu/varstore/vm.json'/>
</os>
这些路径体现两种不同固件布局,不能从第一段复制 NVRAM 路径、再与第二段的架构混用。要迫使 libvirt 重新执行固件自动选择,必须从域 XML 中移除已记录的 loader,以及适用的 nvram 或 varstore 元素;保留旧的选择结果很可能导致错误。
但重选固件仍不等于改变当前 Secure Boot 状态。虚拟机已有的 NVRAM 或 varstore 文件还必须从新的模板重新生成,否则此前的变量和密钥仍会继续生效。原文使用以下启动命令:
virsh start vm --reset-nvram
操作边界:vm 是原文的示例虚拟机名。此命令会启动指定虚拟机并重建变量存储,具有状态破坏性;本文未执行。应在虚拟机已正常关机、已备份原域 XML 和对应变量文件、已核实恢复方法的维护窗口内,针对经确认的目标操作。重置可能丢失自定义密钥、启动项以及其他固件变量,个别来宾会因此无法启动。修改持久 XML 也不会令正在运行的虚拟机立即切换固件。
--reset-nvram 从 libvirt 8.1.0 起提供。原文称更早版本需要手动删除 NVRAM 文件后启动。由于删除会不可逆地改变原状态,本文仅保留这一版本差异,不提供直接删除命令;应优先在副本中验证,并依靠事先保存的变量文件和 XML 回退。
验证应落在实际启动行为上
多数宿主系统提供的 EDKII 构建已经支持 Secure Boot。真正使签名要求生效的是变量模板中的信任密钥。enrolled-keys='yes' 会让 libvirt 选择带适当密钥的模板,而关闭它会初始化为不含这些密钥的状态;此时固件没有对应的验证依据,允许未签名系统运行。
完成变更后,应在来宾内确认 Secure Boot 状态,并在可恢复的测试副本中验证未获信任镜像确实被拒绝。仅查看固件文件名包含 secboot、或 XML 中出现 secure='yes',都不足以单独证明当前变量存储里的验证已经生效。本文仅完成配置静态核对,未启动虚拟机、未更改密钥,也未实施拒绝未签名镜像的运行测试。
来源与归属:libvirt:Secure Boot,libvirt 项目贡献者。中文翻译、流程图及安全边界说明为编辑新增。原文页面未单列文档转载许可证,不把 libvirt 软件许可证自动解释成所有文档的独立许可。












暂无评论内容