我试图了解漏洞的RIDL类。
这是一类漏洞,能够从各种微体系结构缓冲区读取陈旧数据。
如今,已知的漏洞得以利用:LFB,加载端口,eMC和存储缓冲区。
链接的论文主要针对LFB。
我不明白为什么CPU会满足LFB中过时数据的负载。
我可以想象,如果一个负载击中了L1d,它会在内部“重播”,直到L1d将数据带到LFB中,以信号通知OoO内核停止“重播”(因为现在读取的数据是有效的)。
但是我不确定“重播”到底是什么意思。
我认为负载已分派到具有负载能力的端口,然后记录在负载缓冲区(MOB)中,并最终根据需要保持,直到它们的数据可用为止(由L1发出信号)。
因此,我不确定“重播”如何发挥作用,此外,为了使RIDL工作,每次“播放”负载的尝试也应解除对相关指令的阻塞。
这对我来说似乎很奇怪,因为在加载正确完成之后,CPU需要跟踪要重播的指令。
RIDL上的论文以该代码为例(不幸的是,由于PDF布局不允许我复制它,因此我不得不将其粘贴为图像):
它可以工作的唯一原因是,如果CPU首先用旧数据满足第6行的负载,然后重播它。
这似乎证实了以下几行:
具体来说,我们可能期望两个
访问速度很快,而不仅仅是与
泄漏的信息。毕竟,当处理器发现
它的错误并以正确的值在第6行重新开始
程序还将使用该索引访问缓冲区。
但是我希望CPU在转发LFB(或任何其他内部缓冲区)中的数据之前先检查负载的地址。
除非CPU实际重复执行加载操作,直到它检测到加载的数据现在有效(即正在重放)为止。
但是,再次,为什么每次尝试都会取消阻塞相关指令?
重播机制(即使存在)如何精确工作,以及它如何与RIDL漏洞相互作用?
最佳答案
我认为RIDL攻击不涉及来自RS的负载重播。因此,除了解释什么是负载重播(@Peter的回答是一个很好的起点)之外,我将基于对RIDL文件中提供的信息(英特尔对这些漏洞的analysis的理解)来讨论我认为正在发生的事情。以及相关专利。
行填充缓冲区是L1D高速缓存中的硬件结构,用于保存在高速缓存中丢失的内存请求和I / O请求,直到它们得到服务为止。当所需的缓存行填充到L1D数据阵列中时,可缓存的请求得到服务。当出现用于退出写合并缓冲区的任何条件时(如手册中所述),将执行写合并写操作。将UC或I / O请求发送到L2高速缓存时,该请求会得到服务(尽快发生)。
请参考RIDL paper的图4。用于产生这些结果的实验如下:
受害线程将已知值写入单个内存位置。存储位置的存储类型为WB,WT,WC或UC。
受害线程在循环中读取相同的内存位置。每个加载操作后跟MFENCE
,并且有一个可选的CLFLUSH
。从纸上来说,我不清楚CLFLUSH
相对于其他两个指令的顺序,但这可能并不重要。 MFENCE
序列化高速缓存行刷新操作,以查看在高速缓存中每个负载未命中时会发生什么。另外,MFENCE
减少了L1D端口上两个逻辑核心之间的争用,从而提高了攻击者的吞吐量。
在同级逻辑内核上运行的攻击者线程循环执行清单1中所示的代码。第6行使用的地址可以是任何地址。唯一重要的是第6行的负载发生故障或导致需要微码辅助(以设置页表项中的访问位)的页面遍历。分页遍历也需要使用LFB,并且大多数LFB在逻辑核心之间共享。
我不清楚图4中的Y轴代表什么。我的理解是,它表示每秒从隐式通道提取到高速缓存层次结构(第10行)中的行数,其中数组中行的索引等于受害者写入的值。
如果内存位置是WB类型,则当受害者线程将已知值写入内存位置时,该行将被填充到L1D高速缓存中。如果存储器位置是WT类型,则当受害者线程将已知值写入存储器位置时,该行将不会填充到L1D高速缓存中。但是,在该行的第一次读取中,它将被填充。因此,在两种情况下,如果没有CLFLUSH
,来自受害线程的大多数负载都会进入缓存。
当装入请求的高速缓存行到达L1D高速缓存时,它将首先写入为请求分配的LFB中。可以将高速缓存行的请求部分从LFB直接提供给加载缓冲区,而不必等待将行填充到高速缓存中。根据对MFBDS漏洞的描述,在某些情况下,先前请求中的陈旧数据可能会转发到加载缓冲区,以满足加载uop的要求。在WB和WT情况下(不刷新),受害者的数据最多被写入2个不同的LFB中。从攻击者线程走来的页面很容易覆盖LFB中的受害者数据,此后攻击者线程将永远无法在其中找到数据。 L1D高速缓存中命中的所有负载请求都不会通过LFB。它们有一条单独的路径,与来自LFB的路径复用。但是,在某些情况下,来自LFB的陈旧数据(噪声)被推测性地转发到了攻击者的逻辑核心,而这可能是来自页面遍历(以及中断处理程序和硬件预取器)的。
有趣的是,在WB和WT情况下,过时的数据转发频率远低于所有其他情况。这可以通过以下事实来解释:受害人的吞吐率在这些情况下要高得多,并且实验可能会更早终止。
在所有其他情况下(WC,UC和所有带刷新的类型),缓存中的每个负载都会丢失,并且必须通过LFB将数据从主内存中提取到负载缓冲区。发生以下事件序列:
来自受害者的访问在TLB中命中,因为它们是对同一有效虚拟页面的访问。物理地址是从TLB获得的,并提供给L1D,后者为请求分配LFB(由于未命中),并且物理地址与描述加载请求的其他信息一起被写入LFB。此时,来自受害者的请求正在LFB中等待处理。由于受害者在每次加载后执行MFENCE
,因此在任何给定周期内,LFB中最多有一个来自受害者的未完成负载。
运行在同级逻辑核心上的攻击者向L1D和TLB发出加载请求。每次加载都针对未映射的用户页面,因此将导致故障。当它在TLB中未命中时,MMU告诉加载缓冲区应阻止加载,直到地址转换完成为止。根据该专利的第26段和其他英特尔专利,这就是TLB遗漏的处理方式。地址转换仍在进行中,负载已被阻止。
来自受害者的加载请求接收其高速缓存行,该高速缓存行被写入为该加载分配的LFB中。负载请求的那部分行被转发到MOB,同时,该行被写入L1D高速缓存。此后,可以对LFB进行脱涂层处理,但不会清除任何字段(指示其空闲状态的字段除外)。特别是,数据仍在LFB中。然后,受害者发送另一个加载请求,该请求也由于无法缓存或已刷新缓存行而在缓存中丢失。
攻击者的负载的地址转换过程完成。 MMU确定由于物理页面不存在而需要引发故障。但是,直到负载即将卸除(到达ROB的顶部)时,故障才引发。无效的翻译未缓存在Intel处理器的MMU中。 MMU仍必须告诉MOB转换已完成,在这种情况下,需要在ROB的相应条目中设置错误代码。看起来,当ROB看到其中一个uops具有有效的故障/辅助代码时,它将禁用与该uops的大小和地址有关的所有检查(可能还有ROB中所有以后的uops)。这些检查不再重要。据推测,禁用这些检查可以节省动态能耗。退出逻辑知道,当负载即将退出时,无论如何都会出现故障。同时,当MOB获悉翻译已完成时,它将照常重放攻击者的负载。但是,这一次,某些无效的物理地址提供给了L1D缓存。通常,需要将物理地址与来自同一逻辑核心的LFB中所有未决请求进行比较,以确保逻辑核心看到最新的值。这是在查找L1D缓存之前或同时完成的。物理地址并不重要,因为已禁用比较逻辑。但是,所有比较的结果都表现得好像结果表明成功一样。如果至少有一个分配的LFB,则物理地址将与某个分配的LFB匹配。由于受害人有未完成的请求,并且受害人的机密可能已经与先前的请求写入了相同的LFB,因此缓存行的相同部分从技术上讲包含过时数据,在这种情况下,过时数据是机密),将转发给攻击者。请注意,攻击者可以控制高速缓存行中的偏移量和要获取的字节数,但无法控制哪个LFB。高速缓存行的大小为64字节,因此攻击者负载的虚拟地址中只有6个最低有效位与负载的大小有关。然后,攻击者使用数据将其索引到其数组中,以使用高速缓存侧通道攻击来揭示秘密。这种行为也可以解释MSBDS,其中显然会禁用数据大小和STD uop检查(即,检查不容易通过)。
之后,故障/辅助负载到达ROB的顶部。负载不会消失,管道会被冲洗。如果负载出现故障,则会引发故障。在辅助加载的情况下,从相同的加载指令重新开始执行,但需要在页面结构中设置所需的标志。
重复这些步骤。但是攻击者可能并不总是能够从受害者那里泄露秘密。如您所见,攻击者的加载请求必然会碰到分配的包含机密信息的LFB条目。为页面遍历和硬件预取程序分配的LFB可能会更难于执行成功的攻击。
如果攻击者的负载没有故障/没有得到协助,则LFB将从MMU接收有效的物理地址,并执行所有必要的检查以确保正确性。这就是负载必须故障/辅助的原因。
本文的以下引文讨论了如何在同一线程中执行RIDL攻击:
我们通过自己编写值执行无SMT的RIDL攻击
线程并观察我们从同一线程泄漏的值。
图3显示,如果我们不写值(“没有受害者”),则会泄漏
只有零,但受害者和攻击者在同一硬件上运行
线程(例如,在沙箱中),我们几乎在所有
案件。
我认为此实验中没有特权级别更改。受害者和攻击者在同一硬件线程上的同一OS线程中运行。从受害者返回攻击者时,LFB中可能仍存在来自(尤其是来自商店)的一些未完成的请求。请注意,在RIDL论文中,所有实验均启用了KPTI(与Fallout论文相反)。
除了从LFB泄漏数据之外,MLPDS还显示数据也可以从加载端口缓冲区泄漏。这些包括行分割缓冲区和用于大于8个字节大小的负载的缓冲区(我认为当负载uop的大小大于负载端口的大小时,例如SnB / IvB上的AVX 256b,我认为这是必需的占用端口2个周期)。
图5中的WB情况(无冲洗)也很有趣。在该实验中,受害线程将4个不同的值写入4个不同的缓存行,而不是从同一缓存行中读取。该图显示,在WB情况下,只有写入最后一条缓存行的数据才泄漏给攻击者。解释可能取决于高速缓存行在循环的不同迭代中是否不同,但不幸的是在本文中并不清楚。论文说:
对于不刷新的WB,仅最后一个缓存有一个信号
行,这表明CPU可以在一个单独的时间内执行写合并
在将数据存储在高速缓存中之前,先将LFB条目存储在LFB中。
在将数据存储到高速缓存之前,如何将写入不同高速缓存行的写入合并到同一LFB中?这是零意义。 LFB可以容纳单个高速缓存行和一个物理地址。只是不可能合并这样的写法。可能发生的情况是,WB写操作正在分配给为其RFO请求分配的LFB中。当将无效的物理地址发送到LFB进行比较时,可以始终从最后分配的LFB提供数据。这可以解释为什么只泄漏第四存储写入的值。
有关MDS缓解的信息,请参阅:What are the new MDS attacks, and how can they be mitigated?。我的回答仅讨论基于英特尔微码更新的缓解措施(不是非常有趣的“软件序列”)。
下图显示了使用数据推测的易受攻击的结构。