SEV-SNP隔离原理:NPT、RMP与硬件强制
hypervisor 负责翻译地址,可它自己又不可信——SEV-SNP 是怎么让”不可信的管家”干活、又防住它偷东西的?
📚 基本概念速读
| 名称 | 定义 | 省流 |
|---|---|---|
| hypervisor | 虚拟机监控器(VMM) | 云上管虚拟机的软件层 |
| 嵌套分页 | Nested Paging,两层地址翻译 | 虚拟机地址翻译机制 |
| NPT | Nested Page Table,嵌套页表 | hypervisor 建的翻译规则 |
| RMP | Reverse Map Table,反向映射表 | 硬件记录的”物理页归谁”事实 |
| RMPE | RMP Entry,RMP 条目 | 每 4KB 物理页一条记录 |
| ASID | Address Space Identifier,地址空间标识符 | 每个 CVM 的唯一身份编号 |
| VMCB | Virtual Machine Control Block,虚拟机控制块 | 存 VM 状态和 ASID 的控制块 |
| VMRUN/VMEXIT | 进出虚拟机的特权指令 | 硬件切换”当前身份”的开关 |
| VMPL | Virtual Machine Privilege Level,虚拟机特权级 | VM 内部的 4 级权限 |
| PSP | Platform Security Processor,平台安全处理器 | AMD CPU 里的独立安全小电脑 |
| #PF | Page Fault,缺页异常 | 硬件拒绝访问时的信号 |
🧩 为什么需要 SNP:第一代 SEV 的漏洞
先看虚拟机地址翻译。虚拟机里的地址要翻译两次才能到真实物理地址:
1 | Guest 认为的地址(GVA) → Guest 页表 → Guest 物理地址(GPA) |
这里的 NPT 由 hypervisor 管理。问题来了:hypervisor 不可信,它可以:
| 攻击 | 做法 | 后果 |
|---|---|---|
| 偷换内容 | 把 VM 的某个 GPA 悄悄重映射到别的物理页 | VM 读到被替换的假数据 |
| 数据串扰 | 把 VM 的页映射给另一个 VM | 两个租户数据互相泄露 |
| 直接偷读 | 把自己映射到 VM 的页 | 读取 VM 内存 |
第一代 SEV 只做内存加密,防不了这种重映射/篡改。加密只保证”别人读不懂”,但 hypervisor 可以”把读的对象换掉”。这就是 SNP 要补的洞。
🔍 RMP:反向映射表,硬件管的”所有权事实”
SNP(Secure Nested Paging,安全嵌套分页) 的核心是引入 RMP(Reverse Map Table,反向映射表):
1 | RMP:每 4KB 物理页一行,硬件强制记录: |
“反向”的含义:NPT 是 hypervisor 往前翻译”地址去哪”,RMP 是硬件反过来锁”这页是谁的、谁才能动”。
一句话对比:
| 表 | 谁维护 | 管什么 | 本质 |
|---|---|---|---|
| NPT | hypervisor(软件) | 地址往哪翻 | 路由规则 |
| RMP | CPU 硬件 | 翻过去之后你有没有资格碰 | 所有权事实 |
hypervisor 能改路由规则,但改不了所有权事实——事实由 PSP 固件锁定。所以 hypervisor 怎么折腾 NPT 都是白费力气,最终判定权在硬件手里。
🔒 硬件强制执行是怎么实现的
“硬件强制执行,谁也绕不过”靠两把锁:
锁 1:RMP 表的内容,软件改不了
1 | RMP 表本身也是内存里的一个区域,但是: |
锁 2:检查逻辑固化在硬件翻译路径里,软件绕不过
1 | RMP 检查不是"一段软件代码",而是 CPU 微码/硬件逻辑的一部分, |
类比:高速公路入口的自动测速摄像头——你(hypervisor)只能决定”开多快”(建 NPT 规则),但摄像头拍不拍、罚不罚,是硬件自动执行的,你没有权限关掉它。
🪪 访问者身份怎么判定:ASID
ASID(Address Space Identifier,地址空间标识符)——每个 CVM 一个唯一编号。身份从哪来?怎么保证伪造不了?
1 | ① 每个 CVM 启动时分配一个 ASID(如 VM-A=16, VM-B=17) |
判定流程(硬件完成,一次访存):
1 | 访存到达物理页 SPA |
为什么软件伪造不了身份?
1 | · "当前 ASID"是 CPU 内部状态,由 VMRUN / VMEXIT 这两个特权指令 |
类比:VMRUN 就是”刷门禁卡进房间”,CPU 是门禁系统本身。门禁系统自己知道”现在里面是谁”——它不需要房间里的人来汇报身份,因为它就是放你进去的那个系统。
🧩 关键澄清:hypervisor 只是”提供规则”,不是”执行翻译”
这是最容易混的点。页表是谁建的 ≠ 翻译是谁执行的:
1 | 你以为的访存路径: |
关键事实:GPA→SPA
的翻译虽然规则表(NPT)是 hypervisor
写的,但翻译这个动作是 CPU 硬件执行的,hypervisor
的代码根本没机会跑在访存路径上。NPT 是 hypervisor 画的”地图”,但走路的是
CPU。
最后一块拼图:hypervisor 造假 NPT 也没用
1 | hypervisor 写 NPT:VM-A 的 GPA X → 物理页 P(其实是 VM-B 的页) |
📋 典型场景对照
| 访问者身份(当前 ASID) | 目标页归属(RMPE.ASID) | 判定 |
|---|---|---|
| VM-A (16) | 16(自己) | ✅ 允许 |
| VM-A (16) | 17(VM-B 的页) | ❌ 拒绝 |
| hypervisor | 16(CVM 的页) | ❌ 拒绝 |
| hypervisor | 未分配页 | ✅ 允许(host 自己的内存) |
补充两个细节:
- VMPL(Virtual Machine Privilege Level):SEV-SNP 还给每个 VM 内部划分 4 个特权级(VMPL0~3),RMPE 里分别记录各级的读/写/执行权限。ASID 管”是不是这家的”,VMPL 管”这家里面谁有权碰”。
- 设备 DMA 同样受限:设备要通过 IOMMU(AMD-Vi)访问内存,IOMMU 域也关联 ASID,hypervisor 不能直接把设备 DMA 指向 CVM 的私有页。
⚠️ 常见误区
| 误区 | 正解 |
|---|---|
| hypervisor 查 RMP | 查 RMP 的是 CPU 硬件,不是 hypervisor——它是裁判,不能当运动员 |
| hypervisor 执行地址翻译 | 翻译由 CPU 的 MMU 硬件执行,hypervisor 只提供 NPT 规则表 |
| hypervisor 改 NPT 就能访问 CVM 内存 | NPT 是路由规则,RMP 是所有权事实,路由改了也过不了所有权检查 |
| 内存加密就够防篡改 | 加密只防”读不懂”,SNP/RMP 才是防”偷换、重映射”的关键 |
| ASID 是软件声明的身份 | ASID 是硬件通过 VMRUN/VMEXIT 自动维护的内部状态,软件伪造不了 |
| RMP 表软件可以随便改 | RMP 区域对软件保留,唯一入口 RMPUPDATE 由 PSP 固件把关 |
✅ 总结
SEV-SNP 用 RMP 把”物理页归谁”这个事实从软件手里夺走,交给硬件记录并强制执行;翻译和判定都由 CPU 硬件执行,hypervisor 只提供页表规则;“当前访问者”是硬件通过 VMRUN/VMEXIT 自动维护的 ASID 状态,谁都无法伪造——NPT 管”地址往哪翻”,RMP 管”翻过去之后你有没有资格碰”。
下一站:TPM——用户能直接摸到的白盒信任根。
Happy Hacking! 🎉