https://docs.amd.com/v/u/en-US/Protecting-VM-Register-State-with-SEV-ES
AMD Secure Encrypted Virtualization (SEV) | AMD

![[Pasted image 20260306173420.png]]


2017 年 2 月
十年前的技术

最近,AMD 引入了安全加密虚拟化(SEV)技术 [1],该技术将内存加密与 AMD-V 虚拟化技术相结合,为加密虚拟机(VM)提供支持。加密虚拟机非常适合云计算等多租户环境,因为它们能够防范各种跨虚拟机以及基于虚拟机管理程序(Hypervisor)的攻击。例如,即使虚拟机管理程序存在漏洞,使得同驻虚拟机能够逃逸其沙箱并读取系统上的任意内存,该漏洞也无法用于窃取数据或破坏启用了 SEV 的虚拟机。

虽然没有任何安全系统是 100% 安全的,但 SEV 显著减少了云端虚拟机的攻击面。它通过使用虚拟机独有且对虚拟机管理程序未知的密钥,来对虚拟机内存进行加密。许多机密和重要信息通常存储在虚拟机的内存空间中,对这些内容进行加密有助于防止攻击和敏感数据泄露。

然而,当虚拟机正在使用这些机密信息时,它们往往不仅存在于内存中,还会驻留在 CPU 寄存器中。每当虚拟机因中断或其他事件停止运行时,其寄存器的内容就会被保存到虚拟机管理程序的内存中。即使启用了 SEV,虚拟机管理程序也能读取这部分内存。这些信息可能会让恶意或被破坏的虚拟机管理程序窃取机密,或者更改客户机状态中的关键值(例如指令指针、加密密钥等)。

新的带有加密状态的 SEV(SEV-ES)功能通过在==虚拟机停止运行时加密并保护所有 CPU 寄存器内容==,从而阻止了此类攻击。这可以防止 CPU 寄存器中的信息泄露给虚拟机管理程序等组件,甚至还能检测并防止对 CPU 寄存器状态的恶意修改。SEV-ES 在 SEV 的基础之上构建,为客户虚拟机提供了更小的攻击面,并增加了针对虚拟机管理程序的额外保护。

本文档提供了 SEV-ES 功能的技术概述、架构背后的原理,以及为进一步隔离加密虚拟机所提供的保护措施。有关更多技术细节,请参阅《AMD64 程序员手册》[2]。


安全目标


SEV-ES 技术旨在==保护客户虚拟机(VM)免受来自恶意虚拟机管理程序(Hypervisor)对其寄存器状态的攻击。这些攻击可能包括读取客户机寄存器值、写入恶意值,甚至将旧状态重放(Replay)回虚拟机中==。

恶意虚拟机管理程序读取客户机寄存器值可能会导致隐秘的数据泄露,例如,在使用 x86 AES 指令时,读取通常用于保存 AES 密钥的 XMM 寄存器。写入恶意值则可用于直接或间接地修改客户虚拟机的控制流,例如在恢复(Resuming)虚拟机时覆盖指令指针寄存器(RIP)。这种修改可能会导致客户虚拟机内部出现潜在的意外行为,例如跳过关键的安全检查。SEV-ES 对客户虚拟机的寄存器状态进行加密和完整性保护,以防范这些类型的攻击。

保护虚拟机寄存器状态的挑战在于:有时虚拟机管理程序确实需要访问虚拟机寄存器,以便提供诸如设备模拟、MSR(模型特定寄存器)处理等服务。必须严格控制这些访问以防止恶意利用,而此类恶意利用往往很难被察觉。

为了解决这个问题,SEV-ES 技术允许客户虚拟机根据具体情况,自行决定向虚拟机管理程序暴露哪些信息。这在原理上与 SEV 类似,在 SEV 中,由客户虚拟机控制并选择共享哪些内存页。将这种控制权限放置在客户虚拟机内部,使其既灵活又能针对不同的应用场景进行定制。


技术纵览

加密寄存器状态 (Encrypted Register State)

在传统的 AMD-V 架构中,保存和恢复客户虚拟机(VM)的寄存器状态是一个多步过程。用于将控制权转移给客户虚拟机的 VMRUN 指令,仅能保存和加载系统整体状态的一个子集 [2]。许多状态,包括 TR 等系统寄存器以及 RDX 等通用寄存器(GPR),都不会被 VMRUN 指令自动保存和恢复。在恢复客户机之前,典型的虚拟机管理程序(Hypervisor)还需要加载客户机的通用寄存器值,使用 VMLOAD 指令加载额外的系统状态,甚至可能还要使用 XRSTOR 指令来加载客户机的浮点寄存器状态。

SEV-ES 架构将这整个操作合并为一条单一的原子硬件指令:VMRUN。当为启用了 SEV-ES 的客户机执行 VMRUN 时,CPU 硬件会加载所有的客户机寄存器信息,包括系统寄存器、通用寄存器和浮点寄存器。同样地,当虚拟机停止运行(发生所谓的“VMEXIT”)时,硬件会自动将所有这些状态保存回内存,并加载虚拟机管理程序的状态。这一单一的原子过程确保了在虚拟机管理程序和客户机之间的环境切换(world switch)不会被中断,并且客户机的信息不会泄露给虚拟机管理程序。

当硬件保存和恢复客户机寄存器状态时,它是将状态保存到使用该虚拟机的内存加密密钥所加密的内存中。任何 CPU 上的软件都不知道这个密钥,虚拟机管理程序也无法使用它,因此虚拟机管理程序无法读取实际的客户机寄存器状态。此外,在保存寄存器状态时,CPU 会计算一个完整性校验值。该校验值保存在任何 CPU 软件都无法访问的受保护 DRAM 中。当 CPU 稍后使用 VMRUN 恢复该客户机时,会检查这个值,以确保客户机寄存器状态没有被虚拟机管理程序篡改。

因此,SEV-ES 架构不仅确保了客户机寄存器内容可以对虚拟机管理程序保密,还确保了虚拟机管理程序无法轻易地操纵或重放这些状态。如果自上一次 VMEXIT 以来寄存器状态被修改,完整性校验值就能检测出这种篡改;如果校验值不正确,CPU 将拒绝恢复该客户虚拟机。换言之,客户虚拟机只能恢复到它最后一次运行时的、完全相同的状态。


PXOR %xmm0, %xmm1
AESENC %xmm0, %xmm2
AESENC %xmm0, %xmm3
Interrupt (中断)

(客户机模式 Guest Mode) -> (虚拟机管理程序模式 Hypervisor Mode)

VMRUN
Read %xmm1 (读取 %xmm1)
send to attacker (发送给攻击者)

图 1:从虚拟机中窃取 AES 密钥

请注意,在 SEV-ES 架构中,用于描述特定虚拟机的 虚拟机控制块(VMCB, Virtual Machine Control Block) 被分为了两个部分:

  1. 控制区 (Control Area):由虚拟机管理程序拥有和管理。控制区包含诸如虚拟机管理程序希望拦截哪些事件、中断传递信息等内容。
  2. 保存区 (Save Area):用于存储虚拟机寄存器状态。当启用 SEV-ES 时,正如前文所述,该区域将被加密并受到完整性保护。

![[Pasted image 20260306174446.png]]


虚拟机“退出” (VM “Exits”)

执行 VMRUN 指令后,CPU 硬件会继续执行客户虚拟机(VM),直到发生退出事件,这被称为 VMEXIT。可能导致 VMEXIT 的具体事件由 AMD64 架构 [2] 定义,并由虚拟机管理程序(Hypervisor)通过设置 VMCB 控制区中的“拦截位(intercept bits)”来进行配置。

例如,虚拟机管理程序可以设置相关拦截位,配置在外部中断、写入控制寄存器、读取特定端口等情况下触发 VMEXIT。在传统的 AMD-V 架构中,当 VMEXIT 事件发生时,CPU 硬件会将控制权交还给虚拟机管理程序,并附带一个事件代码来指示引发 VMEXIT 的原因。

在 SEV-ES 架构中,可能触发的 VMEXIT 事件集合被划分为两组,分别称为 自动退出(Automatic Exits, AE)非自动退出(Non-Automatic Exits, NAE)

当启用 SEV-ES 时,AE 事件是唯一会导致完整环境切换(full world switch)并将控制权交还给虚拟机管理程序的 VMEXIT 事件。正如上一节所述,这些事件会触发 CPU 硬件自动保存并加密所有客户机寄存器状态,同时加载虚拟机管理程序的状态。在虚拟机管理程序完成其所需的任何任务后,它可以通过 VMRUN 指令恢复客户虚拟机,从而将控制权转移回客户虚拟机被挂起时的那个执行点。

与 AE 事件不同,NAE 事件始终是由于客户虚拟机内部的特定行为引发的,例如执行了特定的指令、访问了模拟设备的寄存器等。与传统的 AMD-V 虚拟化不同,当启用 SEV-ES 时,这些事件 不会 导致环境切换回虚拟机管理程序。相反,当 NAE 事件发生时,硬件会生成一个新的异常 —— #VC(VMM 通信异常,VMM Communication Exception),并且这个异常必须直接由客户虚拟机自行处理。

![[Pasted image 20260306175150.png]]

VMM 通信异常 (#VC)

新的 #VC 异常通知客户虚拟机(VM)操作系统:它刚刚执行了一个需要虚拟机管理程序(Hypervisor)进行模拟的事件。随后,#VC 异常处理程序必须决定如何响应,并向虚拟机管理程序请求适当的服务。

图 2:虚拟机控制块 (VMCB) (注:如文本中的图示说明,VMCB 分为两部分)

客体 - 虚拟机管理程序通信块 (GHCB)

为了促进这种通信,SEV-ES 架构定义了客体 - 虚拟机管理程序通信块(GHCB, Guest Hypervisor Communication Block)。GHCB 驻留在一个共享内存页中,因此客户虚拟机和虚拟机管理程序都可以访问它。SEV-ES 架构并没有明确定义 GHCB 的具体结构,但建议使其与 VMCB 的保存区结构保持一致,以便客户机和虚拟机管理程序能够轻松地交流状态信息。

不同的事件需要在客户机和虚拟机管理程序之间传递不同的状态信息。因此,#VC 处理程序必须在运行时动态决定应当向虚拟机管理程序暴露哪些客户机状态:

为了共享所需的信息,#VC 处理程序会将相关的状态片段以及对虚拟机管理程序服务的请求复制到 GHCB 中。通过这种方式,#VC 处理程序全权负责筛选并决定将哪些状态暴露给虚拟机管理程序。

VMGEXIT 指令与模拟响应

在将相关状态复制完毕后,#VC 处理程序会使用新的 VMGEXIT(虚拟机通用退出,Virtual Machine General Exit) 指令将控制权转移给虚拟机管理程序。该指令会触发一次 AE(自动退出)事件,从而安全地保存所有客户机状态,并恢复虚拟机管理程序的执行。

此时,虚拟机管理程序会读取 GHCB,以确定客户机所需的模拟支持。由于虚拟机管理程序无法直接修改客户机内部的加密状态,它必须在外部执行所需的模拟操作,并将返回给客户机的任何新状态值 放回 GHCB 中

例如,在完成 CPUID 模拟之后,虚拟机管理程序应该将 RAX/RBX/RCX/RDX 的新值写入 GHCB 中。


当虚拟机管理程序恢复客户虚拟机时,代码将从 VMGEXIT 指令之后的挂起位置继续执行,此时程序仍处于 #VC 异常处理程序内部。现在,该处理程序可以检查虚拟机管理程序在 GHCB 中返回(或请求)的状态更改,并自行判断这些更改是否可接受。如果确认无误,处理程序就会将这些新状态值复制到相关的寄存器中,并结束异常处理流程。

图 3:NAE 示例流程 (NAE Example Flow) 展示了 #VC 处理程序的这一完整执行过程。

![[Pasted image 20260306180219.png]]


这段文本很好地总结了客户虚拟机如何验证并应用虚拟机管理程序返回的数据,从而彻底闭环了整个安全通信机制,确保恶意虚拟机管理程序无法通过伪造返回值来破坏虚拟机的状态。


初始化 SEV-ES 虚拟机 (Initializing SEV-ES VMs)

SEV-ES 虚拟机的初始化与现有的 SEV 虚拟机非常相似 [3]。需要注意的是,在 SEV-ES 中,初始内存映像以及初始 CPU 寄存器状态都必须由 AMD 安全处理器(AMD-SP)进行加密,随后客户虚拟机(VM)才能开始执行。

在此初始化过程中,AMD-SP 会对内存映像和初始 CPU 寄存器状态进行密码学测量(measured cryptographically),从而生成一个启动凭据(launch receipt),该凭据可用于对客户机进行证明(attestation)。这种证明机制使得客户虚拟机的所有者能够在向其释放(或注入)机密信息之前,验证该虚拟机是否已使用正确的映像和寄存器状态成功启动。

软件影响 (Software Impact)

与 SEV 功能一样,支持 SEV-ES 不需要修改任何应用程序代码,只有客户机操作系统(Guest OS)和虚拟机管理程序(Hypervisor)会受到影响。具体而言,客户虚拟机操作系统必须支持处理新的 #VC 异常,并能与虚拟机管理程序进行通信以获得所需的模拟支持。需要注意的是,由于所有 NAE(非自动退出)事件都会引发新的 #VC 异常,因此客户虚拟机操作系统内的驱动程序不需要进行修改,也不要求它们具备感知 SEV-ES 存在的能力。所有出于模拟目的而与虚拟机管理程序进行的通信,都是通过一个单一的集中式处理程序来完成的。

由于在启用 SEV-ES 时无法查看客户机的寄存器状态,虚拟机管理程序软件必须支持新的 GHCB 结构,以便与客户机的 #VC 处理程序进行通信。在许多情况下,这仅仅意味着在响应模拟请求时,去读取或写入 GHCB 结构,而不是原先的 VMCB。此外,在 SEV-ES 架构中,许多与模拟相关的任务(例如指令解码/重新执行,instruction cracking/re-execution)实际上被转移到了客户机内部的 #VC 处理程序中,这意味着虚拟机管理程序所需要承担的模拟支持工作量大幅减少。

性能优化 (Performance Optimizations)

虽然 SEV-ES 的主要目标是保护客户机寄存器状态并让客户机掌控哪些内容可以被访问,但 #VC 异常机制也为优化客户机与虚拟机管理程序之间的通信提供了一个契机。特别是,客户机的 #VC 处理程序可以潜在地实现某些逻辑,从而减少环境切换(world switches)的次数,和/或完全在客户机内部自行处理特定的 NAE 事件。例如,#VC 处理程序可以缓存静态值(例如 CPUID 指令的执行结果),或者将对虚拟机管理程序的多个请求批量合并为单次 VMGEXIT 操作。支持此类优化可能需要客户机和虚拟机管理程序之间进行一些特定的通信配合。


结论 (Conclusion)

SEV-ES 功能提供了额外的硬件级安全保障,用于将客户虚拟机(VM)与虚拟机管理程序(Hypervisor)隔离开来。它建立在 ==SEV 提供的内存保护基础==之上,为==客户机的寄存器状态提供机密性和完整性保护==,以防止虚拟机管理程序造成的信息泄露和控制流篡改。SEV-ES 赋予了客户虚拟机在任何时候都能控制虚拟机管理程序可以查看和修改哪些状态片段的能力,从而能够在不需要对设备驱动程序和虚拟机管理程序进行重大更改的情况下,支持现有的功能(例如设备模拟)。

虽然 SEV 通过内存加密减少了虚拟机的攻击面,但对客户机寄存器状态的保护使这种防护更进一步,从而针对被破坏的(compromised)虚拟机管理程序提供了更全面的安全保护。

参考文献 (References)

[1] AMD 内存加密白皮书 (AMD Memory Encryption Whitepaper): http://amd-dev.wpengine.netdnacdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

[2] AMD64 程序员手册第 2 卷 (AMD64 Programmer’s Manual Volume 2): http://support.amd.com/TechDocs/24593.pdf

[3] 安全加密虚拟化密钥管理规范 (Secure Encrypted Virtualization Key Management): http://support.amd.com/TechDocs/55766_SEVKM%20API_Specification.pdf