From c0f7e397417d556803e7064a5fe1808ac821a10b Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Thu, 9 May 2019 23:30:53 +0800 Subject: upd --- chap/chap2.tex | 147 +++++++++++++++++++++++++++++++++++++++++++++++++-------- thesis.tex | 2 + 2 files changed, 129 insertions(+), 20 deletions(-) diff --git a/chap/chap2.tex b/chap/chap2.tex index 0ab30ea..5476f01 100644 --- a/chap/chap2.tex +++ b/chap/chap2.tex @@ -201,6 +201,38 @@ Foreshadow 对 Intel SGX 所追求的安全模型产生了深远的影响,在 的行为,并且不利用任何软件漏洞,甚至不需要知道受害者 enclave 的源代码。 % foreshadow attack +\begin{figure}[htbp] + \centering + \includegraphics[width=0.8\textwidth]{addr-trans.eps} + \caption{CPU 的地址翻译过程和 L1 终端错误的原理:图片的下半部分为文 + 档描述的地址翻译过程,上半部分是微架构的行为。} + \label{fig:addr-tran} +\end{figure} + +在现代 Intel x86 处理器中,用一个虚拟内存地址访问内存时,处理器先在TLB +中查询对应的物理地址,如果 TLB 中没有这个地址对应的项,则会在页表中找到 +虚拟地址对应的页表项,以获得对应的物理地址和访问权限信息。 +如果在虚拟机环境中,则需要如图 \ref{fig:addr-tran} 所示,增加一个扩展 +页表(Extended Page Table,EPT)的访问过程,将客户机的物理地址翻译为底 +层物理机的物理地址。最后,启用了 Intel SGX 的处理器还会进一步检查地址 +翻译的结果,确保这个地址翻译遵守硬件强制的 enclave 访问控制限制。如果 +这三个独立的阶段报告一个访问违例,则处理器抛出一个页错误,控制流转向异 +常处理代码,而对于 SGX,大多数的 enclave 内存违例会被处理器忽视,将内 +存装载指令得到的值设为 abort page 的值 -1. + +在体系结构层次上,以上的地址翻译过程在文档中有精确的描述。现代处理器为 +了加快地址翻译和内存访问,使用了并行访问和额外的缓存结构。在 Meltdown类 +型的攻击中,可以发现 Intel 的 CPU 将内存访问违例检查放到了指令提交的时 +间,使得在页错误发生之前,未授权的内存内容仍然可以到达流水线中其后执行 +的乱序执行的指令。Meltdown 攻击利用了这个时间窗口,在瞬时指令中,将只有 +特权态能访问的内存编码至持久的微架构状态。 + +现代 Intel 处理器使用虚拟地址索引,物理地址标签的一级缓存。如 +图\ref{fig:addr-tran} 所示,这种缓存索引方式使得地址翻译可以和一级缓存 +的查询并行。在得到虚拟地址对应的一级缓存组后,处理器还需要知道是否有某 +一路缓存含有需要的数据,因此处理器要将地址翻译得到的物理地址和缓存每一 +路的物理地址标签对比,在某一个有效的缓存路存在正确的物理地址时,此时一 +级缓存命中,数据返回至处理器的执行单元。 Foreshadow\supercite{foreshadow} 是一种可以读取 Intel SGX enclave 中秘 密数据的 Meltdown 型攻击。如果对 SGX 使用 Meltdown 攻击,攻击者读取未授 @@ -210,22 +242,25 @@ page 只在页权限检查通过后发生,攻击者可以将该页 present 位 因此仍然可以从一级缓存读取该虚拟地址中的数据,从而瞬时指令可以泄露 SGX enclave 中的数据。 -通过将一个页设为不存在,绕过地址翻译,从一级缓存读取数据的攻击方式, -Intel 将其称为L1终端错误(L1 Terminal Fault)\supercite{l1tf}。 -Foreshadow-NG\supercite{foreshadowNG} 利用这种攻击方法,可以绕过操作系 -统和虚拟机的隔离。Foreshadow-NG 包含了 Foreshadow-OS 和 Foreshadow-VMM. +通过将一个页设为不存在,绕过地址翻译,从一级缓存读取数据的攻击方 +式,Intel 将其称为L1终端错误(L1 Terminal +Fault)\supercite{l1tf}。Foreshadow-NG\supercite{foreshadowNG} 利用相同 +的原理,新增了Foreshadow-OS 和 Foreshadow-VMM 两种 Foreshadow 类型的攻 +击,可以绕过操作系统和虚拟机的隔离。 + % forshadow-OS 操作系统内核将虚拟内存页从内存交换至外部持久存储时,都需要清除页表项的 -存在位。但是,根据处理器的体系结构规范,内核可以根据需要,自由地使用标 -记为不存在的页表项中的剩余位。例如,操作系统可以保持这些位不变,将它们 -归零,或者使用它们来存储用于把页从磁盘复制回内存的元数据。因此,虽然非 -特权用户空间应用程序不能直接控制页表项,但是当页表项取消映射相应的虚拟 -页时,操作系统在页表项中留下的元数据仍然可以指向包含敏感数据的有效物理 -地址。在内核清除相应页表项中的存在位后,从用户空间解引用未映射的页将导 -致终端错误。 - -然而,危险的是,尽管错误存在,在页表项中的元数据表示在缓存中的物理地址 +存在位。但是,根据处理器的体系结构规范\supercite{intel-spec},内核可以 +根据需要,自由地使用标记为不存在的页表项中的剩余位。例如,操作系统可以 +保持这些位不变,将它们归零,或者使用它们来存储用于把页从磁盘复制回内存 +的元数据。因此,虽然非特权用户空间应用程序不能直接控制页表项,但是当页 +表项取消映射相应的虚拟页时,操作系统在页表项中留下的元数据仍然可以指向 +包含敏感数据的有效物理地址。在内核清除相应页表项中的存在位后,从用户空 +间解引用未映射的页将导致终端错误。 + +Foreshadow-OS 利用了这种错误造成的瞬时执行的指令。虽然访问页表中标记为 +不存在的页会触发终端错误存在,在页表项中的元数据表示在缓存中的物理地址 的情况下,处理器仍然将一级数据高速缓存中未授权数据传递到瞬时乱序执行中。 然后可以和其他瞬时执行攻击一样,将秘密数据从微架构瞬时执行域带入体系结 构状态中,例如,使用基于缓存的隐蔽通道。更糟糕的是,如果操作系统支持大 @@ -243,7 +278,7 @@ enclave,或 SMM 内存的数据。在操作系统通过 munmap 系统调用释 虽然上述 Foreshadow-OS 变体允许无特权的攻击者使用未经授权的物理内存位置 上的数据进行瞬时计算,但他们无法直接控制访问哪些物理地址。因此, Foreshadow 攻击使用在可以直接控制客户机器物理地址和一级缓存标签比较的 -不可信虚拟机时时,会变得更有破坏性。 +不可信虚拟机时时,会变得更有破坏性。这种攻击称为 Foreshadow-VMM. 根据 Intel 处理器的架构规范\supercite{intel-spec},客户机物理地址经过基 于 EPT 的转换过程以找到底层主机物理内存地址。英特尔的分 @@ -270,12 +305,84 @@ Foreshadow 攻击使用在可以直接控制客户机器物理地址和一级缓 \subsubsection{LazyFP} -由于浮点寄存器和内存交换数据进行操作有一定开销,大部分应用程序不做浮点 -运算,因此部分操作系统在进行上下文切换时不保存浮点寄存器。操作系统在恢 -复用户态程序的运行之前,对处理器设置禁用浮点寄存器,程序使用了浮点指令 -后,触发异常,操作系统才对浮点寄存器进行保存和恢复。 -LazyFP\supercite{lazyfp} 攻击利用这个异常,利用这个方法,攻击者可以读 -出一个处理器核此前运行的使用了浮点寄存器的程序中的浮点寄存器的值。 +% introduction +LazyFP\supercite{lazyfp} 是一个 Meltdown 类型的攻击,它可以跨越进程和虚 +拟机的边界,泄露浮点处理单元(FPU)寄存器的状态。这种攻击利用 Intel 处 +理器处理设备不可用异常(\Fault{NM})的行为。这个异常用于在操作系统中实 +现延迟 FPU 上下文切换的优化。在 LazyFP 攻击中,没有特权的本地执行的代码, +可以利用 \Fault{NM} 异常的瞬时指令,恢复受害者进程的 FPU 寄存器状态。 +由于 AES-NI 的密钥等数据可能存在 FPU 寄存器中,这种攻击导致的数据泄露 +对信息安全是个很大的威胁。 + +% background + +x87 浮点单元(FPU)是 x86 的处理器的一个扩展,其最初目的是加速浮点数的 +运算。它有自己的一组指令和寄存器。自 1989 年推出 Intel 486DX 以来,它是 +每个 x86 微处理器不可或缺的一部分,而在此之前,它是一个可选的外部协处理 +器。在上下文切换中,向内存保存 FPU 状态和恢复 FPU 的状态曾经是一个成本 +很高的操作,因为内存速度慢并且大小有限。此外,那时 FPU 只在少数程序中被 +使用。在 FPU 不被所有进程使用的情况下,在每个上下文切换时,切换 FPU 状 +态会产生不必要的开销。为了能够减少这种开销,x86 处理器引入了一个控制寄 +存器位 cr0.ts,允许操作系统打开和关闭FPU,当FPU关闭时,它会保持其状态, +但用户和内核代码都无法访问。 + +利用 cr0.ts 实现的优化称为延迟 FPU 上下文切换(lazy FPU context +switching)。核心思想是 FPU 寄存器状态仅在必要时进行上下文切换,并保留 +在不使用 FPU 的进程中。这样,操作系统可以避免不必要的保存和恢复 FPU 上 +下文的成本。 + +操作系统跟踪当前 FPU 寄存器状态所属的进程,此进程称为FPU所有者。FPU 可 +以在启用和禁用状态,在 FPU 启用状态下,当前进程是 FPU 所有者,可以自由 +地执行 FPU 指令。当操作系统切换到另一个进程时,FPU 被禁用。在进程尝试执 +行 FPU 指令之前,它将保持禁用状态。由于 FPU 被禁用,使用浮点指令时,处 +理器会生成 \Fault{NM} 异常。操作系统处理 \Fault{NM} 异常的方式取决于当 +前进程是否为FPU 所有者,如果是,则 FPU 寄存器状态属于该进程,操作系统启 +用FPU,该进程再次可以自由执行FPU指令。否则,则操作系统在启用 FPU 的同时, +将当前FPU 寄存器状态存储到 FPU 所有者进程的状态保存区域,并恢复当前进程 +的FPU 寄存器状态,并将该进程设为 FPU 的所有者。 + +这个算法在不同操作系统中的实现可能不同,它们的共同点是,使用 FPU 的进程 +切换到不使用 FPU 的进程时,操作系统不需要上下文切换 FPU 寄存器的状态。 + +虽然延迟 FPU 上下文切换仍然在现代的操作系统中广泛使用,但其基本假设通常 +不再适用。从 Intel MMX 指令集扩展,到后续的 SSE,AVX 和 AVX-512,FPU 寄 +存器状态已经扩展到更大的 SIMD 寄存器。SSE 指令集是 64 位 x86 处理器的必 +须组成部分,并且在几乎所有程序和库中用于实现不同的任务,例如内存复制。 + +虽然更大的 FPU 寄存器状态使得避免 FPU 上下文切换更具吸引力,但在当前的 +软件中,每个进程最终都会使用 FPU 寄存器并触发 \Fault{NM} 异常。因 +此,Linux 内核已经默认将 FPU 寄存器作为普通上下文切换的一部分进行切换, +在正常操作中不会生成 \Fault{NM} 异常。 + +在使用 Intel 的硬件辅助虚拟化技术时,处理器在从客户机切换到管理程序时, +不会切换FPU寄存器状态。虚拟机管理程序负责上下文切换 FPU 寄存器的状态, +并且机制与非虚拟化操作系统的机制相同。因此,延迟 FPU 上下文切换也适用于 +虚拟机管理程序。 + +在使用延迟 FPU 上下文切换的操作系统中,利用 LazyFP 攻击可以使没有特权的 +攻击者获取同一处理器硬件线程中 FPU 寄存器的数据。以下简单的例子可以泄 +露1比特的数据。 + +\begin{minted}{nasm} +movq rax, xmm0 +and rax, 1 +shl rax, 6 +mov rax, dword [mem + rax] +\end{minted} + +在以上代码片段中,由于进程中 FPU 寄存器被禁用,movq 指令产 +生 \Fault{NM} 异常。操作系统会用对应用程序透明的方式处理该异常,恢复进 +程的状态并继续执行。 + +而在处理器结束 movq 指令的执行并产生 \Fault{NM} 之前,已经执行了后续指 +令,虽然最终这些指令引起的体系结构状态更改会被丢弃,但在缓存中的状态仍 +然保留。这段代码使用了受害者进程的 FPU 寄存器和攻击者进程的通用寄存器 +进行瞬时指令的执行,通过探测 mem 指向的数组的缓存状态,可以恢复 xmm0 +最低位的值。 + +利用 Intel TSX 等技术处理异常,攻击者可以高效地泄露所有 FPU 寄存器的数 +据。在 Intel Core i7-5600U 处理器中,可以以 3.3MB/s 的速度泄露一个 AVX +寄存器的数据。 \subsection{Spectre型攻击} diff --git a/thesis.tex b/thesis.tex index 01d36c2..b285e73 100644 --- a/thesis.tex +++ b/thesis.tex @@ -48,6 +48,8 @@ % 载入参考文献数据库(注意不要省略“.bib”)。 \addbibresource{thesis.bib} +\newcommand{\Fault}[1]{\texttt{\#}#1} + \begin{document} % 以下为正文之前的部分,默认不进行章节编号。 \frontmatter -- cgit v1.2.3