summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2019-05-10 08:10:39 +0800
committerIru Cai <mytbk920423@gmail.com>2019-05-10 08:10:39 +0800
commit823e803107907915e8725e7a31d4b1f4dfe466f2 (patch)
tree35ff0a3f90d85a11e41ee1a98c2791c0c714cdc4
parente452464c954bca0098aa714ffd03c02ae4c42566 (diff)
downloaddissertation-823e803107907915e8725e7a31d4b1f4dfe466f2.tar.xz
import gtran
-rw-r--r--chap/chap3.tex104
1 files changed, 104 insertions, 0 deletions
diff --git a/chap/chap3.tex b/chap/chap3.tex
index 5fdd73e..4540453 100644
--- a/chap/chap3.tex
+++ b/chap/chap3.tex
@@ -78,6 +78,97 @@ TLB 添加了影子结构,推测式执行的指令对缓存和 TLB 修改临
\subsubsection{InvisiSpec}
+%%%%%% gtran %%%%%%
+在本文中,我们提出了InvisiSpec,这是一种通过在数据缓存层次结构中使推测不可见来抵御多处理器中的硬件推测攻击的新策略。目标是通过多处理器数据高速缓存层次结构来阻止微架构隐蔽和侧通道,这是由于推测性负载 - 例如,源自高速缓存集占用,线路替换信息和高速缓存一致性状态的信道。我们希望不仅防止基于分支机构推测的类似幽灵的攻击;我们还希望防止任何投机负载可能构成威胁的未来攻击。
+
+InvisiSpec的微架构基于两种机制。首先,不安全的推测性加载将数据读入新的推测缓冲区(SB)而不是缓存中,而不修改缓存层次结构。 SB中的数据不会观察缓存一致性事务,这可能导致丢失内存一致性违规。我们的第二种机制解决了这个问当推测性负载最终是安全的时,InvisiSpec硬件通过将其重新发送到内存系统并将数据加载到高速缓存中使其对系统的其余部分可见。在此过程中,如果InvisiSpec认为负载可能违反了内存一致性,InvisiSpec会验证负载首次读取的数据是否正确 - 如果数据不正确则压缩负载。
+
+% memory consistency
+
+内存一致性模型(或内存模型)指定内核执行内存操作的顺序,并由共享内存系统中的其他内核观察[10]。当商店退休时,其数据将存入写缓冲区。从那里,当内存一致性模型允许时,数据被合并到缓存中。我们说当数据合并到缓存中时执行存储,并且所有其他核心都可以观察到存储。负载可以在到达ROB头之前从内存中读取。我们说负载是在接收数据时执行的。负载可以从存储器读取并且不按顺序执行 - 即,在ROB中的早期加载和存储之前。无序负载可能导致内存一致性违规,核心通过推测执行的压缩和回滚机制恢复[11]。细节取决于内存模型;我们将在下面描述两种常见模型,我们将其假设为添加InvisiSpec的基线。
+
+总存储顺序(TSO)[12],[13]是x86架构的内存模型。 TSO禁止所有可观察的加载和存储重新排序,但存储→加载重新排序,即当负载绕过较早的存储到不同的地址时。实现通过确保负载在执行时读取的值在负载退出时保持有效,从而阻止可观察负载→负载重新排序。如果核心接收到负载读取的线路的高速缓存无效请求(或遭受高速缓存驱逐),则通过压缩已执行但尚未退出的负载来维持此保证。通过使用FIFO写入缓冲区来防止存储→存储重新排序,确保存储按程序顺序执行。如果需要,可以通过使用fence指令分隔存储和加载来防止存储→加载重新排序,该指令在完成所有先前的访问之前不会完成。原子指令具有栅栏语义。
+
+释放一致性(RC)[14]允许任何重新排序,除了跨同步指令。装载和存储不得通过先前的获取或随后的发布进行重新排序。因此,仅当存在先前的非退休获取并且具有非FIFO写缓冲区时,RC实现压缩在接收到其高速缓存行的无效时执行加载。
+
+\begin{tabular}{|c|c|}
+\hline
+攻击 & 瞬时指令的来源\tabularnewline
+\hline
+\hline
+Meltdown & \multirow{2}{*}{虚拟内存异常}\tabularnewline
+\cline{1-1}
+L1TF & \tabularnewline
+\hline
+LazyFP & \multirow{2}{*}{读取禁用的或者特权寄存器发生异常}\tabularnewline
+\cline{1-1}
+Rogue System Register Read & \tabularnewline
+\hline
+Spectre & 控制流预测错误\tabularnewline
+\hline
+Speculative Store Bypass & 装载指令和更早的存储指令地址别名\tabularnewline
+\hline
+未来的攻击 & 异常、控制流预测错误、访存别名、一致性违例、中断等\tabularnewline
+\hline
+\end{tabular}
+
+1)不安全的推测负载:严格地说,任何在到达ROB头部之前启动读取的负载都是推测负载。在这项工作中,我们对可能由于推测而产生安全漏洞的(大)投机负载子集感兴趣。我们称这些负载为Unsafe Speculative Loads(USLs)。作为USL的一组推测性负载取决于攻击模型。
+
+在Spectre攻击模型中,USL是遵循未解决的控制流指令的推测性负载。一旦控制流指令解决,跟随它的USL在分支的正确路径中转换到安全负载 - 尽管它们仍然是推测性的。
+
+在我们的未来攻击模型中,USL是所有可以被先前指令压扁的推测性负载。一旦USL变为(i)非推测性的,因为它到达ROB的头部或者(ii)推测不能通过任何先前的指令(或推测性的不可压缩的短路)变为安全负载。推测性非可压缩负载是(i)不在ROB的头部并且(ii)在ROB之前仅通过指令而不是由表I中的任何压扁事件压缩的未来的负载。请注意,在表中,其中一个压缩事件是中断。因此,使负载安全包括延迟中断直到负载到达ROB的头部。
+
+要了解为什么这两个条件允许USL过渡到安全负载,请考虑以下内容。 ROB头上的负载本身不能是瞬态的;它可以被压扁(例如,由于异常),但它是一个正确的指令。关于推测性非可压缩负载也可以这样说。这是因为,虽然不在ROB头部,但是它们不能被任何先前的指令压扁,因此可以被认为是ROB头部处的指令的逻辑扩展。
+
+2)使USLs看不见:InvisiSpec背后的想法是让USL隐形。这意味着USL无法以任何其他线程可见的方式修改缓存层次结构,包括一致性状态。 USL将数据加载到我们称为Speculative Buffer(SB)的特殊缓冲区中,而不是加载到本地缓存中。如上所述,USL可以转换到安全负载的时间点。此时,称为可见性点,InvisiSpec采取的行动将使USL可见 - 即,将使USL在内存层次结构中的所有副作用对所有其他线程都明显。 InvisiSpec通过重新加载数据使USL可见,这次将数据存储在本地缓存中并更改缓存层次结构状态。负载可能仍然是推测性的。
+
+3)维护内存一致性:负载的可抑制可见性窗口是从USL发出负载到使其自身可见之间的时间段。在此期间,由于USL不会更改任何一致性状态,因此核心可能无法接收针对USL加载的线路的无效。因此,负载违反内存一致性模型存在未检测到的风险。这是因为这种违规通常是通过传入的失效来检测的,并且通过压缩负载来解决。要解决此问题,InvisiSpec可能必须在负载的可见点重新加载数据时执行验证步骤。
+
+当USL发布并且线路加载到SB时,USL请求的线路可能已经在核心的L1缓存中。在这种情况下,核心可能会收到该行的无效。但是,USL忽略了这种失效,因为USL是不可见的,并且这种失效的任何影响都将在可见点处理。
+
+4)USL的验证或曝光:在可见性点重新加载数据的操作有两种形式:验证和曝光。如果在该窗口期间,核心已经收到USL加载的行的无效,则验证是在可抑制可见性窗口期间(由于内存一致性考虑)使可见的USL可见的方法。验证操作包括将USL使用的实际字节(存储在SB中)与从缓存层次结构加载的最新值进行比较。如果它们不相同,USL及其所有连续指令都会被压扁。这是满足内存一致性模型所必需的。这一步让人想起Cain和Lipasti的基于价值的记忆排序[31]。
+
+ 验证可能很昂贵。持久验证的USL在事务结束之前不能退出 - 即,从高速缓存层次结构获得的行被加载到高速缓存中,行的数据与SB中使用的子集进行比较,并做出关于压缩的决定。因此,如果USL位于ROB头并且ROB已满,则管道停止。
+
+值得庆幸的是,InvisiSpec识别出许多在其抑制可见性窗口期间无法违反内存一致性模型的USL,并允许它们以廉价的曝光可见。 如果在该窗口期间核心已经收到USL加载的行的无效,则这些USL在禁用可见性窗口期间不会被内存一致性模型压扁。 在曝光中,缓存层次结构返回的行只是存储在缓存中而不进行比较。 一旦将行请求发送到缓存层次结构,持续曝光的USL就会退出。 因此,USL不会阻止管道。
+
+总而言之,有两种方法可以使USL可见:验证和曝光。 内存一致性模型确定需要哪一个。 图2显示了具有验证和曝光的USL的时间线。
+
+InvisiSpec的负载有两个步骤。首先,当它作为USL发布到内存时,它访问缓存层次结构并获得所请求的缓存行的当前版本。该行仅存储在本地SB中,本地SB与L1高速缓存一样靠近核心。 USL不修改高速缓存一致性状态,高速缓存替换算法状态或任何其他高速缓存层次结构状态。没有其他线程(本地或远程)可以看到任何更改。但是,核心使用USL返回的数据来取得进展。 SB存储行而不是单个词来利用空间局部性。
+
+当可以使USL可见时,并且总是在它收到其请求的高速缓存行之后,硬件触发验证或暴露事务。这样的事务再次重新请求该行,这次修改缓存层次结构,并将该行带到本地缓存。如第V-A4部分所述,验证和暴露交易的运作方式不同,并且具有不同的性能影响。
+
+我们考虑两种攻击模型,幽灵和未来派,并提出略微不同的InvisiSpec设计来抵御这些攻击中的每一种。在我们对Specter攻击的防御中,USL在其所有先前的控制流指令解决时达到其可见性点。此时,硬件根据内存一致性模型和负载在ROB中的位置(第V-C节)发出负载的验证或暴露事务。如果多个USL可以发出验证或暴露交易,则交易必须按程序顺序开始,否则全部重叠(第V-D节)。
+
+在我们对未来攻击的防御中,USL只有在以下情况下才能达到其可见性:( i)它不再是推测因为它位于ROB的头部,或者(ii)它仍然是推测性的,但不能再被压扁。此时,硬件根据内存一致性模型和负载在ROB中的位置(第V-C节)发出负载的验证或暴露。如果多个USL可以发出验证或暴露交易,则必须按程序顺序发布交易。但是,当发布验证交易时,后续验证或暴露交易不会与之重叠;在验证完成之前,他们都必须等待发布(第V-D节)。另一方面,当发出暴露交易时,直到并包括下一个验证交易的所有后续暴露交易都可以与之重叠(第V-D节)。
+
+总的来说,在幽灵和未来派防御设计中,当验证事务阻止ROB头部的负载退出并且ROB已满时,可能会发生唯一的管道停顿。这在未来派中比在幽灵中更有可能。
+
+我们将这些设计称为InvisiSpec-Spectre(或IS-Spectre)和InvisiSpec-Future(或IS-Future)。它们显示在表II的第一行中。为了进行比较,第二行显示了如何使用基于栅栏的方法防御这些相同的攻击 - 遵循当前提出的防御幽灵的建议[32]。我们将这些设计称为Fence-Spectre和Fence- Future。前者在每个间接或有条件的分支后放置围栏;后者在每次装载前放置围栏。
+
+与基于栅栏的设计相比,InvisiSpec提高了性能。具体而言,负载是在传统的不安全机器中推测性地执行的。一个问题是ROB头部的负载的验证事务可能使管道停滞。但是,我们将展示如何以验证次数为代价最大化曝光次数(不会导致失速)。最后,InvisiSpec确实会创建更多缓存层次结构流量并争用各种缓存端口。应该设计硬件来处理它们。
+
+内存一致性模型确定何时使用验证以及何时使用曝光。首先考虑TSO。在高性能TSO实现中,当ROB中没有较旧的负载(或栅栏)时读取的推测性负载将不会被随后的对其读取的线路的无效进行压缩。因此,这样的USL可以在其变得可见时使用曝光。另一方面,当ROB中存在至少一个较旧的负载(或栅栏)时读取的推测性负载将被其读取的行的无效压缩。因此,这样的USL需要使用验证。
+
+现在考虑RC。在这种情况下,只有在ROB中存在至少一个早期栅栏时读取的推测性负载将被线路读取的无效压缩。因此,只有那些将被要求使用验证;绝大多数负载都可以使用暴露。
+
+从这个讨论中,我们看到在TSO下观察停止管道验证的机会最高的设计是IS-Future。为了减少这些事件的发生,InvisiSpec实现了两种机制。第一个允许一些使用验证的USL代替使用曝光。第二个标识可以使用验证的USL,如果验证失败的可能性很大,则提前将它们压扁。我们接下来考虑这些机制。
+
+1)将验证USL转换为曝光USL:假设在TSO下,USL1在ROB中存在较早的负载时启动读取。通常,InvisiSpec会将USL1标记为需要验证。但是,假设在读取时,早于USL1的ROB中的所有负载已经获得了他们请求的数据 - 特别是,如果它们是USL,则他们请求的数据已经到达SB并且已经到达传递到登记册。在这种情况下,USL1不会相对于任何早期的负载重新排序。因此,TSO不会要求在收到对其加载的线路无效时压缩USL1。因此,USL1被标记为需要曝光,而不是验证。
+
+为了支持这种机制,我们用一个名为Performed的位来标记每个USL。当USL请求的数据已在SB中接收并传递到目标寄存器时设置。
+
+2)USL的早期压缩需要验证:假设核心接收到其缓存中的行的失效,该行也恰好被标记为需要验证的USL加载到其SB中。接收失效表示该行已更新。此类更新通常会导致USL在可见性失败时的验证。如果此失效是由错误共享引起的,或者如果对该行的所有更新的净效果直到验证结果是无声的(即,它们将数据恢复到其初始值),则验证才能成功。由于这些条件不太可能发生,InvisiSpec会因接收失效而挤压这样的USL。还有第二个USL的案例,验证失败的可能性很高。假设USL1需要验证并且在SB中有数据。此外,有一个较早的USL2到同一行(但对于该行的不同单词),其在SB中也有其数据并需要验证。当USL2执行验证并将线路连接到核心时,InvisiSpec还会将该线路与SB中的USL1数据进行比较。如果数据不同,则表明USL1已读取陈旧数据。那时,InvisiSpec保守地压制了USL1。
+
+ % skips subsection D, E
+
+USL执行两个事务 - 一个是首次发布时,一个是验证或公开时。现在,假设USL的第一次访问错过最后一级缓存(LLC)并访问主内存。然后,USL的第二次访问可能也是对主内存的长延迟访问。
+
+为了提高性能,我们设计了InvisiSpec,以避免在大多数情况下进行第二次主存访问。具体来说,我们在LLC旁边添加了每核LLC推特缓冲区(LLC-SB)。当USL的第一次访问从主存储器读取该行时,当该行被发送回请求核心的L1 SB时,InvisiSpec将其副本存储在核心的LLC-SB中。之后,当USL发布其验证或曝光时,它将从核心的LLC-SB读取该行,跳过对主存储器的访问。
+
+如果在两次访问之间,第二个核心通过验证/暴露或安全访问访问该线路,则InvisiSpec使来自第一个核心的LLC-SB的线路无效。这保守地确保LLC-SB不保存陈旧数据。在这种情况下,原始USL的验证或公开事务将从缓存层次结构中的任何位置获取该行的最新副本。
+%%%%%%%%%%%%%%%%%%%
+
InvisiSpec\supercite{invisispec} 和 SafeSpec 类似,使用一个称为推测式
执行缓冲区(Speculative Buffer)的结构存放推测式执行的 load 指令从存储
系统中获取的数据,直到这条指令安全的时候再让它更新缓存。和 SafeSpec 不
@@ -236,6 +327,19 @@ S-Pattern 不匹配,则被认为是安全的。
\subsubsection{SpectreGuard}
+%%% gtran %%%
+
+自Spectre披露以来,已经提出了几种基于软件和硬件的缓解策略。基于软件的缓解策略通过手动插入序列化指令[12]或在条件跳转和后续存储器加载指令之间引入其他数据依赖性[7,21]来防止推测。但是,手动识别程序的易受攻击的分支是困难的,而通过编译器自动化保护所有分支会导致过多的性能开销[21]。基于硬件的方法通常通过引入额外的硬件结构来缓冲推测结果来集中隐藏攻击者可观察的微架构状态变化[13,27]。虽然它们不需要手动更改代码,但它们会导致侵入式硬件更改和高性能开销[13,27]。
+
+在本文中,我们提出了SpectreGuard,一种针对幽灵攻击的新型跨层防御。我们的方法是以数据为中心的,因为我们专注于程序的数据而不是代码。我们观察到,对于软件开发人员来说,识别程序的秘密数据(例如,密钥)可能比识别易受攻击的代码块(即,幽灵小工具)更容易,这些代码块可以出现在程序的任何分支中,即使它们不相关处理秘密数据。因此,我们的方法首先要识别敏感的内存块,这些内存块保存秘密数据,并将它们标记为非推测性内存区域。识别的存储区域通过简单的OS /库API被通知给OS,然后由硬件利用以通过低成本的微架构扩展选择性地和有效地防止推测性攻击。
+
+我们的微架构扩展很小,并且基于一个基本观察,即成功的Specter变体1攻击需要以下三个不同的步骤推测性地发生:(步骤1)秘密数据从存储器层次加载; (步骤2)然后将其转发给相关指令; (步骤3)执行从属指令,通过微架构隐蔽信道(例如,高速缓存)泄漏秘密。重要的是要注意秘密是通过第二和第三步骤泄露的,在此期间留下了攻击者可观察的,秘密依赖的,微观建筑的足迹。换句话说,即使秘密数据被加载到CPU管道上,除非它被转发到秘密相关指令,否则秘密不会泄露给攻击者。
+
+ 基于这种观察,我们的方法允许第一步发生但延迟第二步直到所有先前的分支被解决之后。请注意,仅当第一步中的虚拟地址在非推测内存区域内时才需要此延迟。所有其他“正常”地址可以立即转发到任何等待的相关指令。因此,不经常访问的秘密将在整体性能上具有可忽略的开销。
+
+%%%%%%%%%%%%%%
+
+
SpectreGuard\supercite{spectreguard} 是一种软硬件结合防御 Spectre 攻击
的方法。软件在页表中标记一个页是否存在秘密数据,如果一条指令在推测式执
行中读取了带标记的页中的数据,处理器则禁止这条指令将读取的值转发至其他