分支预测和推测性提取缓解
Branch prediction & speculative fetch mitigation
为什么虚拟地址 (VA) 分离不足以缓解各种幽灵和崩溃漏洞?我的意思是通用的,不包括攻击 intel p-cache == v-cache hack 的那个;这显然是个坏主意,我找不到任何同情。
作为基准线:
我的内核地址space(AS)只与用户AS共享一个文本和数据页。这些页面仅包含足够的代码和数据来保存和存储寄存器;加载新的内存上下文,并跳转到适当的位置。因此,这里没有有趣的地址可以发现。
来自 exec 的进程 AS 没有任何共同的 VA。也就是说,每个 VA 分配都是从一个公共池中获取的,因此即使像 libc 这样的共享对象在每个进程中也处于不同的地址。大多数 unix 派生的人会觉得这很奇怪,但这肯定是可行的;我错了一次^H*10/为了测试。
Fork() 的进程图像如果位于单独的访问控制域中,则将被沙盒化,以防止交叉泄漏。沙盒可以涉及上下文切换缓存逐出、排除超线程的 cpuset,一直到 非干扰 内核。
我了解 [1] 是与熔毁相关问题的基本缓解措施; [2] 是 [1] 的扩展,因此它适用于幽灵。 [3] 会导致性能问题,但同样仅限于那些情况。
Meltdown 攻击依赖于(推测)直接访问目标虚拟地址(从攻击过程中)1.
但幽灵不是。 您启动 分支预测器 以便受到攻击的代码推测性地访问它自己的虚拟地址 space,它有权这样做。分支预测器别名意味着您通常/有时可以在您不能/没有映射的虚拟地址处为分支预测做准备。 (例如在内核中。)
通常的边信道(缓存读取攻击)是基于逐出您自己地址中数组的缓存 space。但其他侧通道也可以将 Spectre 数据从目标返回给攻击者,例如启动缓存,然后查找哪个条目被冲突未命中逐出的地址别名 进程中的一些内存受到攻击。 (更难,因为现代 x86 CPU 中的 L3 缓存使用复杂的索引功能,这与使用简单的位范围作为索引的更简单的缓存不同。但您可能可以使用 L2 或 L1d 未命中。
L2 未命中/L3 命中仍应明显长于 L2 命中。)
或者使用 SMT(例如超线程),一种 ALU 定时攻击,其中 Spectre 小工具会创建数据相关的 ALU 端口压力。在这种情况下,唯一相关的内存访问是受到攻击的数据(这是硬件允许的,只有分支的错误推测会导致回滚,而不是加载错误)。
攻击内核时,会将攻击进程的物理内存页映射到某处。 (大多数内核将所有物理内存映射到一个连续的虚拟地址范围,允许轻松访问任何物理地址。)缓存基于物理地址,而不是虚拟地址。
通过对同一页面的不同映射使高速缓存行变热的 Spectre 小工具仍然有效。
在系统调用的上下文中,内核通常将 user-space 内存映射到它在进程 中使用的相同虚拟地址,因此系统read
和 write
之类的调用可以在 user-space 和页面缓存之间复制。许多系统调用将 user-space 指针传递给文件名。所以在攻击内核时,Spectre gadget可以在攻击过程中直接使用user-space地址。
Spectre 小工具本身甚至可能位于 user-space 内存中,尽管使用单独的页表来解决 Meltdown,您可以通过将内核页表设置为具有 user-space 未经执行许可映射的 VA。
脚注 1:Meltdown 是页表中 U/S 位的绕过,允许用户 space 潜在地读取内核留下映射的任何内存。是的,[1] 是一个足够的解决方法。参见 http://blog.stuffedcow.net/2018/05/meltdown-microarchitecture/。
为什么虚拟地址 (VA) 分离不足以缓解各种幽灵和崩溃漏洞?我的意思是通用的,不包括攻击 intel p-cache == v-cache hack 的那个;这显然是个坏主意,我找不到任何同情。
作为基准线:
我的内核地址space(AS)只与用户AS共享一个文本和数据页。这些页面仅包含足够的代码和数据来保存和存储寄存器;加载新的内存上下文,并跳转到适当的位置。因此,这里没有有趣的地址可以发现。
来自 exec 的进程 AS 没有任何共同的 VA。也就是说,每个 VA 分配都是从一个公共池中获取的,因此即使像 libc 这样的共享对象在每个进程中也处于不同的地址。大多数 unix 派生的人会觉得这很奇怪,但这肯定是可行的;我错了一次^H*10/为了测试。
Fork() 的进程图像如果位于单独的访问控制域中,则将被沙盒化,以防止交叉泄漏。沙盒可以涉及上下文切换缓存逐出、排除超线程的 cpuset,一直到 非干扰 内核。
我了解 [1] 是与熔毁相关问题的基本缓解措施; [2] 是 [1] 的扩展,因此它适用于幽灵。 [3] 会导致性能问题,但同样仅限于那些情况。
Meltdown 攻击依赖于(推测)直接访问目标虚拟地址(从攻击过程中)1.
但幽灵不是。 您启动 分支预测器 以便受到攻击的代码推测性地访问它自己的虚拟地址 space,它有权这样做。分支预测器别名意味着您通常/有时可以在您不能/没有映射的虚拟地址处为分支预测做准备。 (例如在内核中。)
通常的边信道(缓存读取攻击)是基于逐出您自己地址中数组的缓存 space。但其他侧通道也可以将 Spectre 数据从目标返回给攻击者,例如启动缓存,然后查找哪个条目被冲突未命中逐出的地址别名 进程中的一些内存受到攻击。 (更难,因为现代 x86 CPU 中的 L3 缓存使用复杂的索引功能,这与使用简单的位范围作为索引的更简单的缓存不同。但您可能可以使用 L2 或 L1d 未命中。 L2 未命中/L3 命中仍应明显长于 L2 命中。)
或者使用 SMT(例如超线程),一种 ALU 定时攻击,其中 Spectre 小工具会创建数据相关的 ALU 端口压力。在这种情况下,唯一相关的内存访问是受到攻击的数据(这是硬件允许的,只有分支的错误推测会导致回滚,而不是加载错误)。
攻击内核时,会将攻击进程的物理内存页映射到某处。 (大多数内核将所有物理内存映射到一个连续的虚拟地址范围,允许轻松访问任何物理地址。)缓存基于物理地址,而不是虚拟地址。
通过对同一页面的不同映射使高速缓存行变热的 Spectre 小工具仍然有效。
在系统调用的上下文中,内核通常将 user-space 内存映射到它在进程 中使用的相同虚拟地址,因此系统read
和 write
之类的调用可以在 user-space 和页面缓存之间复制。许多系统调用将 user-space 指针传递给文件名。所以在攻击内核时,Spectre gadget可以在攻击过程中直接使用user-space地址。
Spectre 小工具本身甚至可能位于 user-space 内存中,尽管使用单独的页表来解决 Meltdown,您可以通过将内核页表设置为具有 user-space 未经执行许可映射的 VA。
脚注 1:Meltdown 是页表中 U/S 位的绕过,允许用户 space 潜在地读取内核留下映射的任何内存。是的,[1] 是一个足够的解决方法。参见 http://blog.stuffedcow.net/2018/05/meltdown-microarchitecture/。