首页
/ Linux 内核 Cross-Thread RSB(CVE-2022-27672)漏洞机理剖析与 KVM/内核缓解配置指南

Linux 内核 Cross-Thread RSB(CVE-2022-27672)漏洞机理剖析与 KVM/内核缓解配置指南

2026-09-07 15:30:20作者:幸俭卉

本文以内核文档 Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst 为骨架,结合 x86/KVM 源码剖析 AMD/Hygon 处理器上的 Cross-Thread Return Address Predictions(跨线程返回地址预测,别名 SMT 相关的 RSB 预测注入,CVE-2022-27672)漏洞,说明其 RAP/RSB 硬件机理、攻击面,以及 Linux 内核对空转(idle)路径与 KVM 客户机的两级缓解机制与开关方法。读完本文,你将掌握该漏洞为何需要“内核 RSB 填充 + KVM 拦截 HLT/MWAIT”双管齐下、如何在命令行与 KVM 模块参数上正确配置,并能在源码层面追踪对应的实现路径。

漏洞概述与威胁模型

Cross-Thread Return Predictions(跨线程返回地址预测) 是一类影响特定 AMD 与 Hygon SMT 处理器的分支预测侧信道问题。当系统以 SMT 模式运行、且某个核心内的一对兄弟线程(sibling thread)之一通过 HLTMWAIT 退出 C0 状态时,仍处于活跃状态的另一个兄弟线程 可能错误地消费已退出 C0 线程的返回目标预测,从而在 RET 预测路径中引入不可信地址。

Linux 内核本身通过 Spectre v2 缓解体系保护了这一路径:内核在上下文切换到 idle 线程(进入空转)时,会用安全目标填充返回地址预测表项。但 KVM 允许 VMM 在客户机退出 C0 时不退出 guest 模式,一旦 HLT/MWAIT 被允许直接在客户机内执行,就可能在兄弟线程的 RET 预测中混入由 guest 控制的目标——这正是漏洞需要被单独关注的原因。

受影响处理器

依据文档与 x86 源码中的漏洞黑名单,受影响处理器如下:

厂商 处理器家族 漏洞标志
AMD Family 17h X86_BUG_SMT_RSB
Hygon Family 18h X86_BUG_SMT_RSB

内核通过 arch/x86/kernel/cpu/common.ccpu_vuln_blacklist 的条目 VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO | VMSCAPE)VULNBL_HYGON(0x18, ...) 标记这些处理器,并在启动早期通过 cpu_matches(cpu_vuln_blacklist, SMT_RSB) 命中后执行 setup_force_cpu_bug(X86_BUG_SMT_RSB)(见 common.c)。该 bug 标志是整个缓解逻辑(含 KVM 模块参数生效判定)的分发开关,后续所有 boot_cpu_has_bug(X86_BUG_SMT_RSB) 检查都依赖它。

关联 CVE

CVE 名称
CVE-2022-27672 Cross-Thread Return Address Predictions

该 CVE 与“SMT Retbleed”密切相关:受影响 CPU 同时携带 RETBLEED | SMT_RSB 等黑名单标志,属于同一代返回地址预测侧信道问题家族。

硬件机理:SMT 1T/2T 模式下的 RAP 分区与指针漂移

要理解该漏洞,需要先理解受影响处理器的执行模式切换机制:

  • 支持 SMT 的受影响处理器在 SMT 使能时支持 1T 与 2T 两种执行模式
    • 2T 模式:核心内两个线程同时在执行代码;
    • 1T 模式:仅单个线程活跃,要求另一个线程主动请求退出 C0 状态(通过执行 HLT 指令,或执行请求非 C0 状态的 MWAIT 指令来表达)。当线程重新进入 C0 时,只要另一线程仍处于 C0,处理器便回到 2T 模式。
  • 受影响处理器的返回地址预测器(Return Address Predictor,RAP) 依据 SMT 模式被分区使用:
    • 2T 模式下,每个线程使用一份私有的 16 项 RAP;
    • 1T 模式下,活跃线程使用 32 项 RAP。
  • 关键点在于:1T/2T 模式切换时 RAP 内容并不清空,但控制“下一次 RET 预测该使用哪个返回目标”的 RAP 指针可能发生变化

正是“内容保留、指针漂移”的组合,导致一个 SMT 线程的返回目标可能被兄弟线程的 RET 预测使用:RET 指令若紧跟在 1T 模式切换之后执行,可能消费刚从 C0 退出(转入 idle)线程留下的返回目标。理论上,若这些被消费的返回目标并非来自可信代码,就会造成信息泄露。Linux 文档将该硬件单元称为 RAP,而 Linux 上下文切换填充路径沿用了传统术语 RSB(Return Stack Buffer),二者在本文语境中指代同一预测结构。

攻击场景

攻击者可以在受影响处理器上按如下步骤布设攻击原语:

  1. 执行一系列 CALL 指令,把精心选择的“返回位置”(return locations)压入 RSB/RAP;
  2. 通过 HLT/MWAIT 退出 C0 状态,触发 1T/2T 模式切换;
  3. 借助 RAP 指针漂移,使兄弟线程随后的 RET 预测命中攻击者布置的返回目标。

若该返回目标落在攻击者可控制的代码(例如 guest 内代码)上,兄弟线程(宿主侧)可能在此后基于不可信预测执行,进而引发信息泄露。由于返回目标本身来自执行过的 CALL 指令,这一场景更偏向于推测执行窗口内的侧信道利用。

缓解机制:为何需要“内核 + KVM”双重防护

文档明确指出,完整解决该问题需要同时具备两层缓解:

1. 内核侧:idle 路径的 RSB 填充

在进入空转状态前,内核会把上下文切换到 idle 线程;上下文切换通过执行一串 CALL 指令,把 RAP/RSB 表项填充为安全目标。这样即便发生 1T/2T 切换、RAP 指针发生漂移,兄弟线程随后消费到的返回目标也来自内核植入的安全地址,而非前一线程遗留的用户可控地址。这一机制是既有 Spectre v2 缓解的一部分,其命令行为解析与缓解策略选择实现在 arch/x86/kernel/cpu/bugs.c(含 spectre_v2_user_parse_cmdline 等解析函数)。因此,只要保持 Spectre v2 缓解开启,宿主内核的上下文切换路径即处于受保护状态;相关的 RSB(返回栈缓冲)攻击与填充原理可进一步参考 Documentation/admin-guide/hw-vuln/rsb.rst

2. KVM 侧:拦截 HLT 与 MWAIT,阻止 guest 直接置处理器于空转

仅保护宿主内核还不够:如果客户机(guest)能把处理器直接置于空转状态,guest 控制的 CALL/返回目标就可能成为 RAP 中的“脏数据”。因此 KVM 虚拟化层还需拦截客户机的 HLT 与 MWAIT 指令,避免 guest 绕过宿主内核的 RSB 填充路径直接触发 1T/2T 切换。

以 SVM(AMD/ Hygon 的硬件虚拟化扩展)为例,在 arch/x86/kvm/svm/svm.c 中,KVM 初始化 VMCB 拦截位时:

  • 仅当 !kvm_mwait_in_guest() 时才设置 INTERCEPT_MONITORINTERCEPT_MWAIT
  • 仅当 !kvm_hlt_in_guest() 时才设置 INTERCEPT_IDLE_HLT/INTERCEPT_HLT

即:默认情况下这些指令均被拦截;只有当 VMM 通过 KVM_CAP_X86_DISABLE_EXITS 显式“取消退出”后,拦截位才会被清除。kvm_hlt_in_guest()/kvm_mwait_in_guest() 等辅助函数通过检查 kvm->arch.disabled_exits 位掩码(对应 KVM_X86_DISABLE_EXITS_HLTKVM_X86_DISABLE_EXITS_MWAITKVM_X86_DISABLE_EXITS_CSTATE)判定该 VM 是否允许在 guest 内直接执行这些指令,见 arch/x86/kvm/x86.h

缓解控制与配置实操

内核命令行:沿用既有 Spectre v2 缓解

Cross-Thread RSB 的内核侧防护不引入新开关,直接使用现有 Spectre v2 缓解即可:保持默认的 retpoline/Safe RET 与上下文切换 RSB 填充不被关闭(不要使用 spectre_v2=offmitigations=off 之类的破坏性开关)。具体可用取值与影响可查阅 Documentation/admin-guide/hw-vuln/spectre.rstDocumentation/admin-guide/hw-vuln/rsb.rst

KVM 缓解开关:kvm.mitigate_smt_rsb

默认行为如下:

  • 默认情况下,KVM 本身就通过拦截 guest 的 C0 退出尝试来缓解该问题(即拦截 HLT/MWAIT);
  • 但 VMM 可以使用 KVM_CAP_X86_DISABLE_EXITS capability 请求取消这些拦截。由于实际使用该 capability 的 VMM 并不常见,针对这条“取消拦截”路径的强制缓解默认并未开启

补充防护通过 KVM 模块的布尔参数 kvm.mitigate_smt_rsb 打开:

kvm.mitigate_smt_rsb=1

例如在 /etc/modprobe.d/ 下添加配置后重新加载 kvm 模块,或在内核命令行通过 kvm.mitigate_smt_rsb=1 传入。在源码中(arch/x86/kvm/x86.c):

/* Enable/disable SMT_RSB bug mitigation */
static bool __read_mostly mitigate_smt_rsb;
module_param(mitigate_smt_rsb, bool, 0444);

其生效逻辑在 arch/x86/kvm/x86.c 的模块初始化函数中收口:

mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible();

也就是说,即使显式传入 kvm.mitigate_smt_rsb=1,也只有当 CPU 实际携带 X86_BUG_SMT_RSB 漏洞标志且 SMT 可能启用时,该参数才真正生效——在不受影响或 SMT 禁用的系统上它是空操作,这是设计上的自动降级。

该参数如何起作用?见 arch/x86/kvm/x86.ckvm_get_allowed_disable_exits()

static u64 kvm_get_allowed_disable_exits(void)
{
	u64 r = KVM_X86_DISABLE_EXITS_PAUSE;

	if (boot_cpu_has(X86_FEATURE_APERFMPERF))
		r |= KVM_X86_DISABLE_EXITS_APERFMPERF;

	if (!mitigate_smt_rsb) {
		r |= KVM_X86_DISABLE_EXITS_HLT |
			KVM_X86_DISABLE_EXITS_CSTATE;

		if (kvm_can_mwait_in_guest())
			r |= KVM_X86_DISABLE_EXITS_MWAIT;
	}
	return r;
}

含义一目了然:

  • mitigate_smt_rsb 为 0(默认)时,VMM 通过 KVM_CAP_X86_DISABLE_EXITS 可请求的取消项包含 HLTCSTATEMWAIT(后者还需 CPU 支持 MWAIT 虚拟化条件 kvm_can_mwait_in_guest():具备 X86_FEATURE_MWAIT、无 X86_BUG_MONITOR、具备 X86_FEATURE_ARAT);
  • mitigate_smt_rsb=1 时,这三项从“可取消集合”中被剔除,VMM 即使请求也无法关闭对应拦截,从而保证 guest 无法直接置处理器于空转。

该 capability 的处理在 arch/x86/kvm/x86.c:内核首先校验 cap->args[0] 不超过 kvm_get_allowed_disable_exits() 允许的位,随后通过 kvm_disable_exits(kvm, cap->args[0]) 落掩码。特别地,在处理器受影响(X86_BUG_SMT_RSB)、SMT 可能存在、且未开启 mitigate_smt_rsb 的情况下,如果 VMM 请求了超出 PAUSE/APERFMPERF 的取消项,KVM 会通过 pr_warn_once() 打印一条警示(SMT_RSB_MSG):

"This processor is affected by the Cross-Thread Return Predictions vulnerability. KVM_CAP_X86_DISABLE_EXITS should only be used with SMT disabled or trusted guests."

这条警告的含义是:在受影响的处理器上,只有已关闭 SMT完全信任 guest 时才应取消对 HLT/MWAIT/CSTATE 的拦截。若在宿主日志中看到该消息,说明当前配置正在放宽对该漏洞的保护。

推荐配置组合

综合文档与源码,面向受影响平台的加固建议如下:

  1. 保持默认 Spectre v2 缓解开启,确保上下文切换路径的 RSB 填充生效;
  2. 若 CPU 属于 AMD Family 17h / Hygon Family 18h 且启用了 SMT,建议加载 kvm 模块时传入 kvm.mitigate_smt_rsb=1,从“允许集合”中排除 HLT/CSTATE/MWAIT 取消项;
  3. 对于确需使用 KVM_CAP_X86_DISABLE_EXITS 取消这些退出的高性能场景,先评估自身是否满足“SMT 已关闭”或“guest 可信”的前提;
  4. 如无强需求,直接关闭 SMT 也是消除该 SMT 侧信道的终极手段(内核对该 CPU bug 的强制缓解判定同样依赖 cpu_smt_possible())。

状态查询与延伸阅读

系统整体漏洞缓解状态可通过 sysfs 查看。内核在 /sys/devices/system/cpu/vulnerabilities/ 下按漏洞公开状态文件(输出形如 "Not affected" / "Vulnerable" / "Mitigation: ..."),其中 spectre_v2 文件反映了含 RSB 填充在内的 Spectre v2 缓解状态,接口说明见 Documentation/ABI/testing/sysfs-devices-system-cpu。完整的 CPU 漏洞/缓解状态文件清单与通用读取方式见 Documentation/admin-guide/hw-vuln/index.rst

相关主题的进一步阅读:

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
916
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388