跨线程返回地址预测

某些 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 指针(控制用于预测的下一个返回目标)可能会发生变化。此行为可能会导致一个 SMT 线程的返回目标在 1T/2T 切换后被兄弟线程中的 RET 预测使用。特别是,在转换到 1T 后立即执行的 RET 指令可能会使用刚刚变为空闲的线程的返回目标。从理论上讲,如果使用的返回目标不是来自可信代码,这可能会导致信息泄露。

攻击场景

可以通过执行一系列具有目标返回位置的 CALL 指令,然后转换出 C0 状态,在受影响的处理器上发起攻击。

缓解机制

在进入空闲状态之前,内核上下文切换到空闲线程。上下文切换通过执行一系列 CALL 指令,使用安全目标填充 RAP 条目(在 Linux 中称为 RSB)。

通过拦截 HLT 和 MWAIT 指令,防止访客虚拟机直接将处理器置于空闲状态。

需要两种缓解措施才能完全解决此问题。

内核命令行上的缓解控制

使用现有的 Spectre v2 缓解措施,这些措施将在上下文切换时填充 RSB。

KVM 的缓解控制 - 模块参数

默认情况下,KVM 虚拟机监控程序通过拦截访客尝试转换出 C0 来缓解此问题。VMM 可以使用 KVM_CAP_X86_DISABLE_EXITS 功能覆盖这些拦截,但由于这并不常见,因此默认情况下不会启用涵盖此路径的缓解措施。

可以使用布尔模块参数 mitigate_smt_rsb 开启对 KVM_CAP_X86_DISABLE_EXITS 功能的缓解,例如 kvm.mitigate_smt_rsb=1