本文发表于USENIX’24,提出了一种通过验证指针完整性来防御DMA攻击的硬件设计。DMAAUTH 采用了一种名为 “可运算指针验证(APAC)”的方法,在支持指针运算的同时保护DMA指针的完整性。本文在FPGA上实现了 DMAAUTH的原型并进行了全面评估,在网卡和SSD上的性能开销表现在0.9%-8.6%。同时还在支持了ARM 和 RISC-V 仿真器上的实现,以展示其跨体系结构的能力。
PROBLEM
IOMMU 提供了地址空间隔离功能,使设备只能访问允许的页面,而无法访问其他内存,一定程度上缓解了许多DMA攻击。但是最近的研究表明绝大多数的系统上都没有开启IOMMU的功能,因为地址转换和TLB刷新带来的开销过大。并且,即便是开启了IOMMU的系统也仍然暴露在安全威胁下。本文将DMA攻击分为两种类型,分别是空间和时间攻击。
空间攻击即sub-page攻击,由于IOMMU是基于页面粒度的,因此无法防止外设访问和IO buffer位于同一个页面上的内核数据,恶意的设备就可以获取敏感信息或者劫持控制流。时间攻击是指deferred IOTLB invalidation引起的TOCTTOU攻击,IOMMU为了优化性能,通常使用延迟TLB刷新的模式,在延迟的时间窗口内,恶意的外设就可以访问已经取消映射但是TLB条目尚未刷新的内存。
Workflow
如下图所示。❶当设备需要进行DMA时,内核会分配一个内存对象,但只允许设备访问该对象的一部分(图中标记为 I/O Buffer 的块)。❷内存分配后,内核显式地将缓冲区映射到外设页表中,并得到一个DMA指针,在没有启用 IOMMU 的情况下,DMA 指针是一个物理地址,而在启用 IOMMU 的情况下,DMA 指针是一个 IOVA。❸内核会为每个映射生成元数据,其中包含缓冲区的边界和随机标识符。❹接下来,内核使用元数据和key对DMA指针进行签名,以保护指针和元数据。将签名后的ACPA指针传给设备。❺设备接收到指针后发起DMA访问请求,DMAAUTH硬件拦截请求,I/O 总线上的Authenticator会首先获取元数据,然后使用整个元数据条目来验证指针签名,以确定指针是否是伪造或者已经过期的。此外,Authenticator还会进一步使用元数据中的边界来检查访问是否在buffer的合法范围内。❻ 如果指针通过了完整性和边界检查,Authenticator解密ACPA指针,得到一个合法的物理地址或 IOVA,以继续外设的数据访问请求。
Arithmetic-capable Pointer Authentication
由于DMA请求中时常会使用到指针运算,现有的ARM指针验证方案不支持运算,所以本文提出了一种支持指针运算的验证方法。主要的idea是只对指针的高位部分进行签名,使用低位进行偏移运算。一个ACPA的指针由三部分组成,从低位到高位分别是偏移位、基本位、签名,如下图所示。在确定偏移位长度后,内核使用基本位来签名和验证指针,而跳过偏移位。具体来说,内核将基本位作为 QARMA 加密引擎的输入,以生成指针签名。另外两个输入是每个映射元数据中的标识符和加密密钥。签名后内核会将其嵌入APAC指针未使用的高位。
当外设使用APAC指针进行DMA时,指针验证由总线上的Authenticator进行。首先通过签名定位元数据表中对应的元数据,获取元数据后,Authenticator验证偏移位的大小是否超出buffer的边界,并开始验证指针,以确定指针是否由外设伪造。如果外设向 APAC指针添加了合法偏移量,则指针的基本位保持不变,因此验证器重新计算的签名也保持不变。一旦指针运算导致偏移量字段溢出或不足,就会改变 APAC 指针的基本位。这样所有的非法内存访问都会被拒绝。
原文始发于微信公众号(COMPASS Lab):论文分享|DMAAUTH