LWN: 限制DMA访问区域!

关注了就能看到更多这么棒的文章哦~

Restricted DMA

By Jonathan Corbet
January 7, 2021
DeepL assisted translation
https://lwn.net/Articles/841916/

系统加固(system hardening) 中的一个关键就是要限制访问内存。这也包括要阻止内核对内存的访问,大多数时候都不应该允许访问或修改系统中的绝大部分内存区域。不能被访问的内存区域,就不会被攻击者读取或修改了。不过在许多系统中,这些访问限制并不能约束外设行为,它们可以轻松地使用直接内存访问(DMA)来访问到绝大多数系统内存区域。最近发布的 restricted DMA patch set 的目的就是通过限制 DMA 操作可以访问到的内存区域,从而减少暴露给错误或恶意的设备动作的攻击面。

DMA 允许 device 直接读取或写入系统内存。除非是那些非常慢速的设备,否则要想让 device 能拥有合理的 I/O 性能,就需要 DMA。通常情况下,内核会负责管理 DMA 操作,设备驱动程序来分配缓冲区(buffer),并告知 device 在这些缓冲区上执行 I/O 操作,一切都能按预期那样正常工作起来。但如果驱动程序或硬件包含错误的话,DMA 传输就有可能覆盖一些不相关的内存区域,导致系统损坏,用户会有抱怨。而那些恶意的(或本身已经被入侵的)硬件可以使用 DMA 来破坏这个硬件所连接的系统,使用户收到更大伤害。多年来,这种类型的攻击已经有很多例子了(https://blade.tencent.com/en/advisories/qualpwn/)。

解决这个问题的方法之一,就是在 device 和 memory 之间加一个 I/O 内存管理单元(IOMMU, I/O memory-management unit)。内核对 IOMMU 进行设置,从而允许对特定的内存区域的访问,然后 IOMMU 就能确保 device 访问到超出这个区域的地址。但并不是所有的系统都配备了 IOMMU,它们大多都是在台式机、数据中心等大型处理器中存在。移动设备通常不会带 IOMMU。

由 Claire Chang 发布的 restricted DMA patch set,就是试图对没有 IOMMU 的系统上的 DMA 操作进行限制。它建立在一个古老的、相对少用到的内核机制上,也就是 "swiotlb",它指的是 "software I/O translation lookaside buffer"。swiotlb 最初创建出来是为了便于操作那些 DMA 操作中有很烦人的一些限制的设备的,比如有的 DMA 无法访问到系统中所有的内存区域。swiotlb 使用的核心机制是 bounce buffering:在 device 能够访问的区域分配一个缓冲区 buffer,然后需要在 I/O 缓冲区和这个 bounce buffer 之间进行数据复制。复制数据显然会减慢 I/O 操作的速度,但这比完全不使用 DMA 要好得多。

Chang 的 patch set 增强了 swiotlb 的功能,允许它分配特定范围的物理内存,并将其与指定的设备关联起来。这个范围可以在 devicetree 中使用新增的 restricted-dma-pool 这个 "compatible" property 来设置。所有牵涉到该设备的 DMA 操作都将使用这个内存范围来进行弹跳(这就是 bounce buffer 名称的由来),从而有效地将 device 与系统其他部分所看到的实际 I/O buffer 区域隔离开来。

使用这种 bounce-buffering 机制本身就有一些好处。编者过去写过设备驱动程序,虽然我绝不会犯这样的错误,但确实听到过有驱动程序的中 bug 导致 device DMA 读写了系统中错误的地址的情况。如果内存缓冲区随机地被写坏,并且无法固定复现这种问题,那么就可能会导致数据损坏、痛苦的 debug 过程、以及需要借酒浇愁了(同样,编者可没有犯过这种错误)。将 device 使用的 buffer 与内核使用的 buffer 分开,restricted DMA 改动就是通过这种方法来减轻这类 bug 带来的许多痛苦经历。

读者可能会想要知道,使用 swiotlb 是如何保护系统不受恶意或被入侵的 device 的影响的,毕竟这些设备很可能会根本无视软件中将其 DMA 活动限制指定区域的这些设置的。答案是,无法阻止这种攻击——至少,仅靠这个功能是无法实现的。实际上这个改动的目的是将 restricted DMA 与 trusted firmware(https://www.trustedfirmware.org/about/) 搭配起来,trusted firmware 能够将 DMA 操作限制在特定的内存范围内,这些限制是在启动之时(或启动之前)就设置好的,内核无法更改。这样一来,trusted firmware 就可以限制设备只访问指定区域了,而 restricted DMA 机制则会让所有的 DMA 操作都要经过该区域。这两种机制共同配合,就可以达到在不使用系统 IOMMU 的情况下也能限制 DMA 随意访问内存的目的了。

这里需要不少 setup 工作,,因此这种功能在大多数通用系统(general-purpose)上都不会很快得到应用。但在那些受到严格控制的系统上(比如例如移动设备)还是很希望能得到阻止恶意设备访问的功能的。目前还不清楚这个 restricted DMA patch 是否当前的版本就足以达到进入 mainline 的标准了,但它很可能迟早会被合入 Linux kernel。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值