summaryrefslogtreecommitdiff
path: root/chap/chap3.tex
blob: ec0f8245ee05f2221bd38379715bc6411f00f751 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
% Copyright (c) 2014,2016,2018 Casper Ti. Vector
% Public domain.

\chapter{Meltdown和Spectre攻击的防御方案分析}\label{sec:defense}

Meltdown 和 Spectre 及其多种变体被发现后,研究者提出了多种减轻这些攻击
的防御方法,它们需要对软件或硬件进行修改。也有研究者提出通过修改现有的
指令系统\supercite{oisa},使得用这种指令系统的程序不受 Spectre 攻击的
影响。

\section{Meltdown型攻击的防御}

Meltdown型攻击利用了瞬时指令可以读取体系结构层次上不可访问的数据,并且
用此数据做计算。因此一种防御方式是使体系结构层次上不可访问的数据,在微
架构层次上仍然不可访问。

KAISER\supercite{kaiser}是一种已经部署在 Linux 内核上的一种防御
Meltdown 攻击的方案。它的作用是在用户空间中去除内核空间的地址映射,使
得用户空间的执行的指令无法访问内核空间的存储区域。

防御 Meltdown 型攻击的第二种方法是阻止异常的产生。例如对于 LazyFP,最
新的 Linux 内核在上下文切换时,对所有进程都会保存和恢复浮点寄存器,从
而用户程序使用浮点寄存器都不会产生异常,从而消除这种攻击。

\section{Spectre型攻击的防御}

Spectre 型攻击的防御方案可以分为三类:阻止推测式执行、防止瞬时指令访问
秘密数据、切断隐蔽信道或降低隐蔽信道的精度。研究者在软件和硬件方面都提
出了防御方案。

\subsection{软件防御方案}

Intel 和 AMD 都提出了在分支指令后插入 lfence 指令阻止推测式执行的方
法。\supercite{intel-spectre}\supercite{amd-spectre}lfence 指令在此作
为一条串行化指令使用,可以在 lfence 指令提交前阻止新的指令执行,从而阻
止了程序在推测式执行中对秘密数据进行操作。

\Todo: 增加 SLH,retpoline,index masking 相关的代码

由于 lfence 性能开销大,LLVM提出推测式装载指令加固(Speculative
Load Hardening)\supercite{spec-load-hardening} 技术,它的作用是在指令
流中添加数据相关,使得装载指令使用的地址依赖于分支结果。

retpoline\supercite{retpoline} 是 Google 提出的防御 Spectre-BTB 的方法。
它的作用是把程序中的间接转移指令修改为一个指令序列,最终使用 ret 指令
完成跳转,从而使用 RSB 而不是 BTB 来进行间接转移的转移预测。

% index masking
Webkit 在数组访问中使用 index masking\supercite{webkit} 方法,它让数组
下标和一个值进行与操作,去掉下标高位的1,将数组下标控制在一定范围内,
防止处理器在推测式执行中访问数组指定范围之外的数据。Linux 构造了一个粒
度更细的 array\_index\_nospec 宏\supercite{linux-spec},使得在推测式执
行的过程中,数组的索引始终在界内,避免了推测式的访问秘密数据。

% poison value
Webkit 还使用了指针投毒(pointer poisoning)的方式,它考虑分支用于做类
型检查的情形。对于不同类型的数据,Webkit 将这种类型的指针和一个类型对
应的值异或,要使用的时候再异或这个值得到指向数据的指针,如果类型不匹配,
则得到的指针会指向一个程序无法访问的内存区域。通过这种方法,程序在推测
式执行中无法通过这种指针访问到程序中的数据,从而避免了秘密数据的泄露。

% site isolation, \Fixme: needs citing
Google 为 Chrome 浏览器使用了站点隔离(site isolation)技术,使得浏览
器用不同的进程访问不同的网站,从而攻击者无法通过用 Javascript 通过侧信
道攻击获取另一站点相关的数据。

% timer reduction
降低计时器精度可以降低计时攻击所用侧信道的精度,一个例子是在浏览器中降
低 Javascript 引擎中 performance.now 等计时器的精度。
\supercite{webkit} 但是相关研究发现,攻击者可以使用其他方式构造高精度
的计时器\supercite{js-timer},因此降低计时器精度不是一个有效的防御方法。


\subsection{硬件防御方案}

\subsubsection{SafeSpec}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gtran %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\Todo: SafeSpec III. SAFESPEC :LEAKAGE - FREE SPECULATION 一章,包含一
些设计选择

\Fixme: 需要重新翻译

SafeSpec\supercite{safespec}提出了一种原则性的方法来保护处理器免受推测
式执行攻击,同时保留执行推测性执行以从其性能中受益的能力。一般原理(如
图\ref{fig:safespec}所示)使用临时结构(图中的阴影状态)来保存任何以推
测方式产生的状态,而不会影响处理器的主要结构(我们在图中称为提交状态)。
例如,如果推测性加载指令导致加载高速缓存行,而不是将该高速缓存行加载到
处理器高速缓存中,我们将该行保存在临时结构中。如果稍后对加载指令进行压
缩,则会将这些效果移除(从提交状态开始的底部路径),不会从错误推测的指
令中更改缓存,并关闭漏洞。或者,如果指令提交,则将高速缓存行从临时结构
移动到L1高速缓存并从阴影状态中移除。

\begin{figure}[htbp]
  \centering
  \includegraphics[width=0.8\textwidth]{safespec.eps}
  \caption{SafeSpec 总体设计}
  \label{fig:safespec}
\end{figure}

虽然SafeSpec原则上很简单,但必须解决许多与其安全性,复杂性和性能相关的
问题。我们将在本节的其余部分概述这些问题。

% transient to commit
有两个选项可用于决定何时将状态从阴影移动到已提交状态。在第一个变量中,
我们称之为等待分支(WFB),我们可以假设一条指令在它所依赖的所有分支
(更一般地说,所有预测)都已被解析时不再是推测性的。 WFB阻止两种幽灵的
变种,它们依赖于错误分支预测;没有任何错误推测的指令移动到已提交状态。
但是,它不会阻止不依赖于分支预测器的Meltdown。第二个变量等待提交(WFC)
等待直到导致推测性副作用的指令在将其效果移动到提交状态之前提交,因此也
会阻止崩溃。我们注意到,根据此定义的重新排序缓冲区是一种阴影状态,只有
在提交指令时,其数据才会移动到永久状态(架构状态)。

阴影状态组织和大小:如果阴影状态结构太小,则替换推测状态(如果稍后将提
交此数据,则导致丢失对已提交状态的更新),或者指令必须停止,直到那里在
发布之前,它是投机结构的空间。因此,从性能的角度来看,应该设计影子结构
的组织和大小,使得结构可以保持通过在典型工作负载上测量的推测产生的推测
状态。但是,我们将证明安全考虑因素对投机状态提出了更严格的要求。

减轻瞬态猜测攻击:通过构造安全规范可以防止推测值影响已提交结构的状态,
这是在已发布的推测攻击中隐蔽地传递数据的途径。但是,它不会在处于推测状
态的指令之间创建隔离。这为我们称为瞬态推测攻击(TSA)的新型攻击创造了
可能性。特别是,由于提交的指令可以处于推测状态(在它们的依赖分支在WFB
中提交之前,或者在指令本身在WFC中提交之前),因此有一个时间窗口,它们
可以在它们之前与错误指定的指令共享推测状态。被压扁了。如果我们不小心,
可以在此期间创建一个隐蔽通道,将敏感数据从错误推测的分支传递到将要提交
的分支,从而允许数据被泄露。

考虑一个尺寸小的阴影结构的例子(比如说一个条目)。然后,读取特权数据的
恶意推测代码可以使用阴影状态秘密地将其传递给推测代码(将提交的“接收器”
代码)。例如,它可以替换阴影状态中的条目,导致接收者在提交后注意到其推
测状态(因为它被替换)的缺失。或者,如果我们在阴影结构已满时阻塞,接收
器可以检测到其代码执行时间较长。

尽管TSA的严重程度远低于原始攻击,但必须仔细考虑它们以确保无法进行泄漏。
解决此问题的一种方法是对每个分支的推测状态进行分区,或者对其进行大量调
整,或者甚至在最坏的情况下,以确保通过阴影状态不发生泄漏。 TSA还可以通
过在功能单元或其他共享结构上创建争用来秘密地进行通信;这是我们也考虑的
问题。我们将在第五节讨论如何减轻TSA攻击。

过滤延迟的副作用:当指令在执行过程中被压缩时,会发生SafeSpec的一个问题。
如果指令已经启动了高延迟操作,例如从内存中读取,我们必须确保在收到内存
后可以丢弃内存中的响应。 执行的指令推测性地将任何结果状态存储到阴影结
构。 因此,如果收到长等待时间回复并且没有匹配的事务,我们只是丢弃这些
值。 然而,也可能希望在系统中较低地过滤这些事务,使得提交的事务直接提
交,并且压缩的事务在适当的位置被取消。 为了控制此过滤器的大小,我们可
以在分支粒度中包含一个带有事务和跟踪操作的分支ID。 过滤器还可用于标记
已提交的分支,以便与其对应的内存响应直接提交到永久结构。

\Todo: SafeSpec for caches and TLB
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsubsection{InvisiSpec}

%%%%%% gtran %%%%%%

\Todo: InvisiSpec introduction, 去掉最前面的背景介绍部分

\Fixme: 重新翻译

在本文中,我们提出了InvisiSpec,这是一种通过在数据缓存层次结构中使推测不可见来抵御多处理器中的硬件推测攻击的新策略。目标是通过多处理器数据高速缓存层次结构来阻止微架构隐蔽和侧通道,这是由于推测性负载 - 例如,源自高速缓存集占用,线路替换信息和高速缓存一致性状态的信道。我们希望不仅防止基于分支机构推测的类似幽灵的攻击;我们还希望防止任何投机负载可能构成威胁的未来攻击。

InvisiSpec的微架构基于两种机制。首先,不安全的推测性加载将数据读入新的推测缓冲区(SB)而不是缓存中,而不修改缓存层次结构。 SB中的数据不会观察缓存一致性事务,这可能导致丢失内存一致性违规。我们的第二种机制解决了这个问当推测性负载最终是安全的时,InvisiSpec硬件通过将其重新发送到内存系统并将数据加载到高速缓存中使其对系统的其余部分可见。在此过程中,如果InvisiSpec认为负载可能违反了内存一致性,InvisiSpec会验证负载首次读取的数据是否正确 - 如果数据不正确则压缩负载。

% memory consistency

\Todo: InvisiSpec 考虑了内存模型,下面是关于 TSO 和 RC 的介绍

\Fixme: 重新翻译

内存一致性模型(或内存模型)指定内核执行内存操作的顺序,并由共享内存系统中的其他内核观察[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}

\Todo: InvisiSpec  V: INVISISPEC: THWARTING SPECULATION ATTACKS

\Fixme: 重新翻译以下内容

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的验证或公开事务将从缓存层次结构中的任何位置获取该行的最新副本。
%%%%%%%%%%%%%%%%%%%

在 gem5 模拟器下, 使用 SPEC CPU2006 和 PARSEC 对 InvisiSpec 进行评测,
以 Spectre 为威胁模型,在 TSO 内存模型下,InvisiSpec 平均性能损失为
21\%,而使用 fence 性能下降 74\%.

\subsubsection{DAWG}

\Todo: DAWG introduction

\Fixme: 重新翻译

在一个设计良好的系统中,攻击者无法在架构上观察到这个秘密,因为秘密应该
局限于一个保护域,阻止其他程序在架构上观察它。但是,当攻击者可以通过软
件方式观察执行的副作用时,可能存在漏洞。

进行这种观察的机制称为软件侧信道。必须根据受害者保护域中的活动来调制这
些信道,即它们的状态改变,并且攻击者必须能够检测那些状态变化。目前,最
广泛探索的渠道基于共享缓存的状态。例如,如果攻击者观察到地址上的命中,
则该地址必须已经缓存,这意味着某个方(可能是受害者)最近访问过该地址,
并且尚未被替换。确定访问是否是命中可以通过测量程序进行特定引用所花费的
时间来完成。

隐蔽通信信道在不允许通过现有保护机制进行通信的进程之间传输信息。例如,
当侧信道用于向攻击者传达“秘密”时,攻击将包括受害者保护域内用于访问秘密
的代码和用于将秘密传递给攻击者的发送器。它们一起形成数据抽头,将根据秘
密调制信道。由攻击者控制并在受害者保护域之外的接收器将监听信道上的信号
并对其进行解码以确定该秘密。这在图1中以图示的方式示出。

对RSA的经典攻击依赖于这种情况[9]。具体地,现有RSA代码遵循作为秘密的函
数的条件执行序列,并且通过根据该执行序列修改指令高速缓存状态而无意地发
送私有信息。这导致了一个隐蔽的通信,让观察对手确定秘密的位。在这种情况
下,访问秘密的代码和传送秘密的发送器预先存在于RSA代码中。因此,共享
icache的攻击者仅需要提供可以解调通过基于缓存标签状态的信道传送的秘密的
接收器。最近的工作表明,广泛的可行攻击通过共享缓存渗透信息。

最近,多个安全研究人员(例如,[22],[31],[35])已经找到了攻击者在受害
者中创建新数据管道的方法。这里,攻击者能够在受害者的域中创建数据抽头和
/或影响数据抽头以访问和传输所选择的秘密。 Spectre和Meltdown利用了这样
一个事实,即推测性地执行的代码可以完全访问任何秘密。

虽然广泛定义了投机执行,但我们关注的是本文中的控制流量推测。现代处理器
不按顺序执行指令,只要保留依赖性,就允许下游指令在上游指令之前执行。现
代无序处理器上的大多数指令也是推测性的,即,它们创建检查点并沿着预测路
径执行,同时一个或多个先前条件分支正在等待解决。预测被解析为正确丢弃检
查点状态,而不正确一个强制处理器回滚到检查点并沿正确的路径继续。一段时
间内执行了错误预测的指令,但不修改架构状态。然而,诸如高速缓存标签状态
的微体系结构状态由于(不正确的)推测性执行而被修改,从而导致信道被调制,
这可能允许秘密泄漏。

通过利用错误推测的执行,攻击者可以执行通常无法访问的代码路径,从而绕过
软件不变量。一个例子是攻击者推测性地执行非法访问秘密的数据抽头代码,并
在异常发生之前通过微架构副作用引起传输[35]。另一个例子是攻击者强制分支
预测器状态以鼓励沿着攻击者选择的代码路径的错误推测,这实现了受害者域中
的数据抽头。因此,有三种创建数据点击的方法:
1)数据抽头预先存在于受害者的代码中,我们在RSA攻击[9]中描述过。
2)攻击者明确编程数据点击。 Meltdown [35]就是一个例子。
3)攻击者合成受害者现有代码中的数据抽头 - 例如幽灵变种[22],[30],[31]。

例如,该框架可以应用于除缓存状态之外的侧通道,描述通过分支预测器逻辑或
TLB状态的泄漏。鉴于对这种新攻击类的变体的研究兴趣越来越浓,我们也想象
出可以构建数据抽头的新方法。因此,我们希望设计一种针对广泛的当前和未来
攻击的防御。

已经提出了可以仅在软件中实现的防御机制(例如,[11],[43])。不幸的是,
这些机制看起来非常具有攻击性:例如,编译器分析[43]确定了一些易受幽灵变
种1影响的代码实例;微码更新或编译器和链接器修复减少了对Spectre Variant
2的暴露[11]。已经引入了关闭脆弱区域中的推测的指令(例如,[2]),供将来
的编译器使用。在本文中,我们针对硬件进行了最小程度的修改,以抵御广泛的
侧通道攻击,包括那些基于推测的攻击,其目标是通过改变缓存状态来消除与渗
透相关的整个攻击面。

为了防止泄漏,我们需要保护域之间的强隔离,这可以防止任何发送器/接收器
对共享相同的通道。缓存分区是一种实现隔离的吸引人的机制。不幸的是,设置
(例如,页面着色[29],[50])和方式(例如,英特尔的高速缓存分配技术
(CAT)[21],[23])当今处理器中可用的分区机制要么性能低要么要么不高提
供隔离。

我们提出了DAWG,动态分配方式保护,一种用于包括高速缓存的集合关联结构的
安全方式分区的通用机制。 DAWG赋予一组关联结构和保护域概念,以提供强大
的隔离。与CAT等现有机制不同,DAWG不允许跨保护域点击。这会影响命中路径
和缓存一致性[42],DAWG通过对现代操作系统的最小修改来处理这些问题,同时
将操作系统的攻击面减少到一小部分带注释的部分,其中数据跨越保护域,或者
域是调整/重新分配。只有在这些少数例程中,DAWG保护才会放松,并且根据需
要应用其他防御机制,例如投机围栏。我们使用体系结构仿真和实际硬件的组合
来评估DAWG的性能影响,并与传统的服务质量分区缓存进行比较。我们得出结论,
DAWG提供了强大的隔离和合理的性能开销。

\Todo: DAWG 的设计

在 zsim 模拟器中使用 SPEC CPU2006, PARSEC, GAPBS 进行模拟,相对于
Intel CAT,在不同的评测程序和划分方式下,大多数程序性能下降为 4\%\~7\%.

DAWG 的主要缺点是需要操作系统的支持。此外,DAWG 不能防御 NetSpectre 等可
在同一安全域内进行的攻击。

\subsubsection{Context-Sensitive Fencing}

\Todo: CSF introduction

\Fixme: 重新翻译

这项工作提出了上下文敏感的防护,一种针对幽灵的新型微码级防御。防御策略
的关键组成部分包括:(a)微码定制机制,允许处理器手动将栅栏插入动态指
令流,以减轻推测性执行的不良副作用,(b)解码器级信息流跟踪(DLIFT)
)框架,用于识别可能不安全的执行模式以触发微代码定制,以及(c)缓解保
护分支预测器和返回地址堆栈的缓解措施。

为了在对性能影响最小的情况下执行安全的微码定制,这项工作利用了上下文敏
感解码(CSD)[68],这是最近提出的对英特尔(和其他人)微操作转换机制的
扩展,可实现按需和上下文敏感自定义动态微操作指令流。此外,这项工作还利
用了CSD提供的重新配置框架,允许操作系统和其他可信实体动态控制通过外科
手术插入微操作流的投机栅栏的频率,类型和行为,以确保投机安全执行。

这项工作分析了一套显着扩展的围栏,考虑了不同的可能的执法阶段和执法策略。
特别是,我们引入了一个新的栅栏,可以防止推测性更新缓存状态,同时在指令
的动态调度中具有最小的干扰。

上下文敏感的防护能够通过基于解码器级信息流跟踪的新型检测机制自动识别网
格插入点。由于处理器前端通常以比管线的其余部分高得多的速率搅拌指令,因
此解码器级的信息流跟踪易于频繁过度和不确定的情况。虽然由于栅栏插入的频
率增加而导致过度拉伸可能会损害性能,但是对于短暂的窗口来说,不确定会破
坏系统的安全性。通过早期低开销的错误检测和恢复机制解决这些挑战,本文进
一步确定了解码器级信息流跟踪作为一种有效的攻击检测机制的可行性。

这项工作进一步提出了新的微操作流程,保护分支预测器和返回地址堆栈,防止
跨不同保护域的错误训练和/或逆向工程。虽然与英特尔提出的间接分支预测器
屏障(IBPB)指令的精神相似,但这些微操作流程更广泛地应用于更广泛的分支
预测器和返回地址堆栈,并提供更细粒度的控制。

\Todo: 更详细地介绍 CSF

Context-Sensitive Fencing(CSF)\supercite{context-sensitive-fencing} 是
一种微码级防御多种类型 Spectre 攻击的方法。它基于 Context-Sensitive
Decoding (CSD)\supercite{context-sensitive-decoding},一种微码翻译机制
的扩展,用于动态按需自定义微操作指令流。CSF 利用 CSD,在微指令流中注入
fence 等微码,阻止不安全指令的推测式执行。为了降低 fence 的性能开销,
CSF 还提出了3种新的用于防御 Spectre 的 fence.

CSF 由以下几个关键部件组成:
\begin{itemize}
\item 微码自定义机制 CSD:使处理器精确地在指令流中插入 fence,减轻推测
  式执行中不期望的副作用
\item 译码级信息流追踪(DLIFT)框架:用于检测潜在不安全的执行模式,触
  发微码自定义机制
\item 错误训练防御:用于保护分支预测器、返回地址栈等部件
\end{itemize}

CSF 防御 Spectre 的开销在 8\% 以下。

\subsubsection{Conditional Speculation}

条件推测式执行(Conditional Speculation)
\supercite{conditional-speculation} 是一种检测推测式执行中的潜在的泄露
数据的访存指令,并阻止其执行的方法。为了检测可能在推测式执行中泄露数据
的指令,此工作提出安全依赖(security dependence)的概念,类似于数据依
赖和控制依赖,这种新的依赖性用于描述泄漏微架构信息具有潜在安全风险的推
测性执行的指令。对于信道 $c$,指令 $j$ 安全依赖于指令 $i$,如果:

\begin{itemize}
\item 在程序序列中,指令 $j$ 在 $i$ 之前
\item $j$ 在 $i$ 之前推测式地执行,并且 $j$ 会通过信道 $c$ 泄露数据
\end{itemize}

因为信息可以从多种信道上泄露,所以安全依赖的定义指定了某种信道。针对缓
存信道,如果指令 $j$ 不修改缓存的内容,则它对于缓存信道不具有安全依赖,
尽管它可能会泄露某些信息。

根据以上定义,表\ref{tab:secdep}总结了 Spectre 攻击中的主要的安全依赖。
Spectre 攻击的安全依赖性来自两种情况,访存-访存推测和分支-访存推测。

\begin{tabular}{|c|c|c|}
\hline 
Spectre 变体 & 指令 $i$ & 指令 $j$\tabularnewline
\hline 
\hline 
Spectre v1 & 条件分支 & 访存\tabularnewline
\hline 
Spectre v2 & 间接转移 & 访存\tabularnewline
\hline 
Spectre v4 & 访存 & 访存\tabularnewline
\hline 
SpectrePrime & 条件分支 & 访存\tabularnewline
\hline 
\end{tabular}

在条件推测式执行的流水线中,在发射队列中引入了安全冒险检测,以识别具有
安全依赖的可疑的不安全指令。只要在执行阶段确认了真正的冒险,那些不安全
的推测式执行将会使用现有的重执行和推测式执行恢复机制终止并丢弃。

% the following is from gtran

\Todo: V-B Security Hazard Detection in Issue Queue

\Fixme: 重新翻译

我们设计了基于比特矩阵的安全检测逻辑,如图2所示。比特矩阵是一些商品处理器用来跟踪数据依赖和年龄信息的流行方式[26],[27],[28]。通常,数据依赖矩阵和年龄矩阵一起可以确定要发布的指令。对于安全检测模块,安全依赖矩阵还必须确定要发布的指令是否具有任何安全依赖性。

矩阵组织:安全依赖矩阵需要有效地支持行和列访问。假设问题队列具有N个项,则安全依赖性矩阵将包含NxN位的寄存器阵列。它由IQPos(问题队列位置)编制索引。此矩阵的读端口数等于调度宽度,写端口数等于发布宽度。给定任何指令X,IQPos X表示其在问题队列中的位置。如果Matrix [IQPos X,IQPos Y]的值为1,则X对Y具有安全依赖性。否则,这意味着它们之间没有安全依赖性。矩阵初始化:当新指令X被分派到问题队列中时,一个条目被分配索引IQPos X.对于此时在问题队列中有效的每个指令Y,计算Matrix [IQPos X,IQPos Y]根据以下公式。

Matrix[X, Y ] = (IssueQ[X].opcode == MEMORY)
and (IssueQ[Y ].opcode == MEMORY or BRANCH)
and IssueQ[Y ].valid
and \!IssueQ[Y].issued

此公式基于以下逻辑来确定指令之间的安全依赖性。首先,如果在X被分派到问题队列之前Y是有效的,则意味着Y在X之前。其次,对于Specter变体,我们仅检查存储器指令是否依赖于先前的分支或存储器指令。第三,如果在发出存储器指令时,先前的分支或存储器指令仍然在问题队列中等待,则该存储器指令将被认为具有安全依赖性。

危险检测:图2说明了问题队列的三个阶段选项。在第一阶段,数据依赖矩阵生成依赖向量。在第二阶段,然后将该向量发送到年龄矩阵以选择要发布的最早的就绪指令。在第3阶段,对于选择发布的那些指令,查询安全依赖矩阵以获得它们的安全依赖性,然后更新问题队列的相应条目的状态。特别是,安全依赖矩阵的每一行中的位由OR运算处理,结果表明是否存在潜在的安全隐患。当选择发出一条指令并检测到安全危险时,它将被标记为可疑推测标记。

依赖性清除:在发出一条指令X后,更新向量寄存器中的相应位将被设置为0.由IQPos X索引的安全依赖矩阵列将在下一个周期复位。这种操作意味着清除了相应指令和X之间的安全依赖性。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


为了性能,安全性和透明性的平衡,条件推测式执行提出了两种过滤机制,以找
出错误识别的安全安全冒险。基于缓存命中的冒险过滤器针对命中缓存的推测式
执行指令。因为它们的推测式执行不会改变缓存的内容,所以它们是安全的。
另一个提出的过滤器,基于可信页面缓冲区(Trusted Page Buffer, TPBuf)的
冒险过滤器,从另一个角度识别安全的推测推测式执行的指令。对于使用基于共
享内存(例如 Flush+Reload)的缓存侧通道攻击窃取内存信息的 Spectre 变体,
他们对恶意组件的推测式执行具有名为 S-Pattern 的共同特征。 TPBuf 从所有
推测式执行中捕获 S-Pattern,对于任何推测式执行的访存指令,如果它与
S-Pattern 不匹配,则被认为是安全的。

% gtran

\Todo: V-C cache-hit based hazard filter 和 V-D Trusted Pages Buffer
based Hazard Filter

\Fixme: 重新翻译

一种简单的危险消除方法是简单地阻止在发布队列中标记有可疑推测标记的所有指令。这样的政策显然会导致性能下降。同时,只有导致高速缓存未命中的内存请求将改变高速缓存内容,并且大多数应用程序表现出良好的时间和空间局部性。受这两个观察的启发,基于缓存命中的危险过滤器被提议用于减少保守地不执行具有可疑推测标记的指令的性能影响。

% hit-based

对于标记有可疑推测标志的存储器指令,它将被推测性地发布到存储器访问管线。如果推测性存储器访问命中L1高速缓存,则其执行将继续作为正常存储器指令。但是,如果遇到L1高速缓存中的未命中,则丢弃的请求将被丢弃。信号从L1高速缓存发送回问题队列,重新发出逻辑应该应用于存储器指令,直到其安全依赖性得到解决。这些被阻止的指令在发布队列中等待安全依赖性在重新发布之前清除。此设计仅需要L1高速缓存控制逻辑中的最小更改:将不会处理具有可疑推测标记的未命中请求。

% TPBuf
基于缓存命中的危险过滤器仅考虑在L1 DCache中命中的推测性内存指令是安全的,并允许它们被推测性地执行。对于具有高L1 DCache未命中率的应用程序,它将无法恢复投机执行的大部分好处。对于这些应用,我们提出了一种新的危险过滤器可信页面缓冲器(TPBuf)来检测L1 DCache中丢失的指令的安全推测。 TPBuf基于以下观察:并非所有推测性缓存未命中都可用于构建推测性侧通道。基于第3节中定义的威胁模型,我们关注使用共享内存(例如,Flush + Reload)范例和非法访问内存页面信息的Spectre变体。如图3所示,恶意小工具的推测性执行在我们的目标Spectre攻击中被用作通用内存访问模式。特别是,观察到恶意推测执行流程总是包含两个特殊的存储器指令(A和B)。这两条指令具有以下用法和行为。

1)A用于推测性地访问敏感数据。 B推测访问攻击者共享的内存区域,用于构建受害者和攻击者之间的缓存侧通道。由于用于侧信道的秘密数据和存储区域通常位于不同的存储页面,因此这两条指令访问不同的页面。

2)为了构建缓存侧通道,攻击者需要首先刷新特定的共享内存数据。然后,B的诱导推测执行具有高速缓存未命中,因此将高速缓存行重新加载到L1 DCache中。攻击者可以通过缓存侧信道感知状态信息的这种变化。因此,B的高速缓存未命中对于通过高速缓存侧信道泄漏敏感信息是必要的。

3)B是数据依赖于A.A的结果用于计算共享存储区域的索引。这种精心设计的依赖性也是攻击者推断秘密价值的另一个重要点。

在上述观察的推动下,我们将上述共同特征行为称为S模式。具体地,如果观察到推测执行的指令序列具有以下特征,则我们认为该推测指令序列具有S模式行为。

1)至少有两个指令(A和B)分别访问不同的存储页面。

2)指令B导致L1 DCache未命中。

3)指令B具有数据依赖于指令A.

4)A和B之间可能有多个指令(计算,存储器或其他类型的指令)。

  尽管Spectre攻击的恶意小工具被称为S-Pattern行为,但应该注意的是,具有S-Pattern的指令流不一定是幽灵攻击。出于安全原因,我们试图在微体系结构层面上防止形成具有S-Pattern的推测性指令流。在确保安全性的同时,这种机制自然也会导致性能损失。在第6节中,我们详细评估了该策略的性能,并分析了正常程序(如SPEC CPU 2006)中S-Pattern的比例。

  TPBuf旨在通过所有推测执行的S-Pattern捕获内存访问行为。 它记录所有动态推测存储器访问请求并跟踪它们的执行状态(例如,是否重新填充所请求的高速缓存行)。 当一个错过L1 DCache的新内存请求时,TPBuf会将其页面地址与其历史记录进行比较。 并且它根据表II中描述的逻辑决定这种新的推测指令是否安全。

  TPBuf的微体系结构如图4所示。一个主要的设计原则是尽可能利用现有逻辑来降低实现的复杂性,例如避免TPBuf成为核心管道内的新时序关键路径。 TPBuf靠近加载存储队列(LSQ),其条目与LSQ的条目具有1:1映射。 TPBuf条目的分配,提交和压缩与LSQ的Head和Tail指针的移动一起操作。此外,TPBuf涵盖了推测执行窗口中的所有动态推测存储器指令。为了防止攻击者直接推测性地访问未授权数据然后将数据传播到他自己的存储空间,必须首先检查访问地址并使用TLB获取物理页码(PPN)。 TPBuf记录并使用PPN作为每个条目的标记。此外,每个TPBuf条目都存储一个掩码和许多状态位。 TPBuf检测S模式并将结果传递给Cache-hit过滤器,该过滤器决定是否应该阻止可疑的推测性未命中请求。这样,原始内存一致性模型和缓存一致性不受影响。 TPBuf的查找如图4所示。

分配:当在LSQ中分配存储器访问指令时,它们也在TPBuf中分配并且A位被置位。并且根据TPBuf中的A位生成掩码。
它指示TPBuf中的哪些内存指令比程序顺序中的新条目旧。

更新:使用存储器指令附带的可疑推测标志更新S位。当PPN记录在TPBuf中时,V位置位。当存储器指令获取的数据可供其他指令使用时,W置位。

检测:当传入请求进入TPbuf时,TPBuf将其PPN与现有条目的PPN进行比较,然后生成地址匹配向量(匹配)。这些矢量,包括Match,V,W和S,用作等式1逻辑的输入,以确定请求是否安全。特别地,“|”表示减少OR,它对向量中的所有位进行OR运算以生成1位输出。
%%%%%%%

在 gem5 模拟器中用 SPEC CPU2006 进行评测,平均性能开销为 6.8\%.

\subsubsection{SpectreGuard}

SpectreGuard\supercite{spectreguard} 是一种软硬件结合防御 Spectre 攻击
的方法。软件在页表中标记一个页是否存在秘密数据,如果一条指令在推测式执
行中读取了带标记的页中的数据,处理器则禁止这条指令将读取的值转发至其他
指令,直到这条指令之前的所有预测都已验证,确认推测式执行正确。

%%% gtran %%%

\Todo: SpectreGuard introduction

\Fixme: 重新翻译

自Spectre披露以来,已经提出了几种基于软件和硬件的缓解策略。基于软件的缓解策略通过手动插入序列化指令[12]或在条件跳转和后续存储器加载指令之间引入其他数据依赖性[7,21]来防止推测。但是,手动识别程序的易受攻击的分支是困难的,而通过编译器自动化保护所有分支会导致过多的性能开销[21]。基于硬件的方法通常通过引入额外的硬件结构来缓冲推测结果来集中隐藏攻击者可观察的微架构状态变化[13,27]。虽然它们不需要手动更改代码,但它们会导致侵入式硬件更改和高性能开销[13,27]。

在本文中,我们提出了SpectreGuard,一种针对幽灵攻击的新型跨层防御。我们的方法是以数据为中心的,因为我们专注于程序的数据而不是代码。我们观察到,对于软件开发人员来说,识别程序的秘密数据(例如,密钥)可能比识别易受攻击的代码块(即,幽灵小工具)更容易,这些代码块可以出现在程序的任何分支中,即使它们不相关处理秘密数据。因此,我们的方法首先要识别敏感的内存块,这些内存块保存秘密数据,并将它们标记为非推测性内存区域。识别的存储区域通过简单的OS /库API被通知给OS,然后由硬件利用以通过低成本的微架构扩展选择性地和有效地防止推测性攻击。

我们的微架构扩展很小,并且基于一个基本观察,即成功的Specter变体1攻击需要以下三个不同的步骤推测性地发生:(步骤1)秘密数据从存储器层次加载; (步骤2)然后将其转发给相关指令; (步骤3)执行从属指令,通过微架构隐蔽信道(例如,高速缓存)泄漏秘密。重要的是要注意秘密是通过第二和第三步骤泄露的,在此期间留下了攻击者可观察的,秘密依赖的,微观建筑的足迹。换句话说,即使秘密数据被加载到CPU管道上,除非它被转发到秘密相关指令,否则秘密不会泄露给攻击者。

  基于这种观察,我们的方法允许第一步发生但延迟第二步直到所有先前的分支被解决之后。请注意,仅当第一步中的虚拟地址在非推测内存区域内时才需要此延迟。所有其他“正常”地址可以立即转发到任何等待的相关指令。因此,不经常访问的秘密将在整体性能上具有可忽略的开销。
  
%%%%%%%%%%%%%%

在 gem5 模拟器中用 SPEC CPU2006 评测,如果标记内存的所有页,则
SpectreGuard 的平均性能开销为 20\%, 而如果标记堆区域,则性能开销减少至
8\%. 在使用 OpenSSL 的合成基准测试中,如果只标记私钥为秘密数据,则性能
可以接近原处理器的性能。

% \begin{comment}
% 
%   MI6: Secure Enclave in a Speculative Out-of-Order processor
% 
%   abs: 一个考虑了Spectre等攻击设计的enclave方案
% 
% 
%   Data Oblivious ISA(OISA)是一种 ISA 扩展,用于阻止信息通过侧信道泄露。
%   设计原则:
%   \begin{itemize}
%   \item ISA的安全性和微架构无关
%   \item ISA不会阻止现代微处理器的优化技术
%   \end{itemize}
% 
%   OISA有以下组件:
%   \begin{itemize}
%   \item 动态跟踪敏感数据:使用DIFT跟踪程序运行时私密数据在处理器中的传
%     播。所有数据都有 confidential/public 标记,标签在读取操作数时必须
%     解析
%   \item 指令定义操作数可以接受 public 还是 public/confidential 数据
%   \end{itemize}
% \end{comment}
% 
% % vim:ts=4:sw=4