最著名的stackoverflow问题之一是为什么对排序数组进行排序如此之快;答案是因为分支预测。
英特尔和Microsoft幽灵修复的应用是否会有效地使此问题中在受影响的处理器(老一代英特尔处理器、AMD 锐龙和 ARM)上给出的答案无效?
不,Spectre的关键是强制错误预测间接分支,因为它们可以跳转到任何地址。 找到一系列指令来加载您想要的机密数据,然后将该机密作为数组索引进行另一个依赖于数据的加载,这并非易事。
要攻击常规的已取/未取条件分支(就像您在排序函数中找到的那样,或者在排序或未排序数组的循环中找到的条件),您需要找到一种情况,即执行分支的"错误"端(可能是源中 if/else 的错误端)在寄存器中使用"错误"值运行时会做一些有用的事情。 这是合理的1,但不太可能,所以大多数防御幽灵只会担心间接分支。
Spectre的硬件修复必须比"关闭分支预测"(即在每个条件分支处停止管道)更微妙。这可能会使许多代码的性能降低一个数量级,并且太高而无法成为针对本地信息泄漏(可能导致权限提升)的可接受的防御措施。
即使关闭仅间接分支(而不是常规条件分支)的预测对于大多数用户空间代码来说也可能过于昂贵,因为每个共享库/DLL函数调用都经过主流操作系统(Linux,OS X,Windows)上正常软件生态系统中的间接分支。
Linux 内核正在试验 retpoline 来击败内核内间接分支的间接分支预测。 不过,我不确定默认情况下是否启用它,即使在启用 Meltdown 解决方法 (KPTI) 的内核中也是如此。
脚注:
- 有时,
switch
的错误case
可能会做一些完全不合适的事情(例如在解释器中),如果switch
是用嵌套分支而不是单个间接分支编译的,那么你也许可以攻击它。 (编译器经常使用分支目标表进行switch
,但是当情况稀疏时,并不总是可能的。 例如case 10
/case 100
/case 1000
/default
需要一个只有 3 个已用值的 990 个条目数组。