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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
From de751c3d906d17b2e25ee429f81b17a689c7c6c0 Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Wed, 30 Aug 2023 20:24:25 +0100
Subject: [PATCH 11/27] x86/spec-ctrl: Mitigate the Zen1 DIV leakage
In the Zen1 microarchitecure, there is one divider in the pipeline which
services uops from both threads. In the case of #DE, the latched result from
the previous DIV to execute will be forwarded speculatively.
This is an interesting covert channel that allows two threads to communicate
without any system calls. In also allows userspace to obtain the result of
the most recent DIV instruction executed (even speculatively) in the core,
which can be from a higher privilege context.
Scrub the result from the divider by executing a non-faulting divide. This
needs performing on the exit-to-guest paths, and ist_exit-to-Xen.
Alternatives in IST context is believed safe now that it's done in NMI
context.
This is XSA-439 / CVE-2023-20588.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit b5926c6ecf05c28ee99c6248c42d691ccbf0c315)
---
docs/misc/xen-command-line.pandoc | 6 +++-
xen/arch/x86/hvm/svm/entry.S | 1 +
xen/arch/x86/spec_ctrl.c | 49 ++++++++++++++++++++++++++++-
xen/include/asm-x86/cpufeatures.h | 2 +-
xen/include/asm-x86/spec_ctrl_asm.h | 17 ++++++++++
5 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index a37a3890d1..a7a1362bac 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -2263,7 +2263,7 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`).
> {msr-sc,rsb,md-clear,ibpb-entry}=<bool>|{pv,hvm}=<bool>,
> bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd,
> eager-fpu,l1d-flush,branch-harden,srb-lock,
-> unpriv-mmio,gds-mit}=<bool> ]`
+> unpriv-mmio,gds-mit,div-scrub}=<bool> ]`
Controls for speculative execution sidechannel mitigations. By default, Xen
will pick the most appropriate mitigations based on compiled in support,
@@ -2383,6 +2383,10 @@ has elected not to lock the configuration, Xen will use GDS_CTRL to mitigate
GDS with. Otherwise, Xen will mitigate by disabling AVX, which blocks the use
of the AVX2 Gather instructions.
+On all hardware, the `div-scrub=` option can be used to force or prevent Xen
+from mitigating the DIV-leakage vulnerability. By default, Xen will mitigate
+DIV-leakage on hardware believed to be vulnerable.
+
### sync_console
> `= <boolean>`
diff --git a/xen/arch/x86/hvm/svm/entry.S b/xen/arch/x86/hvm/svm/entry.S
index 0ff4008060..ad5ca50c12 100644
--- a/xen/arch/x86/hvm/svm/entry.S
+++ b/xen/arch/x86/hvm/svm/entry.S
@@ -72,6 +72,7 @@ __UNLIKELY_END(nsvm_hap)
1: /* No Spectre v1 concerns. Execution will hit VMRUN imminently. */
.endm
ALTERNATIVE "", svm_vmentry_spec_ctrl, X86_FEATURE_SC_MSR_HVM
+ ALTERNATIVE "", DO_SPEC_CTRL_DIV, X86_FEATURE_SC_DIV
pop %r15
pop %r14
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index 082445179d..6e82a126a3 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -22,6 +22,7 @@
#include <xen/param.h>
#include <xen/warning.h>
+#include <asm/amd.h>
#include <asm/hvm/svm/svm.h>
#include <asm/microcode.h>
#include <asm/msr.h>
@@ -78,6 +79,7 @@ static int8_t __initdata opt_srb_lock = -1;
static bool __initdata opt_unpriv_mmio;
static bool __read_mostly opt_fb_clear_mmio;
static int8_t __initdata opt_gds_mit = -1;
+static int8_t __initdata opt_div_scrub = -1;
static int __init parse_spec_ctrl(const char *s)
{
@@ -132,6 +134,7 @@ static int __init parse_spec_ctrl(const char *s)
opt_srb_lock = 0;
opt_unpriv_mmio = false;
opt_gds_mit = 0;
+ opt_div_scrub = 0;
}
else if ( val > 0 )
rc = -EINVAL;
@@ -284,6 +287,8 @@ static int __init parse_spec_ctrl(const char *s)
opt_unpriv_mmio = val;
else if ( (val = parse_boolean("gds-mit", s, ss)) >= 0 )
opt_gds_mit = val;
+ else if ( (val = parse_boolean("div-scrub", s, ss)) >= 0 )
+ opt_div_scrub = val;
else
rc = -EINVAL;
@@ -484,7 +489,7 @@ static void __init print_details(enum ind_thunk thunk)
"\n");
/* Settings for Xen's protection, irrespective of guests. */
- printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s%s, Other:%s%s%s%s%s\n",
+ printk(" Xen settings: BTI-Thunk %s, SPEC_CTRL: %s%s%s%s%s, Other:%s%s%s%s%s%s\n",
thunk == THUNK_NONE ? "N/A" :
thunk == THUNK_RETPOLINE ? "RETPOLINE" :
thunk == THUNK_LFENCE ? "LFENCE" :
@@ -509,6 +514,7 @@ static void __init print_details(enum ind_thunk thunk)
opt_l1d_flush ? " L1D_FLUSH" : "",
opt_md_clear_pv || opt_md_clear_hvm ||
opt_fb_clear_mmio ? " VERW" : "",
+ opt_div_scrub ? " DIV" : "",
opt_branch_harden ? " BRANCH_HARDEN" : "");
/* L1TF diagnostics, printed if vulnerable or PV shadowing is in use. */
@@ -962,6 +968,45 @@ static void __init srso_calculations(bool hw_smt_enabled)
setup_force_cpu_cap(X86_FEATURE_SRSO_NO);
}
+/*
+ * The Div leakage issue is specific to the AMD Zen1 microarchitecure.
+ *
+ * However, there's no $FOO_NO bit defined, so if we're virtualised we have no
+ * hope of spotting the case where we might move to vulnerable hardware. We
+ * also can't make any useful conclusion about SMT-ness.
+ *
+ * Don't check the hypervisor bit, so at least we do the safe thing when
+ * booting on something that looks like a Zen1 CPU.
+ */
+static bool __init has_div_vuln(void)
+{
+ if ( !(boot_cpu_data.x86_vendor &
+ (X86_VENDOR_AMD | X86_VENDOR_HYGON)) )
+ return false;
+
+ if ( boot_cpu_data.x86 != 0x17 && boot_cpu_data.x86 != 0x18 )
+ return false;
+
+ return is_zen1_uarch();
+}
+
+static void __init div_calculations(bool hw_smt_enabled)
+{
+ bool cpu_bug_div = has_div_vuln();
+
+ if ( opt_div_scrub == -1 )
+ opt_div_scrub = cpu_bug_div;
+
+ if ( opt_div_scrub )
+ setup_force_cpu_cap(X86_FEATURE_SC_DIV);
+
+ if ( opt_smt == -1 && !cpu_has_hypervisor && cpu_bug_div && hw_smt_enabled )
+ warning_add(
+ "Booted on leaky-DIV hardware with SMT/Hyperthreading\n"
+ "enabled. Please assess your configuration and choose an\n"
+ "explicit 'smt=<bool>' setting. See XSA-439.\n");
+}
+
static void __init ibpb_calculations(void)
{
bool def_ibpb_entry = false;
@@ -1716,6 +1761,8 @@ void __init init_speculation_mitigations(void)
ibpb_calculations();
+ div_calculations(hw_smt_enabled);
+
/* Check whether Eager FPU should be enabled by default. */
if ( opt_eager_fpu == -1 )
opt_eager_fpu = should_use_eager_fpu();
diff --git a/xen/include/asm-x86/cpufeatures.h b/xen/include/asm-x86/cpufeatures.h
index ccf9d7287c..70b93b6b44 100644
--- a/xen/include/asm-x86/cpufeatures.h
+++ b/xen/include/asm-x86/cpufeatures.h
@@ -35,7 +35,7 @@ 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 unused. */
+XEN_CPUFEATURE(SC_DIV, X86_SYNTH(23)) /* DIV scrub needed */
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 */
diff --git a/xen/include/asm-x86/spec_ctrl_asm.h b/xen/include/asm-x86/spec_ctrl_asm.h
index 8a816b8cf6..0e69971f66 100644
--- a/xen/include/asm-x86/spec_ctrl_asm.h
+++ b/xen/include/asm-x86/spec_ctrl_asm.h
@@ -182,6 +182,19 @@
.L\@_verw_skip:
.endm
+.macro DO_SPEC_CTRL_DIV
+/*
+ * Requires nothing
+ * Clobbers %rax
+ *
+ * Issue a DIV for its flushing side effect (Zen1 uarch specific). Any
+ * non-faulting DIV will do; a byte DIV has least latency, and doesn't clobber
+ * %rdx.
+ */
+ mov $1, %eax
+ div %al
+.endm
+
.macro DO_SPEC_CTRL_ENTRY maybexen:req
/*
* Requires %rsp=regs (also cpuinfo if !maybexen)
@@ -284,6 +297,8 @@
ALTERNATIVE "", DO_SPEC_CTRL_EXIT_TO_GUEST, X86_FEATURE_SC_MSR_PV
DO_SPEC_CTRL_COND_VERW
+
+ ALTERNATIVE "", DO_SPEC_CTRL_DIV, X86_FEATURE_SC_DIV
.endm
/*
@@ -396,6 +411,8 @@ UNLIKELY_DISPATCH_LABEL(\@_serialise):
verw STACK_CPUINFO_FIELD(verw_sel)(%r14)
.L\@_skip_verw:
+ ALTERNATIVE "", DO_SPEC_CTRL_DIV, X86_FEATURE_SC_DIV
+
.L\@_skip_ist_exit:
.endm
--
2.42.0
|