如何通过GCC和Clang(或一般的LLVM)缓解幽灵

FSM*_*axB 14 security gcc clang spectre

微软/Qspectre为他们的MSVC编译器添加了一个方便的功能(虽然这似乎只是(试图)缓解目前的Specter v1),他们将随着时间的推移进行更新.从用户的角度来看,这是非常好的,只需启用该标志,您就可以获得他们存储的最新和最大的缓解.

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

LLVM应该获得一个-mretpoline编译器标志,通过返回trampolines缓解Specter v2以进行间接调用.

另一方面,GCC有补丁,可以添加三个编译器选项来减轻Spectre v2:

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

所以我很困惑.什么编译器选项可以减轻用户空间应用程序所需的内容和方式?

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

Spectre v1怎么样?

更新:

让我问更准确的问题:

  • 我对编译器选项的正确理解是什么?
  • GCC选项是应用于任何地方还是仅适用于具有推测执行的处理器?
  • LLVM选项是应用于任何地方还是仅应用于具有推测执行的处理器?
  • 这些选项究竟是什么减轻了(他们是否完全减轻了幽灵v2)?
  • 让我们考虑其他一切我要求的额外"奖励"问题"这些问题很有用,但对我的问题不是必不可少的.

Pau*_*ulR 6

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

我认同.

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

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

我只看了一些补丁,但它看起来不像额外的运行时检查.而是改变指令选择以防止后端在设置选项时完全发出不需要的间接跳转.

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

这些选项究竟是什么减轻了(他们是否完全减轻了幽灵v2)?

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

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

分支目标注入是一个问题,因为正如"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版本最初与Intel 控制流强制技术(CET)存在冲突.我假设由于retpolines以不寻常的方式使用返回,因此CET阻止了跳转.然而,根据这个讨论,这些问题似乎已经解决,并且在支持CET的机器上,可以使用其他缓解(IBRS_ALL),这允许再次通过间接跳跃替换retpoline thunk.我认为这个选项本身并没有多大帮助.

更新:幽灵变种1

最近Chandler Carruth 提出了 如何减轻LLVM中的Spectre V1.这仍然在进行中尚未落实到发布中(截至2018年3月).基本思路是在可以与副作用一起使用之前,在错误推测的路径上屏蔽易受攻击的地址或加载的值.