概述
本文介绍了一种基于软件的、安全高效的GPU TEE。Honeycomb的关键思想是利用静态分析来验证GPU应用程序在加载时的安全性。与CPU TEE共同设计,以及添加操作系统和驱动程序支持,Honeycomb能够将操作系统和驱动程序从可信计算基础(TCB)中移除。验证还确保系统内的所有应用程序都是安全的,使通过GPU上的共享设备内存以明文形式交换数据成为一种简洁而安全的方法。
架构
1.Honeycomb
在AMD SEV-SNP TEE VM中启动一个应用。首先在VMPL0中启动SVSM。SVSM在VMPL1中引导BIOS,虚拟机Linux内核,用户空间的应用。SVSM控制所有的应用与GPU的交互。应用程序从Honeycomb中请求GTT内存用来与GPU进行交互。GTT内存可以作为内存副本的临时缓冲区。Honeycomb将GPU隔绝在sandbox VM中。安全监管者(SM)是一个管理程序负责管理驱动和GPU的交互。它确保GPU遵循特定的初始化顺序和持续跟踪设备内存页的所有权以便阻止在所用应用内设备内存的偶然共享。
2.验证器模块
为了执行GPU内核,应用首先加载包含GPU内核的二进制文件。验证器在Honeycomb中获取GPU内核的二进制代码和附带的前提条件作为输入。它验证每一条在GPU内核中的内存指令只能访虚拟地址空间的某些区域。验证器解码GPU内核的指令重构它的控制和数据流。它利用标量演化和多面模型将每一条内存指令的目标地址表示为符号表达式。它插入前提条件去判断目标地址的范围并且确保地址处在具体的区间内。
验证器要确保内核代码符合以下规定:
- 无悬空访问。GPU内核不可以从硬件寄存器中读取未初始化的值。
- 所有内存访问应在他们的区间内。所有内存访问的区间应该符合他们的访问政策。
- 控制流完整性。执行必须在设计好的GPU内核入口点处开始。内核仅仅可以传输它的控制到基本块的入口点。
验证器执行访问控制。有效地将GPU应用程序的虚拟地址空间划分为四个区域:受保护、只读(RO)、读写(RW)和私有,每个区域具有不同的访问策略。例如,应用不允许修改RO区域,但可以完全访问私有区域。Honeycomb将二进制代码和参数放在RO区域,以便恶意内核在通过验证后不能动态修改代码。此外,Honeycomb通过将缓冲区映射到不同的区域来实现安全IPC。蜂窝将IPC缓冲区映射到发送方的保护区和接收方的RO区。发送方调用可信的send()端点,将明文数据复制到IPC缓冲区,在该缓冲区中保密性和完整性都得到了保护。
3.安全监视模块
- 初始化。 Honeycomb强制不可信的GPU驱动遵循一个正确的初始化顺序。
- 启动GPU内核。 应用程序调用相同的用户空间API来启Honeycomb上的GPU内核。首先,应用程序调用hipModuleLoadData()来加载GPU二进制文件。API的实现将捕获到SVSM中,在那里SVSM验证内核,然后将内核复制到受保护的区域,并在它们通过验证的情况下记录它们的先决条件。
- 隔绝地址空间。 在CPU端,Honeycomb利用SEV-SNP TEE中的现有机制来强制不同应用程序之间的隔离。在GPU端,SM拦截驱动程序和GPU之间的所有流量,以维护一个类似于Graviton[83]的RMP表,以跟踪页面的所有权。
- 安全数据传输。 Honeycomb实现了GPU和主机CPU之间的安全数据通信通道,并协调所有进出GPU设备内存的数据传输
4.安全高效的IPC
Honeycomb允许两个enclave在设备内存中安全地交换明文数据。为了创建IPC, Honeycomb将IPC缓冲区映射到发送方的保护区域和接收方的RO区域。发送方调用send()来启动IPC。send()是一个受信任的端点,它只是将数据复制到受保护的区域并更新IPC缓冲区的索引。接收端的GPU内核可以直接读取RO区域,但需要通过Honeycomb提供的recv()来更新索引。该方案是安全的,因为用户应用程序中的GPU内核不能访问保护区域,也不能写RO区域。