英特尔/微软如何提供软件Spectre 的补丁利用了超标量处理器的推测执行特性,这是一种硬件无法修改或禁用的功能(至少会因推测执行而导致 IPC 收益大幅下降)?这些“补丁”实际上如何发挥作用?
答案1
有多种技术可以缓解软件中的 Spectre 式漏洞,而无需修补微代码或更换硬件,但它们确实会产生一些性能成本。我不清楚微软是如何实现这些缓解措施的,但Linux 文档很全面。
对于 Spectre 变体 1,易受攻击的内核代码(由代码审计或扫描工具确定)会逐一注释,以使用 nospec 访问器宏进行边界剪辑[2]以避免任何可用的披露小工具。
为了缓解 Spectre 变体 2,编译器将内核中的间接调用或跳转转换为等效的返回跳转 (retpolines)[3] [9]转到目标地址。retpolines 下的推测执行路径被困在无限循环中,以防止任何推测执行跳转到 gadget。
这里描述的缓解技术本质上并不是防止 Spectre 式信息泄露的方法,但它们是受影响处理器实施方式所产生的问题的实用解决方案。
答案2
从某种意义上说你是对的。这是一个硬件只能通过硬件解决的问题。
事实上,我甚至会更进一步:这是一个心态问题在整个行业中整个行业都犯了一个错误,即强调性能而忽视了安全性,并且没有正确考虑将复杂的优化功能堆积在其他复杂的优化功能之上所导致的极其复杂的相互作用,而每个复杂的优化功能都以高度复杂、不明显的方式与其他所有功能相互作用。
CPU 不仅来自两个都尽管微架构完全不同,但 AMD64 CPU 的主要供应商(英特尔和 AMD)都受到了影响。具有完全不同 ISA 的 CPU 也受到了影响。例如,当时每个 Apple Silicon CPU 也容易受到非常类似的攻击,许多其他基于 ARM 的 CPU 以及基于 MIPS 和 POWER 的 CPU 也是如此。(事实上,Apple 受到了严重的打击,每台基于英特尔的 Mac 以及每台基于 Apple Silicon 的 iPhone、iPad、iPod touch 和 Apple TV 都容易受到攻击——唯一“安全”的设备是 Apple Watch,当时它还没有使用与其他 iDevices 相同的硬件和软件平台。)
因此,这不仅仅需要硬件的改变,而是整个行业优先事项的根本转变。
Spectre 和 Meltdown 仅仅是个开始,迄今为止,该漏洞家族中已发现了二十多个漏洞和变种。
然而,仍然无需更改硬件即可完成的操作。从堆栈顶部开始:
用户程序
用户程序可以关闭其自身代码(部分)的推测执行。
安全库
处理敏感数据的库可以实施防御措施,防止其内存被读取。
这可能不是 100% 完美,也可能无法在所有情况下都实现。但做点什么总比什么都不做要好。大多数这些努力被贴上“缓解措施”而不是“修复措施”的标签是有原因的。
系统库
与上一点类似:您可以在系统库中引入一些功能来缓解漏洞。如果攻击者可以运行不使用系统库的静态链接代码,那么这种方法就无济于事,但在某些情况下还是有帮助的。
操作系统
操作系统可以实施缓解措施,例如在同一物理核心上运行的线程的上下文切换之间刷新分支目标缓冲区。
虚拟机管理程序
与操作系统类似,Hypervisor 可以在上下文切换时清除/刷新缓存和缓冲区。
编译器
更改编译器以不生成易受攻击的代码,也不生成可利用该漏洞的代码。
当然,第二种方法只有在你能确保机器上运行的所有代码都是由打过补丁的编译器编译的情况下才有效。换句话说,它确实不是防止有人在云虚拟机中运行一些漏洞代码并读取其他虚拟机中的机密数据的情况。第一种情况是否可行取决于漏洞在特定平台上的具体工作方式。
但它仍然可以抵御其他可能的攻击。例如,研究人员发现他们可以利用此漏洞通过网络通过特制的 JavaScript,Google 的 V8 编译器会将其编译为利用该漏洞的代码。作为回应,Google 改变了 V8 中的 JIT 编译器,以引入缓解措施。由于您机器上运行的所有 JavaScript 代码始终由处于你的控制,您可以确信这些缓解措施将始终被应用。
例如雷特波林GCC 中的功能。该功能的基本功能是在有关该漏洞的原始论文中提出的,因此几乎每个编译器都实现了该功能的某个版本。
基本思想是“欺骗”CPU 不使用分支预测器,而是使用返回堆栈预测器。因此,retpoline(“返回跳板”)的作用是将分支替换为一个序列,该序列将伪造的返回地址放在堆栈上(指向一个简单的无限循环),调用一个子例程(此时将被推测执行的代码是伪造返回地址处的无限循环),该子例程修复返回地址并返回到“真实”目标。
这尤其适用于 Spectre 变体 2,它基于攻击者“毒害”分支目标缓冲区。Retpolines 诱使 CPU 不使用 BTB,因此攻击者控制的 CPU 部分被绕过。
再次流血
但等一下,还有更多!
事实证明退货说明是还容易受到非常类似的攻击。这篇文章发表于 2022 年。我们又做了什么来减轻对间接分支预测的攻击?哦,对了,把返回在那里 …
因此,这个漏洞绝对被打碎大部分努力都是为了缓解软件早期存在的漏洞。
微码
现代 CPU 中的功能并非全部都是在硬件中实现的。事实上,很多功能都是在微代码中实现的,即使是在硬件中实现的功能有时也可以用微代码覆盖。微代码本质上只是加载到 CPU 上的代码,可以升级和修复。
CPU供应商主要做了三件事:
- 做出改变以缓解漏洞总是,适用于这些缓解措施仅对性能产生微小影响(或没有影响)的情况。
- 引入可以打开或关闭的缓解措施,以应对这些缓解措施对性能产生不可忽略的影响的情况。例如,在同一物理 CPU 核心中运行来自许多不同用户的不受信任代码的云提供商可以将其打开,而运行仅运行受信任代码的渲染农场的人可以将其关闭。
- 引入允许用户代码自我保护的新指令。
表现
一般来说,在堆栈中执行缓解措施的层级越高,对性能的影响就越大。这就是为什么即使你能虽然在软件中可以缓解这个问题,但它应该在下一代 CPU 中得到修复。
但即使修复了 CPU 中的漏洞,也不能保证不会产生影响。毕竟,许多漏洞都攻击的是很心是什么让现代高性能 CPU 如此之快。
上述所有的
当然,您可以将以上所有方法结合起来。例如,编译器可以使用一些新指令来生成不易受攻击的代码。内核、库和应用程序可以发布已启用新编译器功能编译的新版本。系统库可以使用系统函数提供对新 CPU 指令的访问。应用程序和安全库可以利用这些新的系统函数。等等。
但……你是对的
但最终,该行业需要彻底重新思考他们的安全方法以及他们对现代主流高性能 CPU 日益复杂性的傲慢态度。
Retbleed 就是一个很好的例子。它与最初的 Spectre 和 Meltdown 漏洞非常相似,但它并没有通过编译器技巧修复,也没有通过硬件更改修复,事实上,大多数缓解措施都无法修复它。