为什么CPU推测性执行不会导致OOB程序崩溃?

时间:2018-01-07 10:31:46

标签: security memory cpu

问题源于阅读Spectre attack paper。如果我理解正确,攻击源于CPU启发式推测性地执行(错误的)代码分支的可能性。 考虑一下这个例子(在C中):

int arr[42];
if (i < 42) {
    int j = arr[i];
}

如果我正确理解了论文,即使int j = arr[i]i >= 42也可以(在某些情况下)推测性地执行。我的问题是 - 当我访问数据超出其范围时,我的程序经常崩溃(Linux上的分段错误,&#34;程序执行非法操作&#34; Windows上的错误)。

为什么在数组越界访问的情况下,推测性执行不会导致程序崩溃?

1 个答案:

答案 0 :(得分:3)

关键在于,在现代CPU中,动词执行并不代表您认为的含义。

执行指令是计算其输出和副作用的行为(如果有的话) 但是,此不会更改程序状态 这开始似乎很难掌握,但它真的没什么异国情调。

CPU的所有寄存器都有一个相当大的内部存储器,这个存储器的大部分对程序员可见,它被称为架构状态< / em>的。
体系结构状态(AS)是CPU手册中记录的内容,以及由一系列指令(例如程序)改变的内容。

由于改变AS只能在ISA(手册)中给出的语义中发生,并且ISA指定了串行语义(指令在程序顺序中一个接一个地完成),因此不允许并行化。 /> 但是,现代CPU具有许多可以独立完成工作的资源(称为执行单元)。

为了利用所有这些资源,CPU的前端(负责从存储器层次结构读取指令并将它们提供给执行单元的部分)能够在每个周期内到达,解码和输出更多的一条指令。
前端和后端之间的边界(执行单元所在的位置)不再处理指令(但是使用uops),但这是x86 CISC的麻烦。

所以现在CPU被给予4/6 uops一次“执行”但是如果ISA是串行的,除了排队这些uops之外它可能做什么呢?
好吧,前端是这样的,这些uops不能在AS上运行,但在阴影状态(SS,我的术语在这里),它们的操作数被重命名,由大部分组成CPU的无形记忆 并行或无序改变是好的,因为它不是AS 这就是执行:改变SS。

真的值得吗?毕竟,重要的是AS 好吧,与执行相比,将SS转移到AS非常快,所以值得 这是“重命名”(反转之前的重命名)的问题,它被称为退休指令。

实际上,退休远不止于此 由于执行不影响AS,副作用也不应影响它 这些副作用包括异常,但推测性地处理异常过于繁琐(需要协调大量资源),因此异常处理延迟直到退休。
这也具有在处理异常时具有正确AS的优点以及仅在实际必须的情况下引发异常的优点。

推测性执行的意思是下注,CPU下注指令序列不会产生任何异常(包括页面错误),因此在大多数检查关闭时执行它(我不能排除,脱离我的头脑,不管怎样都不做一些检查,从而获得了很多好处 当退出这些指令时,将检查投注,如果失败,则丢弃SS。

这就是推测性执行不会导致程序崩溃的原因。

Spectre所依赖的是这样一个事实:在某种意义上,推测性执行确实改变了AS:缓存没有失效(再次出于性能原因,当赌注关闭时SS根本不会被复制到AS中)和时间安排攻击是可能的。
这可以通过多种方式进行纠正,包括在从TLB读取时执行基本权限检查(在使用所有权限0和3之后,因此逻辑很简单)或向缓存行添加一些位以标记它们是推测的(被非推测性代码视为无效)。