gpt4 book ai didi

caching - 缓存缓存更改会阻止崩溃吗?

转载 作者:行者123 更新时间:2023-12-04 22:55:42 24 4
gpt4 key购买 nike

如果新的CPU具有仅提交给实际CPU高速缓存的高速缓存缓冲区(如果曾经提交过指令),那么是否仍可能发生类似于Meltdown的攻击?

建议是使推测性执行能够从内存中加载,但要等到实际提交后才能写入CPU缓存。

最佳答案

TL:DR:是的,我认为它可以解决当前形式的Spectre(和Meltdown)(使用刷新+读取缓存定时侧通道从物理寄存器复制机密数据),但是可能太昂贵了(在功耗上) ,也可能是性能)。

但是使用超线程(或更普遍的是任何SMT),如果您可能会误以为使用秘密数据运行与数据相关的ALU指令,而不是将其用作数组,则还有一个ALU /端口压力侧通道。指数。 The Meltdown paper在着重于刷新+重载高速缓存定时侧通道之前讨论了这种可能性。 (对于Meltdown,它比Spectre更可行,因为您可以更好地控制使用秘密数据的时间)。

因此,修改缓存行为不会阻止攻击。但是,它将剥夺了将机密数据带入攻击过程的可靠辅助渠道。 (即ALU时序具有较高的噪声,因此具有较低的带宽,以获得相同的可靠性; Shannon's noisy channel theorem),并且您必须确保代码与受攻击的代码在同一物理内核上运行。

在没有SMT的CPU(例如Intel的台式机i5芯片)上,ALU计时副通道很难与Spectre一起使用,因为您不能直接在没有特权的代码上使用perf计数器。 (但是,例如,可以通过在Linux perf上计时自己的ALU指令来利用Meltdown)。



Meltdown特别是much easier to defend against, microarchitecturally,它对CPU的硬连线部分进行了更简单,更便宜的更改,而微代码更新无法重新连线。

您不需要阻止推测性负载影响缓存;更改可能很简单,只要让TLB命中的负载在达到退休后就将失败的情况下继续进行推测性执行即可,但由于对TLB的权限检查失败,因此推测性执行后续指令的推测性执行所使用的值被强制为0条目。

因此,错误推测(在secret的错误加载之后)touch array[secret*4096]加载将始终使同一高速缓存行变热,而没有依赖于秘密数据的行为。秘密数据本身将进入缓存,但不会进入物理寄存器。 (这也会停止ALU /端口压力侧通道。)

即使将“秘密”行首先放入缓存中,也无法阻止错误的负载,这可能使得更难区分内核映射和未映射的页面之间的差异,这可能有助于防止用户空间试图通过发现KASLR来击败KASLR内核已映射的虚拟地址。但这不是崩溃。



幽灵

Spectre是一项艰巨的任务,因为对微体系结构状态进行依赖数据的修改的错误推测的指令确实具有读取机密数据的权限。是的,与存储队列类似的“加载队列”可以解决问题,但是有效地实现它可能会很昂贵。 (特别是考虑到我在写第一部分时没有想到的缓存一致性问题。)

(还有其他方法可以实现您的基本思想;也许还有一种可行的方法。但是extra bits on L1D lines to track their status有缺点,而且显然并不容易。)

The store queue跟踪从执行到提交到L1D缓存的存储。 (商店要等到退休后才能使用L1D,因为这是众所周知的非投机点,因此可以使其对其他核心全局可见)。

加载队列必须存储整个传入的缓存行,而不仅仅是存储已加载的字节。 (但请注意,Skylake-X可以进行64字节的ZMM存储,因此其存储缓冲区条目的大小必须与高速缓存行的大小相同。但是,如果它们可以互相借用空间或其他东西,则可能不会< cc>可用的字节存储空间,即也许标量或窄向量存储只能使用全部条目,但我从未读过关于这种限制的任何内容,因此我认为不存在任何限制,但这是合理的)

一个更严重的问题是英特尔当前的L1D设计具有2个读取端口+ 1个写入端口。 (也许还有另一个端口用于编写与提交存储并行的从L2到达的行?在Unexpectedly poor and weirdly bimodal performance for store loop on Intel Skylake上对此进行了一些讨论。)

如果加载的数据在加载退出后才能进入L1D,则它们可能会争用存储用途的同一写端口。

但是,命中L1D的负载仍然可以直接来自L1D,并且命中内存顺序缓冲区的负载仍可以每个时钟2个执行。 (MOB现在将包括此新的加载队列以及通常的存储队列+用于维护x86内存排序语义的加载标记)。您仍然需要两个L1D读取端口来维护不会占用大量新内存的代码的性能,并且大多数情况下是重新加载在L1D中很热的东西。

这将使MOB大约大一倍(就数据存储而言),尽管它不需要更多条目。据我了解,当前Intel CPU中的MOB由单独的加载缓冲区和存储缓冲区条目组成。 (Haswell has 72 and 42 respectively)。



嗯,更复杂的是,MOB中的加载数据必须保持与其他内核的缓存一致性。这与存储数据有很大不同,存储数据是私有的,并且尚未变为全局可见/不属于全局存储顺序和缓存一致性,直到它提交给L1D。

因此,为您的想法提议的这种“加载队列”实现机制如果不进行调整,可能是不可行的:必须通过来自其他内核的失效请求来检查它,因此这是MOB中需要的另一个读取端口。

任何可能的实现都将存在需要稍后像商店一样提交到L1D的问题。我认为,如果无法从核心外撤回新线路,那将是一个沉重的负担。

(即使允许进行推测性驱逐,但不允许进行冲突性的推测性替代,也会造成可能的缓存时机攻击。您可以对所有线路进行灌注,然后进行负载以从一组或另一组线路中逐出,并找出哪条线路被逐出而不是使用类似的缓存定时辅助通道来获取该辅助通道。因此,在L1D中使用额外的位来查找/逐出从错误推测中恢复的负载线并不能消除该辅助通道。)



脚注:所有说明都是推测性的。这个问题的措词很好,但我认为许多阅读OoO高管和Meltdown / Spectre的人都陷入了将投机执行与错误投机相混淆的陷阱。

请记住,所有指令在执行时都是推测性的。直到退休才知道是正确的猜测。崩溃/幽灵依赖于访问秘密数据并在错误推测期间使用它们。但是,当前OoO CPU设计的基础是您不知道自己是否正确推测。一切都是投机的,直到退休。

任何加载或存储都可能潜在地发生故障,某些ALU指令也可能发生故障(例如,如果未屏蔽异常,则为浮点运算),因此“仅当以推测方式执行时”适用的任何性能成本实际上始终适用。这就是为什么直到存储设备从无序CPU内核(存储数据在存储队列中)退出后,存储才能从存储队列提交到L1D的原因。

但是,我认为对条件分支和间接分支进行了特殊处理,因为预计它们会误导某些时间,因此优化它们的恢复非常重要。我认为,现代CPU的分支性能要好于检测到错误预测时不只是回退到当前的退出状态,我认为使用某种检查点缓冲区。因此,在恢复期间分支可以继续执行之前,指令的乱序执行。

但是循环和其他分支非常普遍,因此大多数代码也从这种意义上“推测地”执行,至少有一个分支回滚检查点尚未被验证为正确的推测。在大多数情况下,这都是正确的推测,因此不会发生回滚。

恢复以错误推测内存顺序或错误负载是一个完整的流水线,回滚到淘汰架构状态。因此,我认为只有分支机构会消耗分支机构检查点微体系结构资源。

无论如何,所有这些都是使Spectre如此阴险的原因:CPU直到事后才知道错误推测与正确推测之间的区别。如果知道它是错误的推测,它将启动回滚而不是执行无用的指令/指令。间接分支也不罕见(在用户空间中)。在Windows和Linux上,每个DLL或共享库函数调用都使用普通可执行文件中的一个。

关于caching - 缓存缓存更改会阻止崩溃吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48196449/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com