跨线程返回地址预测¶
某些 AMD 和海光处理器存在跨线程返回地址预测漏洞。在 SMT 模式下运行时,当一个同级线程从 C0 状态转换出去时,另一个同级线程可能会使用从 C0 状态转换出去的同级线程的返回目标预测。
Spectre v2 缓解措施保护 Linux 内核,因为它在上下文切换到空闲线程时,会用安全的目标填充返回地址预测条目。然而,KVM 允许 VMM 在从 C0 状态转换出去时阻止退出客户机模式。这可能导致由客户机控制的返回目标被同级线程使用。
受影响的处理器¶
以下 CPU 存在漏洞
AMD Family 17h 处理器
海光 Family 18h 处理器
问题¶
当 SMT 启用时,受影响的支持 SMT 的处理器支持 1T 和 2T 执行模式。在 2T 模式下,核心中的两个线程都在执行代码。要使处理器核心进入 1T 模式,需要其中一个线程请求从 C0 状态转换出去。这可以通过 HLT 指令或请求非 C0 的 MWAIT 指令来传达。当线程重新进入 C0 状态时,处理器会转换回 2T 模式,前提是另一个线程也仍在 C0 状态下。
在受影响的处理器中,返回地址预测器 (RAP) 根据 SMT 模式进行分区。例如,在 2T 模式下,每个线程使用一个私有的 16 条目 RAP,但在 1T 模式下,活动线程使用一个 32 条目 RAP。在 1T/2T 模式之间转换时,RAP 内容不会被修改,但 RAP 指针(控制用于预测的下一个返回目标)可能会改变。这种行为可能导致在 1T/2T 切换后,一个 SMT 线程的返回目标被同级线程的 RET 预测使用。特别是,在转换为 1T 后立即执行的 RET 指令可能使用刚进入空闲状态的线程的返回目标。理论上,如果使用的返回目标不是来自可信代码,这可能导致信息泄露。
攻击场景¶
可以通过在受影响的处理器上执行一系列具有目标返回位置的 CALL 指令,然后转换出 C0 状态来发起攻击。
缓解机制¶
在进入空闲状态之前,内核会将上下文切换到空闲线程。上下文切换通过执行一系列 CALL 指令,用安全的目标填充 RAP 条目(在 Linux 中称为 RSB)。
通过拦截 HLT 和 MWAIT 指令,阻止客户机虚拟机直接使处理器进入空闲状态。
完全解决此问题需要以上两种缓解措施。
内核命令行上的缓解控制¶
使用现有的 Spectre v2 缓解措施,这些措施将在上下文切换时填充 RSB。
KVM 缓解控制 - 模块参数¶
默认情况下,KVM 虚拟机监控程序通过拦截客户机尝试从 C0 转换出去来缓解此问题。VMM 可以使用 KVM_CAP_X86_DISABLE_EXITS 功能来覆盖这些拦截,但由于这不常见,因此覆盖此路径的缓解措施默认未启用。
KVM_CAP_X86_DISABLE_EXITS 功能的缓解措施可以通过布尔模块参数 mitigate_smt_rsb 启用,例如 kvm.mitigate_smt_rsb=1
。