想象一下,一台高性能 GPU(图形处理器)就像一座庞大且极速运转的工厂。在工厂内部,成千上万个微小的工人(称为“线程”)正在同时构建复杂的各种产品。他们遵循的指令是用一种被称为 SASS 的秘密、超紧凑代码编写的。这是机器真正理解的“母语”,而不是程序员编写的人类可读代码。
问题在于,如果有人设法在工厂的供应链中混入了一个错别字或损坏的数据(即内存错误/Memory Bug),他们就可以欺骗这些工人去做危险的事情。工人不再是制造一个零件,而是被诱导去抓取另一组指令、跳转到工厂的危险区域,或者夺取整个建筑的钥匙。这被称为控制流劫持(Control-Flow Hijack)。
WARPGUARD 是一种旨在阻止此类行为的新型安全系统,但它有一个非常特殊的策略:它并不试图修复供应链中的错误,而是守卫着工人决定下一步去向的出口大门。
以下是 WARPGUARD 的工作原理,通过简单的概念进行拆解:
1. “邮局”类比
将 GPU 工人想象成邮递员。
- 漏洞(The Bug): 黑客在包裹里塞进了一个虚假地址(内存损坏)。
- 危险(The Danger): 邮递员拿起了包裹,正准备开车前往那个虚假地址。
- 旧方法: 你可能会尝试在包裹离开工厂之前扫描每一个包裹。但这很慢,而且由于工厂过于复杂,往往会漏掉一些东西。
- WARPGUARD 的方式: WARPGUARD 站在出口闸口。在邮递员离开工厂去往新地址之前,WARPGUARD 会检查他们的工作单。
- 后向边(返回原处/Backward Edge): 如果一个工人被派去执行一项任务,现在正准备回来,WARPGUARD 会检查:“你真的完成你被派去做的任务了吗?你的回程票有效吗?”如果票据看起来是伪造的,或者工人试图回到错误的家,WARPGUARD 会立即关上大门。
- 前向边(前往新工作/Forward Edge): 如果一个工人正被派往一台新机器,WARPGUARD 会检查清单:“这个新目的地是否在针对该特定工人的批准名单上?”如果工人试图去一个不在其特定名单上的机器,大门就会关闭。
2. 为什么“SASS”很重要
论文强调,你不能仅仅通过查看人类可读的代码(“食谱”)来进行这项工作。当 GPU 运行代码时,食谱已经被翻译成了 SASS,并且工厂已经自行做出了如何组织工作的决策(例如函数内联或数据移动)。
- 类比: 想象一下,如果你试图通过查看建筑物的原始蓝图来阻止一名小偷,但小偷实际上是通过施工过程中产生的隐藏门进入的。WARPGUARD 通过观察实际的施工现场(SASS 二进制文件)来确定门的确切位置,以及谁被允许通过这些门。
3. “失效闭锁”规则(The "Fail-Closed" Rule)
这是最重要的安全特性。
- 如果 WARPGUARD 不确定一个工人是否被允许离开,或者 paperwork(文书工作)看起来很可疑,它不会进行猜测。它会假设最坏的情况,并锁上大门。
- 该系统的设计目标是“失效闭锁”。它宁愿拦截一名合法的工人(导致暂时性的延迟),也不愿让一名被劫持的工人开着车冲出去破坏工厂。
4. 他们实际测试了什么
研究人员不仅仅是构建了这个系统,他们还针对 77 个不同的真实世界 GPU 程序(人工制品) 进行了测试。
- 他们发现了超过 51,000 个特定的“出口点”(工人决定去向的地方)。
- 他们进行了 5,200 万次实时检查。
- 结果: 当他们尝试用虚假地址或损坏的回程票来欺骗系统时:
- 没有 WARPGUARD 时: 工人们会完全按照黑客预期的方向行动。
- 使用 WARPGUARD(检测模式)时: 系统会发出警报并记录该尝试。
- 使用 WARPGUARD(执行模式)时: 系统捕捉到了尝试,并在工人离开大门之前将其拦截。
5. 它不做的事情(边界限制)
论文非常明确地说明了 WARPGUARD 不是什么:
- 它并不修复内存错误本身(它不会阻止黑客在供应链中塞入假条)。
- 它并不保护所有可能的攻击,仅保护那些“出口门”逻辑可以被清晰验证的攻击。
- 如果系统无法弄清楚一个工人应该去哪里(因为文书工作太混乱),它会将该区域标记为“不支持”,并且不会假装受到保护。承认无知比提供虚假的安全感要好。
总结
WARPGUARD 就像是一个守在高速运转的 GPU 工厂出口处的超级严格的保安。它忽略了混乱的供应链,而完全专注于工人试图离开的那一刻。它会根据一份严格的、经过验证的名单来检查他们的身份和目的地。如果任何事情看起来哪怕有一点不对劲,它就会锁上大门。它是第一个专门针对现代 GPU 实际运行的原始编译代码(SASS)进行此类操作的系统,证明了即使在如此混乱、高速的环境中,你也可以阻止黑客劫持控制流。
技术摘要:WARPGUARD
问题陈述
近期的漏洞利用研究表明,GPU 内存漏洞(例如缓冲区溢出)可以将攻击升级为设备侧的控制流破坏。攻击者可以破坏返回连续性(return continuations)、函数指针、调度表条目或分支目标,这些内容随后会被 GPU 指令消费,从而重定向执行流。虽然控制流完整性(CFI)是 CPU 的标准防御手段,但将其应用于已部署的 CUDA 二进制文件却极具挑战。生产环境中的内核通常以 fatbinary 或 cubin 形式分发,其相关的安全边界是正在执行的 NVIDIA SASS(Streaming ASSembly)代码,而非源代码或 PTX(Parallel Thread Execution)中间表示。
SASS 层引入了 CPU CFI 所不存在的复杂性:
- 降低转换(Lowering Transformations): 源层级的调用可能会被内联,返回状态可能会保存在寄存器中而非溢出到内存,或者间接目标可能会被优化掉。
- SIMT 执行: 单个静态指令在不同的线程束(warp)车道上执行方式可能不同(warp-uniform 与 lane-local),这需要更细粒度的检查。
- 证据差距(Evidence Gaps): 二进制文件中的并非所有控制流站点都有足够的证据来推导出可靠的策略。将不支持的站点视为“允许”会产生安全漏洞,而将没有证据的站点视为“受保护”则是不可靠的。
现有的 GPU 安全工具侧重于内存安全或代码注入,但并未在执行的 SASS 边界处实施 CFI,也未对无法保护的站点进行明确的计数。
方法论:WARPGUARD
WARPGUARD 是首个专门为运行在执行 SASS 上的 CUDA 设备二进制文件设计的 CFI 系统。它执行一种“受保护站点”策略,即仅检查存在足够二进制证据以推导出可靠策略的控制流传输。
站点恢复与分类:
WARPGUARD 分析 SASS 二进制文件以识别控制流消费站点(返回、间接调用、间接分支)。它将每个站点分类为以下六种结果之一:
- 受保护(Protected): 存在充足证据;插入检查逻辑。
- 固定边(Fixed-edge): 目标是静态的(例如直接调用);无需动态检查。
- 不支持(Unsupported): 证据缺失或模糊;该站点被排除在保护之外。
- 无表面(No-surface): 不存在动态传输(例如完全内联的代码)。
- 回退/配置文件排除(Fallback/Profile-excluded): 分析失败或模式被禁用。
至关重要的一点是,WARPGUARD 不会默认为不支持的站点提供静默允许;它们被明确地计入受保护分母之外。
后向边 CFI(返回):
对于受保护的返回,WARPGUARD 在 RET 指令释放控制权之前验证连续性状态。
- 机制: 在受保护的调用期间,系统会在一个受信任的后端私有状态中记录预期的返回连续性、调用点 ID、深度和加键令牌(MAC)。
- 验证: 在返回站点,系统读取观察到的连续性,验证令牌是否与受信任状态匹配,并将其与预期值进行比较。
- 安全性: 可写的影子元数据不具有权威性;只有来自受信任主机/运行时的加键令牌才授权传输。如果验证失败,系统会在无效传输发生前执行“失败关闭”(trap/陷阱)。
前向边 CFI(间接调用/分支):
对于受保护的间接传输,WARPGUARD 将观察到的动态目标与恢复的每站点目标集进行校验。
- 恢复: 目标集通过二进制元数据、常量重定位以及对调度表或取地址函数的分析得出。
- 验证: 在间接传输释放之前,观察到的目标会针对特定站点的允许集合进行检查。
- 粒度: 检查是保守的且默认是车道局部(lane-local)的,以处理 SIMT 分歧,确保被破坏的车道不会隐藏在 warp-uniform 的聚合体中。
实现后端:
WARPGUARD 通过三个不同的后端实现,以实现关注点分离:
- WG-NVBit: 一个广泛的参考后端,使用 NVBit 进行动态插桩和攻击评估。
- WG-ST: 一个静态跳板时间车道(static-trampoline timing lane),用于在特定的
sm_89 表面上进行无回调执行,用于在没有 NVBit 回调底层的条件下比较开销。
- WG-PC: 一个补丁缓存后端,通过应用的经过审查且有清单支持的 SASS 补丁,在
sm_89 表面上实现无回调预防。
核心贡献
- 受保护站点 CFI 公式化: 本文将 CUDA 二进制 CFI 公式化为在恢复的 SASS 消费站点进行的“检查后再释放”强制执行。它明确地统计了固定边、不支持的站点和配置文件排除项,并将它们与受保护覆盖范围区分开来。
- 机制与实现: WARPGUARD 将策略绑定到恢复的 SASS,使用加键令牌验证后向边状态,逐站点验证前向目标,并将遥测数据与授权逻辑分离。
- 带有分离分母的评估: 系统在 77 个 CUDA 工件上进行了评估,分类了 51,621 个 SASS 控制流站点,并记录了 5220 万次动态检查。评估区分了恢复的表面、受保护的强制执行以及剩余的不支持表面。
结果
- 覆盖率: WARPGUARD 成功分类了 51,621 个站点,包括 1,343 个返回点和 154 个受支持的前向目标条目。它识别出 15 个不支持的前向条目和 10 个回退条目,确保这些站点不会被错误地视为受保护。
- 攻击阻断: 在代表性的后向边和前向边破坏攻击中,原生执行达到了攻击者选择的行为,而 WARPGUARD 的强制模式在释放无效传输前执行了失败关闭。这在以下情况均成立:
- 返回劫持和 gadget 链。
- SIMT 分歧攻击(分歧车道返回)。
- 前向边目标破坏(调度表、函数指针)。
- 元数据篡改(令牌、遥测)。
- 现实世界证据: 公开代码案例(如 PPL-CUDA-SMC、PNNL SV-Sim、cuFFT 回调、GooFit)证实,相同的 SASS 消费模式存在于真实的 CUDA 系统中。WARPGUARD 成功恢复并保护了这些站点。
- 性能:
- WG-NVBit: 正如预期,作为动态插桩工具,其开销很高(对于时长 >50ms 的工作负载,开销为 799–927%),主要受辅助调度和回调成本驱动。
- WG-ST/WG-PC: 在匹配的
sm_89 表面上,无回调后端消除了 NVBit 的定时底座。WG-PC 表明,对于经过审查的清单,无回调预防是可行的,尽管这需要严格的清单验证。
意义与主张
本文声称,据作者所知,WARPGUARD 是第一个直接在执行的 SASS 上运行的 CUDA 设备二进制文件 CFI 系统。其意义在于:
- 转移边界: 将 CFI 强制执行从源/PTX 转移到实际执行的 SASS,捕捉真实的控制流事实(内联、溢出、SIMT 掩码)。
- 显式计数: 拒绝将未知或不支持的站点视为安全,从而防止破坏安全性的“允许任何”策略。
- 可审计的强制执行: 提供了一种将动态插桩开销与核心 CFI 逻辑分离,并区分受保护站点与剩余攻击表面的机制。
作者谦虚地指出,WARPGUARD 不提供内存安全性、代码完整性或针对主机侧破坏的保护。它是内存安全工具的补充,专注于被破坏的状态如何被消费为控制流的具体点。该系统依赖于一个受信任的主机/运行时进行密钥管理;如果后端私有状态暴露给 GPU,其安全保证将会下降。
每周获取最佳 computer science 论文。
受到斯坦福、剑桥和法国科学院研究人员的信赖。
请查收邮箱确认订阅。
出了点问题,再试一次?
无垃圾邮件,随时退订。