白皮书
2020 年 1 月

本白皮书是对所讨论技术设计目标的技术说明。最终产品中的实际技术或特性可能有所不同,也可能无法完全实现这些目标。对技术的每一项描述都应被理解为 AMD 努力实现的目标,而不应被解释为保证能够完全实现该性能。任何计算机系统都存在无法完全预防或缓解的安全漏洞风险。


引言

2016 年,AMD 推出了安全加密虚拟化(SEV),这是第一项旨在将虚拟机(VM)与 Hypervisor 隔离的 x86 技术。虽然 Hypervisor 传统上一直是虚拟化安全模型中的可信组件,但许多市场可以从不同的 VM 信任模型中受益。例如,在云计算中,客户可能希望保护其基于 VM 的工作负载免受云管理员的访问,以保持数据机密性,并最大限度地减少其暴露于云提供商基础设施中的漏洞。这导致了在硬件级别将 VM 与 Hypervisor 以及可能共存于同一物理服务器上的其他代码隔离的需求。

AMD 开始通过在 SEV 中使用主内存加密来应对这一挑战。借助该技术,可以为每个 VM 分配一个唯一的 AES 加密密钥,用于自动加密其正在使用的数据。当 Hypervisor 等组件尝试读取客户机内部的内存时,它只能看到加密后的字节。

2017 年,AMD 推出了 SEV-ES(加密状态)功能,为 CPU 寄存器状态增加了额外保护。在 SEV-ES 中,VM 寄存器状态在每次 Hypervisor 转换时都会被加密,因此 Hypervisor 无法看到 VM 正在使用的数据。与 SEV 结合使用,SEV-ES 可以通过帮助保护内存中数据的机密性来减少 VM 的攻击面。

本白皮书介绍了下一代 SEV,称为 SEV-SNP(安全嵌套分页)。SEV-SNP 在现有 SEV 和 SEV-ES 功能的基础上增加了新的基于硬件的安全保护。SEV-SNP 增加了强大的内存完整性保护,以帮助防止恶意的基于 Hypervisor 的攻击,如数据重放、内存重映射等,从而创建一个隔离的执行环境。此外,SEV-SNP 还引入了几项额外的可选安全增强功能,旨在支持额外的 VM 使用模式、提供更强的中断行为保护,并提供针对最近公开的侧信道攻击的增强保护。

本白皮书将 SEV、SEV-ES 和 SEV-SNP 统称为 AMD SEV 技术。


完整性保护的必要性

如 AMD SEV 技术所使用的 AES 加密,为内存提供了增强的机密性保护。不了解加密密钥的攻击者无法解读存储在 DRAM 中的 VM 数据。SEV 内存加密密钥本身由硬件随机数生成器生成,并存储在专用硬件寄存器中,软件无法直接读取。此外,硬件的设计使得不同内存位置的相同明文将被不同地加密。

尽管有加密,有一定动机的攻击者可能会尝试更改内存中的值,即使不知道加密密钥。这类攻击被称为完整性攻击,因为内存中的值与 VM 预期的不同。虽然攻击者无法轻松地将已知的明文放入 VM 中,但他们可能会用旧值或随机数据替换内存中的值(如数据重放和数据损坏攻击)。另一种攻击可能涉及将不同客户机页面映射到相同的物理内存页面,或将单个客户机页面映射到不同的物理内存地址(如内存别名和内存重映射攻击)。

完整性攻击本身并不直接危害 VM。VM 内部的软件必须使用不正确的数据,从而导致被攻破或信息泄露。这种攻击是否成功取决于 VM 内部的软件以及它在遇到被篡改数据时的行为方式。由于 VM 中的软件通常不知道其内存完整性是否已被破坏,因此在这种情况下其行为难以预测。

SEV-SNP 旨在防止基于软件的完整性攻击并降低与内存完整性被破坏相关的风险。SEV-SNP 完整性的基本原则是:==如果 VM 能够读取一个私有(加密的)内存页面,它必须始终读取到它最后写入的值==。这意味着如果 VM 将值 A 写入内存位置 X,那么之后每当它读取 X 时,它必须要么看到值 A,要么获得一个异常表示内存无法被读取。SEV-SNP 的设计确保 VM 不应该能从内存位置 X 看到不同的值。

为了支持标准的 VM 任务,这一保证必须在读取和最后一次写入之间无论内存发生什么都成立。如果该内存页面被交换到磁盘,甚至整个 VM 被迁移到新主机,完整性保证仍必须成立。强制执行这一完整性保证需要结合新的 CPU 硬件和固件,本白皮书稍后将讨论。

在典型的使用场景中,VM 必须既执行自己的任务,又通过 I/O 与外部实体通信。这可能包括通过网络链路、与存储服务器或与其他组件的通信。在 SEV 架构中,此通信通过共享(未加密)内存完成。==VM 希望提供的任何传出数据都放置在共享内存页面中,任何传入数据同样必须放置在共享页面中。由于共享内存不使用 VM 特定密钥加密,因此应使用适当的软件加密协议(如 HTTPS)来确保 I/O 流量的安全。==

AMD SEV VM 使用客户机页表中的 ==enCrypted== 位(C-bit)来控制内存页面是私有的还是共享的。C-bit 的位置由实现定义,可能是最高物理地址位,如图 1 所示。共享(未加密)内存由 VM 标记为 C=0,表示不需要使用 VM 的内存加密密钥进行加密。私有(加密)内存页面供该 VM 独占使用,标记为 C=1。==在典型的 VM 中,大多数页面标记为私有,只有用于外部通信的选定页面标记为共享。与 SEV 机密性保证一样,SEV-SNP 完整性保证仅适用于私有客户机页面。==

![[Pasted image 20260512135538.png]]

威胁模型细节

与之前的 SEV 和 SEV-ES 功能一样,在 SEV-SNP 下,AMD 片上系统(SOC)硬件、AMD 安全处理器(AMD-SP)和 VM 本身都被视为完全可信的。VM 负责保护自身及其接口,并应遵循保护其使用的任何 I/O 数据(如网络流量、硬盘数据等)的标准最佳实践。为此,AMD 强烈建议对受保护的 VM 使用全磁盘加密(FDE)解决方案,因为所有 SEV 技术仅保护正在使用中的数据。FDE 保护静态数据,市面上有许多流行的商业解决方案。

在 SEV-SNP 下,所有其他 CPU 软件组件和 PCI 设备都被视为完全不可信,如图 2 所示。这包括主机系统上的 BIOS、Hypervisor、设备驱动程序、其他 VM 等。完全不可信意味着这些组件被假定为恶意的,可能与其他不可信组件合谋,试图破坏 SEV-SNP VM 的安全保证。

![[Pasted image 20260512160857.png]]

SEV-SNP 威胁模型包含了旨在防范比以前 AMD SEV 技术更多威胁的功能。SEV 和 SEV-ES 使用 " 善意但有漏洞 " 的 Hypervisor 威胁模型。在此威胁模型中,Hypervisor 不被认为是 100% 安全的,但被信任为具有善意。这意味着虽然 Hypervisor 并非主动试图攻破其下的 SEV VM,但它本身可能存在可利用的漏洞。通过阻止或增加某些攻击的难度,SEV 和 SEV-ES 技术可以帮助限制某些类别的 Hypervisor 漏洞的潜在影响,或显著提高利用难度。SEV-SNP 则应对了额外的攻击向量和对 VM 安全的潜在威胁。各种 SEV 技术所应对和未应对的威胁总结在表 1 中。

机密性:如前所述,机密性威胁通过所有当前 SEV 技术中的基于硬件的内存加密来处理。这可以防止不可信组件(如 Hypervisor 或具有 DMA 能力的设备)能够直接读取 VM 内部的明文(当然,VM 选择允许不可信访问的页面除外)。SEV-ES 技术为 VM 寄存器状态增加了机密性保护,在 VM 退出回到 Hypervisor 时加密此状态。此保护在 SEV-SNP 中同样存在。

完整性:SEV-SNP 技术旨在防范完整性攻击,包括数据重放、损坏、重映射和基于别名的攻击。VM 始终看到其最后写入的数据这一保证意味着必须防止所有这些攻击向量。

可用性:任何虚拟化平台的可用性都有两个方面。第一是确保 Hypervisor 保持对系统的控制,客户机 VM 不能阻止 Hypervisor 运行或使物理机不可用。所有 SEV 技术都支持这一级别的可用性,并保证 Hypervisor 可以在需要时始终重新获得控制权(例如,通过物理定时器中断)或在未经该 VM 同意的情况下随时终止客户机。可用性的第二个方面是客户机是否享有任何可用性保证,如最低运行时间。这不是任何 SEV 技术威胁模型的一部分,因为恶意 Hypervisor 始终可以选择永远不运行某个或所有客户机 VM。

物理访问攻击:虽然某些物理攻击(如 DRAM 冷启动攻击,即离线分析 DRAM 芯片)可以被这些技术阻止,但在线 DRAM 完整性攻击(如在 VM 主动运行时攻击 DDR 总线)不在范围内。这些攻击非常复杂,需要大量的本地访问和资源才能执行。

其他:还有几种针对安全 VM 的潜在攻击类型,其中一些在此威胁模型的范围内。例如,SEV-SNP 包含帮助防止可信计算基(TCB)回滚攻击的功能。如后文所述,这提供了一种加密手段来验证 AMD-SP 固件和系统中其他可信组件是否满足 VM 的策略。此外,SEV-SNP 可选地支持限制中断和异常如何被注入 VM 的能力。它还可以支持分支目标缓冲区(BTB)保护以防范某些类型的侧信道攻击。两种保护都将在本白皮书后文讨论。

最后,有某些类别的攻击不在这三个功能中任何一个的范围内。对 CPU 数据结构的架构侧信道攻击不会被任何硬件手段专门阻止。与标准软件安全实践一样,对此类侧信道攻击敏感的代码(如密码学库)应以有助于防止此类攻击的方式编写。当前一代技术也不支持指纹攻击保护。指纹攻击试图通过监控 VM 的访问模式来确定其正在运行什么代码。


表 1:威胁模型

潜在威胁 SEV SEV-ES SEV-SNP
机密性
VM 内存(示例攻击:Hypervisor 读取私有 VM 内存) ✅ 已缓解 ✅ 已缓解 ✅ 已缓解
VM 寄存器状态(示例攻击:VMEXIT 后读取 VM 寄存器状态) ❌ 未缓解 ✅ 已缓解 ✅ 已缓解
DMA 保护(示例攻击:设备尝试读取 VM 内存) ✅ 已缓解 ✅ 已缓解 ✅ 已缓解
完整性
重放保护(示例攻击:用旧副本替换 VM 内存) ❌ 未缓解 ❌ 未缓解 ✅ 已缓解
数据损坏(示例攻击:用垃圾数据替换 VM 内存) ❌ 未缓解 ❌ 未缓解 ✅ 已缓解
内存别名(示例攻击:将两个客户机页面映射到同一 DRAM 页面) ❌ 未缓解 ❌ 未缓解 ✅ 已缓解
内存重映射(示例攻击:切换映射到客户机页面的 DRAM 页面) ❌ 未缓解 ❌ 未缓解 ✅ 已缓解
可用性
对 Hypervisor 的拒绝服务(示例攻击:恶意客户机拒绝让出/退出) ✅ 已缓解 ✅ 已缓解 ✅ 已缓解
对客户机的拒绝服务(示例攻击:恶意 Hypervisor 拒绝运行客户机) ❌ 未缓解 ❌ 未缓解 ❌ 未缓解
物理访问攻击
离线 DRAM 分析(示例攻击:冷启动) ✅ 已缓解 ✅ 已缓解 ✅ 已缓解
主动 DRAM 损坏(示例攻击:VM 运行时操纵 DDR 总线) ❌ 未缓解 ❌ 未缓解 ❌ 未缓解
其他
TCB 回滚(示例攻击:将 AMD-SP 固件回退到旧版本) ❌ 未缓解 ❌ 未缓解 ✅ 已缓解
恶意中断/异常注入(示例攻击:RFLAGS.IF=0 时注入中断) ❌ 未缓解 ❌ 未缓解 ⚠️ 可选缓解
间接分支预测器投毒(示例攻击:从 Hypervisor 投毒 BTB) ❌ 未缓解 ❌ 未缓解 ⚠️ 可选缓解
安全硬件调试寄存器(示例攻击:调试期间更改断点) ❌ 未缓解 ❌ 未缓解 ⚠️ 可选缓解
可信 CPUID 信息(示例攻击:Hypervisor 谎报平台能力) ❌ 未缓解 ❌ 未缓解 ⚠️ 可选缓解
架构侧信道(示例攻击:PRIME+PROBE 追踪 VM 访问) ❌ 未缓解 ❌ 未缓解 ❌ 未缓解
页级侧信道(示例攻击:通过页表追踪 VM 访问模式) ❌ 未缓解 ❌ 未缓解 ❌ 未缓解
性能计数器追踪(示例攻击:通过性能数据识别 VM 应用) ❌ 未缓解 ❌ 未缓解 ❌ 未缓解

完整性威胁

上一节重点介绍了四种独特类型的完整性威胁:重放保护、数据损坏、内存别名和内存重映射。防范这些威胁需要强制执行不同的安全属性,如表 2 所示。

表 2:完整性威胁

威胁 期望的安全属性 SEV-SNP 执行机制
重放保护 只有内存页面的所有者才能写入该页面 反向映射表(RMP)
数据损坏 只有内存页面的所有者才能写入该页面 反向映射表(RMP)
内存别名 每个物理内存页面一次只能映射到单个客户机页面 反向映射表(RMP)
内存重映射 每个客户机页面一次只能映射到单个物理内存页面 页面验证

在重放保护和数据损坏攻击的情况下,这些攻击依赖于不可信代码能够写入受保护 VM 的内存。SEV-SNP 通过强制只有内存页面的所有者(例如,该页面被分配给的 SEV-SNP VM)才能写入该页面来解决此问题。此强制通过以下部分描述的反向映射表(RMP)机制完成。

内存别名攻击涉及 Hypervisor 恶意地将两个不同的客户机页面同时映射到相同的物理内存页面。客户机自然期望其客户机物理地址空间中的不同页面映射到不同的内存,因此任何别名都可能导致意外的数据损坏。解决此威胁需要确保每个物理内存页面一次只能映射到一个客户机页面。同样,RMP 结构用于强制执行此属性。

最后一种完整性威胁,即内存重映射,涉及 Hypervisor 恶意地将单个客户机页面重映射到多个不同的物理内存页面。在此威胁中,客户机可能会看到不一致的内存视图,其中只有它写入的数据的一部分出现在内存中。解决此威胁需要确保每个客户机页面一次只映射到一个物理内存页面,并且除了受信任的实体(如 AMD-SP)之外,此映射不能被更改。SEV-SNP 使用一种称为页面验证的机制来解决此威胁。页面验证依赖于新的 RMP 机制与新的 VM 代码的组合来管理客户机内存和系统内存之间的单射关系。


反向映射表

如前所述,SEV-SNP 的许多完整性保证通过一种称为反向映射表(RMP)的新结构来强制执行。RMP 是整个系统共享的单一数据结构,包含可能被 VM 使用的每个 4K DRAM 页面的一个条目。RMP 的目标很简单:它跟踪每个内存页面的所有者。内存页面可以由 Hypervisor 拥有、由特定 VM 拥有或由 AMD-SP 拥有。对内存的访问受到控制,只有该页面的所有者才能写入它。RMP 与标准 x86 页表结合使用来强制执行访问控制。

RMP 按系统物理地址索引,并在 CPU 和 IOMMU 表遍历结束时进行检查。例如,在原生(非 VM)模式下,虚拟地址通过标准 x86 页表转换为物理地址。转换后,最终的物理地址用于索引 RMP。读取 RMP 条目并进行检查。如果 RMP 条目表明该页面是 Hypervisor 拥有的页面,则检查通过并创建新的 TLB 条目。但如果 RMP 条目表明该页面不是 Hypervisor 拥有的页面,则表遍历发生错误(#PF),访问被拒绝。

在 SEV-SNP VM 中运行时,RMP 检查稍微复杂一些。与原生模式一样,虚拟地址首先被转换为系统物理地址。在这种情况下,使用 AMD-V 二级分页(也称为嵌套分页,如 AMD64 程序员手册第 2 卷第 15.25 节所述)将客户机虚拟地址(GVA)转换为客户机物理地址(GPA),最后转换为系统物理地址(SPA)。SPA 用于索引 RMP,并检查条目。此 RMP 条目应包含信息,表明该页面是客户机拥有的页面、分配给此特定客户机的,并且映射在此特定 GPA 处。也就是说,RMP 条目包含它应该被映射的 GPA,硬件验证此 GPA 是否与当前表遍历的 GPA 匹配。如果此检查或任何其他检查失败,将生成异常,访问被拒绝。

![[Pasted image 20260512162230.png]]

并非每次内存访问都需要 RMP 检查。特别是,来自 Hypervisor(或非 SEV-SNP 客户机)的读取访问不需要 RMP 检查,因为数据机密性已通过 AES 内存加密得到保护。否则,任何模式下的所有写入访问都需要 RMP 检查,SEV-SNP 内部对私有内存页面的读取和写入访问都需要 RMP 检查。写入访问包括标准内存写入以及作为页表遍历一部分的 A/D 位更新。与标准 x86 分页一样,RMP 检查的结果缓存在 CPU TLB 和相关结构中。

因为 RMP 用于强制执行对内存的访问控制,所以该表本身不能被软件直接写入。存在新的 CPU 指令来操作 RMP 条目,允许 Hypervisor 将页面分配给特定客户机、取回页面等。必要时,硬件自动执行 TLB 无效化,以确保系统中所有处理器都能看到更新的 RMP 条目信息。


页面验证

如前所述,每个 RMP 条目包含特定 DRAM 页面应被映射的 GPA。这从构造上确保每个 SPA 一次只能映射到单个 GPA。反之,单个 GPA 映射到多个 SPA 也不能被允许,以满足 SEV-SNP 完整性保证。虽然嵌套页表确保每个 GPA 只能映射到一个 SPA,但 Hypervisor 可能随时更改这些表。SEV-SNP 完整性要求以这种方式操纵表不能破坏期望的完整性,这通过验证(Validation)的概念来解决。

每个 RMP 条目内部有一个已验证位(Validated bit),当为客户机创建新的 RMP 条目时,CPU 硬件自动将此位清零。分配给客户机但已验证位为 0 的页面不能由 Hypervisor 使用或作为私有客户机页面使用,因为该页面尚未验证。客户机只有在通过新的 CPU 指令 PVALIDATE 设置已验证位后才能使用该页面。只有客户机能够使用 PVALIDATE,并且每个客户机 VM 只能验证自己的内存。

因此,向客户机添加新页面需要一个两步过程,如图 4 所示。首先,Hypervisor 使用新的 RMPUPDATE 指令将页面分配给客户机。这将页面转换为客户机 - 无效(Guest-Invalid)状态。其次,客户机使用新的 PVALIDATE 指令验证页面,将其转换为客户机 - 有效(Guest-Valid)状态,然后可以使用。

![[Pasted image 20260512163807.png]]

基本页面状态:

为了满足 SEV-SNP 期望的完整性,客户机 VM 不应对同一 GPA 对应的内存验证超过一次。这可以简单地通过客户机 VM 在启动时验证其所有内存并拒绝验证额外的内存(热插拔事件除外)来实现。或者,客户机 VM 可以跟踪它已验证的内存位置,并拒绝对同一位置进行第二次验证。

假设客户机 VM 正确验证其内存,这保证了 GPA 和 SPA 之间的单射映射。客户机将只验证每个 GPA 一次,而 RMP 表通过构造确保每个 SPA 只能映射到一个 GPA。


页面重映射攻击防护

正确执行时,页面验证可以阻止如图 5 所示的重映射攻击。在此示例中,GPA A 最初映射到 SPA X。客户机执行 PVALIDATE 来验证此转换,这导致 SPA X 对应的 RMP 条目中的已验证位被设置。如果 Hypervisor 随后恶意尝试将 A 重映射到不同的 SPA Y,它将首先使用 RMPUPDATE 指令为 SPA Y 创建一个 RMP 条目,尝试映射同一 GPA A。

然后 Hypervisor 恶意修改嵌套页表(NPT)将 GPA A 重映射到 Y。然而,当客户机访问 Y 时,它将收到 #VC(VMM 通信)异常。此异常发生是因为 SPA Y 对应的 RMP 条目中的已验证位为 0(因为执行 RMPUPDATE 将新页面分配给客户机时,它初始清除了已验证位)。由于客户机知道它已经验证了 GPA A,它知道不应该收到验证错误,因此它正在受到攻击,Hypervisor 行为不正确。作为响应,客户机可以终止或采取其他步骤来保护自己。

![[Pasted image 20260512164022.png]]

页面状态

如上所示,SEV-SNP 中的 RMP 跟踪每个内存页面的状态。这些状态决定了内存可以用于什么目的、谁被允许读/写它,以及页面稍后可以转换到什么状态。例如,处于 Hypervisor 状态的页面可以由 Hypervisor 读/写,或由以 C=0(共享页面)访问内存的 SEV-SNP VM 读/写。相比之下,处于客户机 - 有效状态的页面可以由 SEV-SNP VM 读/写,但不能由 Hypervisor 写入。

图 4 中的图表描述了三种基本页面状态:Hypervisor、客户机 - 有效和客户机 - 无效状态。总共有八种主要页面状态由 SEV-SNP 架构定义,如表 3 所列。页面状态转换如图 6 所示,可通过新的 CPU RMPUPDATE 指令(红色)、新的 PVALIDATE 指令(蓝色)或 AMD-SP 中的 VM 管理 API(绿色)发生。

与之前的 SEV 技术一样,SEV-SNP 在 AMD-SP 中实现了 VM 管理 API。Hypervisor 调用此接口来协助 VM 生命周期任务和页面管理。出于安全原因,AMD-SP 将操作的任何页面必须在发出必要的 API 调用之前被置于特殊状态,称为不可变(Immutable)状态。处于不可变状态的页面不能被 CPU 上的任何软件(Hypervisor 或客户机)写入,除 AMD-SP 外,任何人都不能修改其 RMP 条目。当 AMD-SP 处理完某个不可变状态的页面后,它可以将其转换为由特定 API 调用定义的不同状态。

表 3:SEV-SNP 页面状态

状态 描述 备注
HYPERVISOR 未分配内存的默认状态 用于 Hypervisor 内存、非 SNP-VM 内存和共享(C=0)内存
GUEST-INVALID 页面已分配给客户机但尚未准备好使用 SEV-SNP VM 在验证完成前不可使用
GUEST-VALID 页面已分配给客户机且可使用 可由分配的 SEV-SNP VM 用作私有(C=1)内存
PRE-GUEST 页面为不可变且未验证 在初始启动 SEV-SNP VM 时使用
PRE-SWAP 页面为不可变且已验证 在将客户机页面交换到磁盘时使用
FIRMWARE 页面为不可变且保留给 AMD-SP 使用 通常用作过渡状态直到 AMD-SP 配置好页面
METADATA 页面为不可变且用于元数据 元数据用于将客户机页面交换到磁盘时
CONTEXT 页面为不可变且用于上下文信息 上下文页面由 AMD-SP 用于标识各个 VM 并保存每个 VM 的数据

![[Pasted image 20260512164212.png]]

例如," 元数据 " 页面是一种不可变页面。这些页面只能由 AMD-SP 写入,用于保存与已交换到磁盘的客户机页面关联的元数据条目。由于 SEV-SNP 完整性保证,任何交换到磁盘的页面在被交换回内存之前必须确认其完整性。当页面被交换到磁盘时,AMD-SP 创建一个包含认证标签(来自 AES-GCM)以及页面 RMP 条目中数据(如它所在的 GPA)的元数据条目。

由于元数据页面本身不能由 Hypervisor 写入,此信息的完整性得到保证。当页面被交换回内存时,AMD-SP 验证内容未更改,并确保页面在与之前相同的位置进入客户机地址空间。元数据页面本身也可以以类似方式交换到磁盘,允许任意数量的客户机内存被交换出去。


虚拟机特权级别

虚拟机特权级别(VMPL)是 SEV-SNP 架构中的一个新的可选功能,允许客户机 VM 将其地址空间划分为四个级别。这些级别可用于在 VM 内提供硬件隔离的抽象层以实现额外的安全控制,以及协助管理与 Hypervisor 的通信。

这些级别本质上是分层的,其中 VMPL0 是最高特权,VMPL3 是最低特权。启用此功能后,VM 的每个 vCPU 都被分配一个 VMPL。每个私有客户机内存页面的 RMP 条目也增加了对应每个 VMPL 的页面访问权限,这些权限在标准分页权限之外额外应用。具体来说,各个客户机页面可以被标记为可读、可写、超级模式可执行和用户模式可执行。默认情况下,当客户机首次验证页面时,VMPL0 被授予对该页面的完全权限,所有其他 VMPL 不被授予任何权限。客户机可以通过新的 RMPADJUST 指令选择修改 VMPL 权限。

RMPADJUST 指令允许给定的 VMPL 修改较低特权 VMPL 的权限。例如,VMPL0 可以将页面的读和写(但不是执行)权限授予 VMPL1。这受到限制,一个级别不能授予超过其当前拥有的权限。VMPL 主要用于设置额外的页面权限检查,否则与其他 x86 安全功能正交。

RMP 页面权限检查在表遍历结束时的 RMP 查找时执行。页面权限检查本质上是限制性的,因此例如要使客户机页面可写,它必须在客户机管理的页表(对应于活动 vCPU)、嵌套页表(由 Hypervisor 管理)以及 RMP 表(由更高特权的 VMPL 管理)中都标记为可写。

![[Pasted image 20260512164451.png]]

VMPL 在某些方面类似于嵌套虚拟化,因为客户机可以包含其自己的管理层运行在高 VMPL 上,控制其他页面的权限。这使得安全虚拟化安全执行 Hypervisor 等用例成为可能。在裸机系统上,标准 Hypervisor 可用于强制某些页面为只读、不可执行等,而 SEV-SNP 在云环境中实现了相同的使用模式。在这种情况下,客户机内部的 VMPL0 将强制执行所需的页面权限,因为云中真正的 Hypervisor 被视为不可信。

VMPL 在作为抽象层的几个额外场景中也很有用。例如,APIC 仿真是传统上由 Hypervisor 处理的任务。在 SEV-SNP 中,某些 VM 可能希望一个更严格的环境,其中 APIC 仿真被移到客户机的信任域内。在这种情况下,VMPL0 可用于执行可信的 APIC 仿真,同时允许运行在较低 VMPL 中的其余客户机保持对仿真的无感知。

VMPL0 还可以用作客户机到 Hypervisor 通信的中介。以前,SEV 和 SEV-ES 技术要求一个启蒙(enlightened)的客户机 OS,即了解这些安全功能的 OS。客户机 OS 被期望执行诸如在页表中设置 C-bit、处理 #VC 异常(在 SEV-ES 中)等操作。在 SEV-SNP 的情况下,这些任务可以选择性地委托给 VMPL0。

在此使用模式中,VMPL0 可用于使用称为虚拟内存顶部(vTOM)的水印来配置另一个 vCPU 中的客户机内存是私有(C=1)还是共享(C=0)。vTOM 以下的内存地址自动被视为私有,而 vTOM 以上的内存被视为共享。以这种方式使用 vTOM 分离内存避免了需要在标准 x86 页表中增加 C-bit 标记的需求,简化了客户机 OS 软件。

![[Pasted image 20260512164754.png]]

此外,VMPL0 可用于处理另一个 vCPU 中发生的 #VC 事件。SEV-SNP VM 可以配置为当一个被拦截的指令在一个 vCPU 中执行时(如 RDMSR),该 vCPU 退出并调用 VMPL0。VMPL0 然后可以直接从原始 vCPU 的加密保存区域查看被拦截的信息,执行任何必要的超级调用,并代表原始 vCPU 仿真该指令,如图 8 所示。

虽然不如原生启蒙客户机高效,但此行为可以使 VMPL0 充当运行未启蒙(传统)客户机 VM 的粘合逻辑。这有可能允许 SEV-SNP 用于保护可能不容易升级到较新操作系统的旧工作负载。


中断/异常保护

虽然几乎所有 VM 操作系统都支持中断和异常处理,但某些操作系统可能基于裸机硬件对中断和异常行为有内置假设。如果这些假设可以被恶意 Hypervisor 违反,这种行为可能违反操作系统设计的假设。例如,操作系统可能不期望在其 TPR 提升时接收低优先级中断,或者可能不期望在执行 ADD 指令后接收 #UD 异常。

为了解决这些问题,SEV-SNP 添加了两种可选模式,VM 可以选择启用这些模式以支持 VM 和 Hypervisor 之间关于中断和异常的更严格接口。第一种模式称为 受限注入(Restricted Injection),禁用虚拟中断排队并部分禁用中断注入接口。在此模式下,Hypervisor 只允许注入一个新定义的异常向量 #HV, 作为门铃。受限注入假设 VM 和 Hypervisor 将以半虚拟化方式通信事件,如共享内存中的事件队列。#HV 异常可以作为通知客户机重新扫描事件队列以获取新信息的信号。

第二种模式称为 替代注入(Alternate Injection),允许标准的虚拟中断排队和注入接口,但这些只能由客户机自身控制。加密保存区域(称为虚拟机保存区域或 VMSA)中添加了新字段,允许中断排队和事件注入。由于这些字段在 VMSA 中,它们只能由有权访问客户机 VMSA 数据的人操纵,如 VMPL0。在替代注入模式中,所有与中断相关的安全敏感状态(如 TPR)都保存到 VMSA,因此不能被恶意 Hypervisor 操纵。

![[Pasted image 20260512164821.png]]

这两种模式结合使用,使 VMPL0 能够执行中断处理和 APIC 仿真。用于运行 VMPL0 的 vCPU 可以启用受限注入运行,使其使用半虚拟化接口和 #HV 异常与 Hypervisor 通信。用于运行其他 VMPL(假设客户机的主 OS 在其中运行)的 vCPU 可以启用替代注入运行。这样,VMPL0 可以在安全的时候向主 OS 注入事件和虚拟中断。从软件角度来看,主 OS 可以使用标准的 APIC 接口而无需修改。


可信平台信息

平台功能和能力传统上通过 CPUID 指令发现。Hypervisor 通常出于各种原因陷入并仿真 CPUID 指令,包括限制客户机可能使用的功能以便于迁移。在许多情况下,恶意 Hypervisor 只能通过对 CPUID 功能撒谎来对客户机造成拒绝服务。

然而在某些情况下,不正确的 CPUID 信息可能会导致安全问题。例如,对 x86 扩展保存区域(与 XSAVE/XRSTOR CPU 指令一起使用)大小撒谎的 Hypervisor 可能导致客户机分配一个太小的内存区域,并在执行硬件 XSAVE 指令时发生缓冲区溢出。虽然在许多情况下客户机 VM 可以尝试验证它收到的 CPUID(例如,检查报告的 XSAVE 缓冲区大小是否正确),但这可能具有挑战性,特别是在启动过程中。

为了简化客户机必须执行的检查,SEV-SNP 支持一个可选功能,通过 AMD-SP 过滤 CPUID 结果。AMD-SP 将验证 Hypervisor 报告的 CPUID 结果不超过平台的能力,并且安全敏感信息(如 x86 扩展保存区域大小)是正确的。

CPUID 过滤可以即时完成,也可以作为客户机启动的一部分完成。对于即时过滤,在接收到 CPUID 信息后,客户机可以请求 AMD-SP 验证安全敏感信息是否正确。或者,在 VM 启动期间,可以创建一个特殊的 "CPUID 页面 ",其中包含来自 AMD-SP 的预验证 CPUID 信息,允许客户机从早期启动开始就访问可信的 CPUID 信息。除了安全优势外,此特殊页面允许更快地访问 CPUID 信息,这可以加速 VM 启动过程。


TCB 版本控制

在 SEV-SNP 架构中,有几个可升级的固件组件,包括 AMD-SP API、CPU 微码补丁等。由于这些固件组件在 SEV-SNP 威胁模型中被视为可信的,它们构成了架构的 TCB。随着漏洞修复或功能升级,这些组件的新版本可能会发布。如果在其中一个组件中发现安全漏洞,客户机所有者可能需要保证其 VM 运行在已修补的固件下而不是易受攻击的版本。

先前的 SEV 和 SEV-ES 功能依赖于 AMD-SP 自报告的版本号来实现 TCB 版本控制。客户机所有者可以指定 AMD-SP 固件的最低版本,VM 不能加载在较旧的版本上。在 SEV-SNP 中,此检查已增强为具有加密强度。在 SEV-SNP 中,所有 TCB 组件的版本号与一个称为芯片背书密钥(Chip Endorsement Key)的熔丝秘密结合,创建一个版本化芯片背书密钥(VCEK)。VCEK 是一个私有 ECDSA 密钥,对每个 AMD 芯片唯一,在每个 TCB 版本上运行。VCEK 用于签署证明报告,因此任何证明报告的验证隐含地证明了签署报告的 TCB 版本。由于 VCEK 的派生方式,旧版本固件无法派生出新版本固件使用的相同密钥。这使得更新 TCB 组件成为一种有效的回滚缓解措施。


VM 启动与认证

与之前的 SEV 和 SEV-ES 架构一样,SEV-SNP VM 从初始未加密的镜像启动。此初始镜像预期包含客户机 VM 引导代码等内容,但由于它以未加密形式启动,不应包含任何秘密。在启动过程中,Hypervisor 请求 AMD-SP 在客户机中安装这组初始页面。AMD-SP 将这些页面的内容加密度量到启动摘要中。在 SEV-SNP 架构中,AMD-SP 还度量与这些页面关联的元数据,即页面被放置的 GPA 和它们的页面类型。这确保启动摘要捕获了初始客户机内存的布局及其内容。

在 SEV-SNP 中,在启动过程结束时,客户机所有者可以提供一个签名的身份块(IDB)与 VM 关联。IDB 包含允许客户机所有者唯一标识 VM 的字段,并包含预期的启动摘要。IDB 只能与匹配预期启动摘要的 VM 关联,并作为证明报告的一部分包含。

虽然 SEV 和 SEV-ES 仅在客户机启动期间支持认证,但 SEV-SNP 支持更灵活的认证。证明报告可以由客户机 VM 随时通过受保护的路径从 AMD-SP 请求。作为 SEV-SNP VM 启动的一部分,AMD-SP 创建一组私有通信密钥,客户机可以使用这些密钥直接与 AMD-SP 通信。客户机可以使用此路径请求证明报告、加密密钥等。

![[Pasted image 20260512170225.png]]

证明报告包含来自启动的 IDB 信息、系统信息,以及客户机 VM 作为报告请求一部分提供的任意数据块。证明报告由 AMD-SP 固件使用 VCEK 签名。证明报告使第三方(如客户机所有者)能够验证某些数据来自某个 VM。

例如,VM 可以发布一个公钥并请求 AMD-SP 提供一个包含此公钥哈希的证明报告,如图 10 所示。第三方然后可以通过证明报告验证此公钥与此 VM 关联。证明报告还证明 VM 运行时启用了适当的安全功能,并且它在真正的 AMD 平台上启动。因为证明报告由 VCEK 签名,此报告的验证同时证明了平台的真实性和所使用的 TCB 版本(因为 VCEK 是从 TCB 版本派生的)。成功认证后,第三方(如客户机所有者)可以选择向 VM 提供秘密,如磁盘解密密钥或操作所需的其他密钥。

除了远程认证,SEV-SNP 还支持生成客户机密钥材料的额外使用模式。SEV-SNP VM 可以直接从 AMD-SP 请求密钥用于各种目的,如数据密封。这些密钥可以从不同来源派生,VM 可以根据其用例的需要选择使用哪些来源。例如,可以请求本地密封密钥,这些密钥特定于当前特定 TCB 级别的部件和特定的 IDB 签名密钥。通过这些控制,VM 可以请求保证无法被恶意行为者或其他设备派生的密钥。


VM 迁移

VM 迁移,特别是实时 VM 迁移,是现代云架构的标准功能。实时 VM 迁移允许在需要负载均衡、主机系统维护和其他目的时,不中断地将一个 VM 移动到另一个物理系统。所有 SEV 技术都支持 VM 迁移,但 SEV-SNP 增强了与迁移相关的灵活性。

在 SEV 和 SEV-ES 中,VM 迁移由客户机所有者提供的策略决定。此策略指示 VM 是否可迁移,如果是则指示可以迁移到什么类型的系统。AMD-SP 负责强制执行此迁移策略,通过在开始迁移之前对目标机器上的 AMD-SP 进行身份验证来实现。

在 SEV-SNP 中,迁移策略执行的角色已卸载到一个称为迁移代理(MA)的新实体。MA 本身是一个运行在与主 VM 相同物理系统上的 SEV-SNP VM。当 VM 启动时,它可以选择性地与已运行的 MA 关联。关于 VM 的 MA 绑定信息存在于其证明报告中,因为 MA 是客户机 TCB 的一部分。每个 VM 只能与单个 MA 关联,但单个 MA 可以管理任意数量 VM 的迁移。

MA 负责确定主 VM 可以迁移到哪些系统。虽然 MA 架构的细节超出了本白皮书的范围,但 MA 可以使用其所需的任何手段实现复杂的迁移策略。

在典型的云场景中,MA 本身不可迁移。相反,MA 的单独实例运行在每台物理机上。当 VM 即将迁移时,源机器上的 MA 对目标机器上的 MA 进行身份验证并建立受保护的网络连接。如果成功,MA 传输所需的客户机信息,以便客户机可以在目标机器上重建。源 MA 然后可以选择销毁此客户机信息以完成迁移,或者可以选择保留它或将其放入长期存储。之后,此 VM 可以按照 MA 的意愿在同一台机器或另一台机器上重建。


侧信道

最近大量安全研究关注 CPU 侧信道攻击,即利用 CPU 内部结构来泄露信息的攻击。如 Spectre 等推测性侧信道攻击已被证明利用标准技术(如硬件分支预测)在某些场景中创建数据泄露。AMD 添加了硬件功能来帮助软件防御某些攻击,如 Spectre 变体 2。

Spectre 变体 2 证明了间接分支预测器(BTB)在某些软件环境下可以被利用,并假设攻击者能够影响另一个实体的分支预测。在最近的 CPU 设计中,AMD 添加了对 SPEC_CTRL MSR 和 PRED_CMD MSR 的支持,使软件能够更多地控制 BTB 结构。在 SEV-SNP 架构中,SPEC_CTRL MSR 被虚拟化,允许客户机独立于 Hypervisor 选择自己的推测策略。这允许客户机使用诸如 IBRS 等模式。

在传统虚拟化中,Hypervisor 采取措施保护自己免受基于客户机的攻击。这可能包括 retpoline 或在设置 IBRS 的情况下运行等技术。当 Hypervisor 不被信任时,客户机也可能担心基于 Hypervisor 的攻击。例如,恶意 Hypervisor 可能尝试投毒客户机将使用的 BTB 条目,或可能尝试使用另一个 VM 在 SEV-SNP 客户机运行之前投毒 BTB。

为了防范此类攻击,SEV-SNP VM 可以选择加入额外保护,其中 CPU 硬件将阻止 VM 推测性地使用由其他实体安装的 BTB 条目。此功能跟踪 BTB 条目何时由 Hypervisor 或其他软件安装,并在需要时自动执行 BTB 刷新,以使 SEV-SNP VM 不会推测性地使用那些 BTB 条目。

同步多线程(SMT)是 CPU 硬件中另一个侧信道研究关注的领域。由于 SMT 设计中的共享硬件资源,更多的观察通道是可能的。认为自己对此类观察特别敏感的 SEV-SNP VM 可以选择加入一个策略,限制它们只能在禁用 SMT 的系统上运行。

虽然 SEV-SNP 为客户机提供了几个关于防范推测性侧信道攻击和 SMT 的选项,但它无法保护所有可能的侧信道攻击。例如,对软件的传统侧信道攻击(如 PRIME+PROBE)不受 SEV-SNP 保护。这些类型的攻击需要专门针对容易受到这些类型侧信道攻击的软件算法,通常是因为它们涉及根据秘密值改变其缓存或 TLB 访问模式的代码路径。现代密码学库已针对此类攻击加固,且这些类型的攻击甚至可以在非虚拟化平台上发生。因为 SEV-SNP 硬件并非旨在明确防范此类攻击,VM 所有者有责任遵循标准安全实践,并确保其库和软件更新为不使用可能容易受到这些攻击的算法。

另一类超出 SEV-SNP 范围的侧信道攻击包括应用指纹攻击,如性能或页面故障监控。如前所述,SEV-SNP 主要关注保护 VM 内部的数据,而这些类型的攻击通常只尝试确定正在运行什么应用,不直接破坏客户机 VM 数据的机密性或完整性。未来版本的 SEV 可能包含对其中一些攻击向量的额外保护。


结论

SEV-SNP 代表了在不可信托管环境中运行的虚拟机的增强安全性和隔离级别。在提供数据机密性保护以防范潜在有漏洞的 Hypervisor 的 SEV 和 SEV-ES 功能基础上,SEV-SNP 增加了能够保护 VM 免受恶意 Hypervisor 攻击的完整性保证。除了完整性保护外,SEV-SNP 还以多个 VMPL、新的认证和密钥派生架构以及任意灵活的迁移策略的形式提供了新的架构灵活性。

SEV-SNP 还通过提供可选的保护来防范恶意中断注入、某些推测性侧信道攻击和 TCB 回滚攻击,进一步提高了安全标准。这些功能与之前的 SEV 和 SEV-ES 功能一样,被设计为在客户机操作系统级别启用,这意味着 VM 内部的应用程序不需要任何更改。

VM 隔离对于现代云计算环境是一项具有挑战性的任务。SEV-SNP 是第一个旨在同时支持隔离 VM 的机密性和完整性保护的 x86 架构,为各种工作负载实现更安全的云计算。AMD 相信安全云计算是未来数据中心的关键工作负载,而 SEV-SNP 是朝着这一目标实现的下一步。