从零读懂RDMA的钥匙机制:硬件如何用L_Key/R_Key保护你的内存

从零读懂RDMA的钥匙机制:硬件如何用L_Key/R_Key保护你的内存 在RDMA传输过程中数据从一端传递到另一端CPU全程不插手。但这带来一个致命问题没有CPU把关网卡怎么知道哪个内存能读、哪个能写万一恶意程序指着一块内核内存让网卡去DMA岂不是直接崩了整个系统而这就是L_Key和R_Key要解决的核心问题——给每块注册过的内存配一把“硬件级的门禁卡”。网卡在访问内存之前必须先刷卡验证通不过就拒绝。关键是这个验证过程完全由网卡硬件完成不需要CPU参与也不依赖操作系统。一、L_Key和R_Key长什么样IB规范明确定义了L_Key和R_Key的格式高24位是索引低8位是标签key。或者换一个角度这两把钥匙其实是同一把锁的不同副本它们的高24位索引都是指向同一个MPT条目的“门牌号”而低8位标签是校验码。这两把“钥匙”在内核/硬件眼中仅有使用场景的不同L_Key用于本端操作R_Key用于远端操作。以Mellanox的网卡为例L_Key和R_Key实际取值完全相同那为什么IB规范还要区分两把钥匙答案是语义区分便于上层协议做差异化访问控制——某些场景下你可能希望本地操作比远程操作拥有更多权限比如本地可写、远程只读虽然底层钥匙值相同但在MPT中可以通过不同的权限掩码来实现这种区分。二、MPT硬件的“内存登记册”所有已注册的内存区域都在网卡硬件的MPT内存保护表里有一条记录。MPT的本质是网卡内部或主机内存中的一张数组每个条目通常叫MKey Context存放着某块MR的完整信息内存的起始虚拟地址VA和长度访问权限本地读/写、远程读/写、原子操作等指向MTT内存翻译表的指针其他元数据当应用程序调用ibv_reg_mr时驱动锁页、构建MTT然后向硬件发送命令。硬件在MPT中分配一个新条目填入上述信息然后生成L_Key和R_Key——高24位就是这个条目的索引数组下标低8位由硬件填充一个随机或递增的标签。最后硬件把这两把钥匙返回给驱动驱动再交给应用程序。三、L_Key和R_Key如何使用1、场景1本端发送数据需要L_Key应用程序调用ibv_post_send在SGE散播收集条目中填入缓冲区的虚拟地址、长度、以及L_Key。驱动把这些信息打包成WQE写进SQ然后敲门通知网卡。网卡硬件从SQ取出WQE后立即用L_Key的高24位作为索引到MPT中定位对应的条目。取到条目后硬件做三件事校验标签对比L_Key的低8位是否和MPT条目中存储的标签一致。不一致→拒绝操作。、校验权限当前操作是“本地读”发送数据时需要从本地缓冲区读数据MPT条目中必须允许本地读操作。不允许→拒绝。校验地址范围WQE中的虚拟地址和长度必须在MPT条目的合法范围内。超出→拒绝。全部通过后硬件拿着MPT条目中指向MTT的指针去查地址翻译表把虚拟地址转成物理地址然后发起DMA从内存中取数据封装成包发出去。2、场景2远端发起RDMA Write需要R_Key远端节点发来一个RDMA Write请求包包里包含了目标虚拟地址、要写入的数据、以及R_Key。本端网卡收到包后同样用R_Key的高24位作为索引去查MPT。校验流程和本地操作几乎一样只是权限检查改成了“远程写”。校验通过后网卡根据MPT条目找到MTT翻译地址然后把数据DMA写入对应的物理内存。关键区别L_Key和R_Key校验的是“同一张MPT表”的不同权限掩码。本地操作走本地权限位远程操作走远程权限位。这就是为什么同一把钥匙值可以同时用于L_Key和R_Key——硬件根据请求来源本地WQE还是网络包来判断该检查哪一组权限。四、为什么R_Key能防止非法访问1、钥匙本身不可伪造。R_Key的低8位标签由硬件随机生成且每次注册不同。应用程序通过socket或CM交换R_Key时交换的是这个随机数。攻击者即使截获了虚拟地址和QPN没有正确的R_Key网卡直接拒绝。2、索引标签双重校验。R_Key的高24位索引指向MPT中的某一行。即使攻击者猜中了索引比如遍历0~16M低8位的标签有256种可能且MPT中该条目的标签只有正确的那一个才匹配——硬件在每次请求时都会做标签比对不匹配直接丢弃包。3、硬件级不可覆盖。所有这些校验都在网卡芯片内部完成不经过CPU也不依赖操作系统。即使攻击者拿到了服务器的root权限也无法绕过网卡的硬件校验逻辑——MPT表存储在网卡可访问的内存中但其访问完全由硬件控制内核无法篡改。4、PD隔离。除了钥匙校验RDMA还提供了保护域PD机制QP和MR必须属于同一个PD才能互相访问。这意味着即使攻击者拿到了某个MR的R_Key如果没有一个和该MR同PD的QP也无法发起有效的RDMA操作。五、总结L_Key和R_Key的本质是把“哪块内存能用”的决策权从CPU转移到了网卡硬件。24位索引负责定位8位标签负责防伪MPT负责存储规则。当网卡收到一个内存访问请求时它拿着钥匙自己去查表、校验、决定允许还是拒绝——全程不需要CPU帮忙也不给攻击者留后门。这在追求“CPU零参与”性能的同时还给RDMA提供了硬件级的安全底座