14

微软/Qspectre为他们的 MSVC 编译器添加了一个方便的工具(尽管目前这似乎只是(试图)减轻 Spectre v1 的影响),它们将随着时间的推移而更新。从用户的角度来看,这非常好,只需启用该标志,您就可以获得他们存储的最新和最大的缓解措施。

使用 LLVM 和 GCC,它看起来有点不同。我认为他们的缓解措施尚未正式发布。

LLVM 应该获得一个-mretpoline编译器标志,通过返回蹦床来缓解 Spectre v2 的间接调用。

另一方面,GCC 的补丁添加了三个用于缓解 Spectre v2 的编译器选项:

  • -mindirect-branch可以设置为thunk. 据我了解,这会为每个间接调用创建 retpolines。
  • -mfunction-return可以设置为thunk. 我想这将这些 retpolines 用于每个函数返回,这对于 Skylake 可能是必要的,因为这些处理器也可以预测返回?
  • -mindirect-branch-register这使用寄存器而不是堆栈来存储间接调用的地址?

所以我很困惑。什么编译器选项可以缓解用户空间应用程序在什么情况下需要它们?

通常打开它们是个好主意吗?如果为甚至没有任何推测执行的处理器架构(如微处理器)编译,它们是否也会生成这些 retpolines?

幽灵v1怎么样?

更新:

让我问更精确的问题:

  • 我对编译器选项的理解是否正确?
  • GCC 选项是在任何地方应用还是仅在具有推测执行的处理器上应用?
  • LLVM 选项是在任何地方应用还是仅在具有推测执行的处理器上应用?
  • 这些选项究竟能缓解什么(它们是否完全缓解了 Spectre v2)?
  • 让我们考虑一下我要求的所有其他“奖励”问题”,这些问题很值得了解,但对我的问题并不重要。
4

1 回答 1

6

我对编译器选项的理解是否正确?

我认同。

GCC 选项是在任何地方应用还是仅在具有推测执行的处理器上应用?

到目前为止,这些选项是特定于 x86 的。我没有检查是否有等效的 ARM 补丁,但无论如何,这些选项至少部分取决于处理器架构。

我只看了一些补丁,但看起来并没有强加额外的运行时检查。相反,如果设置了选项,则会更改指令选择以防止后端发出不需要的间接跳转。

因此该选项不适用于完全不相关的架构,但不会尝试发现特定 CPU 在运行时是否易受攻击。请注意,大多数知名 x86 处理器自 ca. Pentium Pro 确实使用推测执行。

这些选项究竟能缓解什么(它们是否完全缓解了 Spectre v2)?

大多数情况下,它们通过确保在相应的间接调用中不会发生攻击者控制的推测来减轻分支目标注入(Spectre v2)。

Retpolines 通过使用返回指令跳转到目标地址来实现这一点,该地址使用不同的分支预测器,该预测器基本上记住最新调用的来源。这是由生成的代码操纵的,该代码在返回指令之前执行调用指令,通过在调用之后放置 mfence 指令来确保推测的执行将陷入死胡同。有关更多详细信息,请参阅此答案

分支目标注入是一个问题,因为正如Spectre 论文中“5.1 讨论”下的解释,可能有很多代码被映射供攻击者利用。讨论讨论的是 Windows,但我可以想象一定有一些来自共享库的代码映射到 Linux 中。如果该代码的地址更随机,则利用可能会更难,但如果不检查,我不会指望这一点。特别是 Linux 内核包含大量代码,攻击者可以使用这些代码注入任意分支目标。

-mfunction-return

乍一看,通过用更复杂的返回替换它来保护返回似乎很愚蠢,但根据David Woodhouse 的这条消息,Linux 内核开发人员要求该选项,因为在记住的返回地址下溢时(基本上是一个隐藏的堆栈在调用堆栈之后),一些 CPU 再次拉入全局分支预测器,这可能被攻击者操纵。所以你的解释是正确的。根据同一消息,Linux 内核没有立即使用此标志。我认为性能影响将是显着的,因为回报其他间接分支更常见,并且专门的回报预测将在实践中实现出色的命中率。

-mindirect-branch-register

我不太确定,什么-mindirect-branch-register减轻了。显然,测试套件中需要它以及其他选项,但我还找不到解释。Xen也将此选项与 一起使用 -mindirect-branch=thunk-extern,这意味着它们自己编写 thunk 代码并且不让编译器生成它。与我最初的猜测相反,这与加载地址时的潜在猜测无关,因为这旨在与防止该猜测的 retpolines 一起使用。在一些讨论中提到,在堆栈而不是寄存器中获取目标地址的 thunk 版本最初与英特尔控制流强制技术有冲突(中欧)。我假设由于 retpolines 以不寻常的方式使用回报,CET 阻止了跳跃。然而,根据这个讨论,这些问题似乎已经解决,并且在支持 CET 的机器上,其他缓解 (IBRS_ALL) 是可用的,这允许 retpoline thunk 再次被间接跳转替换。我认为这个选项本身不会有太大帮助。

更新:幽灵变体 1

最近 Chandler Carruth提出 了如何在 LLVM 中缓解 Spectre V1。这仍在进行中,尚未发布(截至 2018 年 3 月)。基本思想是在错误推测的路径上屏蔽易受攻击的地址或加载的值,然后才能将它们与副作用一起使用。

于 2018-01-31T17:13:16.370 回答