1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
From d4e286db89d80c862b4a24bf971dd71008c8b53e Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Thu, 8 Sep 2022 21:27:58 +0100
Subject: [PATCH 22/61] x86/spec-ctrl: Mitigate Cross-Thread Return Address
Predictions
This is XSA-426 / CVE-2022-27672
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 63305e5392ec2d17b85e7996a97462744425db80)
---
docs/misc/xen-command-line.pandoc | 2 +-
xen/arch/x86/spec_ctrl.c | 31 ++++++++++++++++++++++++++++---
xen/include/asm-x86/cpufeatures.h | 3 ++-
xen/include/asm-x86/spec_ctrl.h | 15 +++++++++++++++
4 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index bd6826d0ae..b3f60cd923 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2275,7 +2275,7 @@ guests to use.
on entry and exit. These blocks are necessary to virtualise support for
guests and if disabled, guests will be unable to use IBRS/STIBP/SSBD/etc.
* `rsb=` offers control over whether to overwrite the Return Stack Buffer /
- Return Address Stack on entry to Xen.
+ Return Address Stack on entry to Xen and on idle.
* `md-clear=` offers control over whether to use VERW to flush
microarchitectural buffers on idle and exit from Xen. *Note: For
compatibility with development versions of this fix, `mds=` is also accepted
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index 90d86fe5cb..14649d92f5 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -1317,13 +1317,38 @@ void __init init_speculation_mitigations(void)
* 3) Some CPUs have RSBs which are not full width, which allow the
* attacker's entries to alias Xen addresses.
*
+ * 4) Some CPUs have RSBs which are re-partitioned based on thread
+ * idleness, which allows an attacker to inject entries into the other
+ * thread. We still active the optimisation in this case, and mitigate
+ * in the idle path which has lower overhead.
+ *
* It is safe to turn off RSB stuffing when Xen is using SMEP itself, and
* 32bit PV guests are disabled, and when the RSB is full width.
*/
BUILD_BUG_ON(RO_MPT_VIRT_START != PML4_ADDR(256));
- if ( opt_rsb_pv == -1 && boot_cpu_has(X86_FEATURE_XEN_SMEP) &&
- !opt_pv32 && rsb_is_full_width() )
- opt_rsb_pv = 0;
+ if ( opt_rsb_pv == -1 )
+ {
+ opt_rsb_pv = (opt_pv32 || !boot_cpu_has(X86_FEATURE_XEN_SMEP) ||
+ !rsb_is_full_width());
+
+ /*
+ * Cross-Thread Return Address Predictions.
+ *
+ * Vulnerable systems are Zen1/Zen2 uarch, which is AMD Fam17 / Hygon
+ * Fam18, when SMT is active.
+ *
+ * To mitigate, we must flush the RSB/RAS/RAP once between entering
+ * Xen and going idle.
+ *
+ * Most cases flush on entry to Xen anyway. The one case where we
+ * don't is when using the SMEP optimisation for PV guests. Flushing
+ * before going idle is less overhead than flushing on PV entry.
+ */
+ if ( !opt_rsb_pv && hw_smt_enabled &&
+ (boot_cpu_data.x86_vendor & (X86_VENDOR_AMD|X86_VENDOR_HYGON)) &&
+ (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) )
+ setup_force_cpu_cap(X86_FEATURE_SC_RSB_IDLE);
+ }
if ( opt_rsb_pv )
{
diff --git a/xen/include/asm-x86/cpufeatures.h b/xen/include/asm-x86/cpufeatures.h
index ecc1bb0950..ccf9d7287c 100644
--- a/xen/include/asm-x86/cpufeatures.h
+++ b/xen/include/asm-x86/cpufeatures.h
@@ -35,7 +35,8 @@ XEN_CPUFEATURE(SC_RSB_HVM, X86_SYNTH(19)) /* RSB overwrite needed for HVM
XEN_CPUFEATURE(XEN_SELFSNOOP, X86_SYNTH(20)) /* SELFSNOOP gets used by Xen itself */
XEN_CPUFEATURE(SC_MSR_IDLE, X86_SYNTH(21)) /* Clear MSR_SPEC_CTRL on idle */
XEN_CPUFEATURE(XEN_LBR, X86_SYNTH(22)) /* Xen uses MSR_DEBUGCTL.LBR */
-/* Bits 23,24 unused. */
+/* Bits 23 unused. */
+XEN_CPUFEATURE(SC_RSB_IDLE, X86_SYNTH(24)) /* RSB overwrite needed for idle. */
XEN_CPUFEATURE(SC_VERW_IDLE, X86_SYNTH(25)) /* VERW used by Xen for idle */
XEN_CPUFEATURE(XEN_SHSTK, X86_SYNTH(26)) /* Xen uses CET Shadow Stacks */
XEN_CPUFEATURE(XEN_IBT, X86_SYNTH(27)) /* Xen uses CET Indirect Branch Tracking */
diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h
index 6a77c39378..391973ef6a 100644
--- a/xen/include/asm-x86/spec_ctrl.h
+++ b/xen/include/asm-x86/spec_ctrl.h
@@ -159,6 +159,21 @@ static always_inline void spec_ctrl_enter_idle(struct cpu_info *info)
*/
alternative_input("", "verw %[sel]", X86_FEATURE_SC_VERW_IDLE,
[sel] "m" (info->verw_sel));
+
+ /*
+ * Cross-Thread Return Address Predictions:
+ *
+ * On vulnerable systems, the return predictions (RSB/RAS) are statically
+ * partitioned between active threads. When entering idle, our entries
+ * are re-partitioned to allow the other threads to use them.
+ *
+ * In some cases, we might still have guest entries in the RAS, so flush
+ * them before injecting them sideways to our sibling thread.
+ *
+ * (ab)use alternative_input() to specify clobbers.
+ */
+ alternative_input("", "DO_OVERWRITE_RSB", X86_FEATURE_SC_RSB_IDLE,
+ : "rax", "rcx");
}
/* WARNING! `ret`, `call *`, `jmp *` not safe before this call. */
--
2.40.0
|