Skip to content

Commit fb3bd91

Browse files
committed
x86/srso: Add a Speculative RAS Overflow mitigation
Add a mitigation for the speculative return address stack overflow vulnerability found on AMD processors. The mitigation works by ensuring all RET instructions speculate to a controlled location, similar to how speculation is controlled in the retpoline sequence. To accomplish this, the __x86_return_thunk forces the CPU to mispredict every function return using a 'safe return' sequence. To ensure the safety of this mitigation, the kernel must ensure that the safe return sequence is itself free from attacker interference. In Zen3 and Zen4, this is accomplished by creating a BTB alias between the untraining function srso_untrain_ret_alias() and the safe return function srso_safe_ret_alias() which results in evicting a potentially poisoned BTB entry and using that safe one for all function returns. In older Zen1 and Zen2, this is accomplished using a reinterpretation technique similar to Retbleed one: srso_untrain_ret() and srso_safe_ret(). Signed-off-by: Borislav Petkov (AMD) <[email protected]>
1 parent 0e52740 commit fb3bd91

File tree

16 files changed

+422
-10
lines changed

16 files changed

+422
-10
lines changed

Documentation/admin-guide/hw-vuln/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ are configurable at compile, boot or run time.
1919
l1d_flush.rst
2020
processor_mmio_stale_data.rst
2121
cross-thread-rsb.rst
22+
srso
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
Speculative Return Stack Overflow (SRSO)
4+
========================================
5+
6+
This is a mitigation for the speculative return stack overflow (SRSO)
7+
vulnerability found on AMD processors. The mechanism is by now the well
8+
known scenario of poisoning CPU functional units - the Branch Target
9+
Buffer (BTB) and Return Address Predictor (RAP) in this case - and then
10+
tricking the elevated privilege domain (the kernel) into leaking
11+
sensitive data.
12+
13+
AMD CPUs predict RET instructions using a Return Address Predictor (aka
14+
Return Address Stack/Return Stack Buffer). In some cases, a non-architectural
15+
CALL instruction (i.e., an instruction predicted to be a CALL but is
16+
not actually a CALL) can create an entry in the RAP which may be used
17+
to predict the target of a subsequent RET instruction.
18+
19+
The specific circumstances that lead to this varies by microarchitecture
20+
but the concern is that an attacker can mis-train the CPU BTB to predict
21+
non-architectural CALL instructions in kernel space and use this to
22+
control the speculative target of a subsequent kernel RET, potentially
23+
leading to information disclosure via a speculative side-channel.
24+
25+
The issue is tracked under CVE-2023-20569.
26+
27+
Affected processors
28+
-------------------
29+
30+
AMD Zen, generations 1-4. That is, all families 0x17 and 0x19. Older
31+
processors have not been investigated.
32+
33+
System information and options
34+
------------------------------
35+
36+
First of all, it is required that the latest microcode be loaded for
37+
mitigations to be effective.
38+
39+
The sysfs file showing SRSO mitigation status is:
40+
41+
/sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow
42+
43+
The possible values in this file are:
44+
45+
- 'Not affected' The processor is not vulnerable
46+
47+
- 'Vulnerable: no microcode' The processor is vulnerable, no
48+
microcode extending IBPB functionality
49+
to address the vulnerability has been
50+
applied.
51+
52+
- 'Mitigation: microcode' Extended IBPB functionality microcode
53+
patch has been applied. It does not
54+
address User->Kernel and Guest->Host
55+
transitions protection but it does
56+
address User->User and VM->VM attack
57+
vectors.
58+
59+
(spec_rstack_overflow=microcode)
60+
61+
- 'Mitigation: safe RET' Software-only mitigation. It complements
62+
the extended IBPB microcode patch
63+
functionality by addressing User->Kernel
64+
and Guest->Host transitions protection.
65+
66+
Selected by default or by
67+
spec_rstack_overflow=safe-ret
68+
69+
- 'Mitigation: IBPB' Similar protection as "safe RET" above
70+
but employs an IBPB barrier on privilege
71+
domain crossings (User->Kernel,
72+
Guest->Host).
73+
74+
(spec_rstack_overflow=ibpb)
75+
76+
- 'Mitigation: IBPB on VMEXIT' Mitigation addressing the cloud provider
77+
scenario - the Guest->Host transitions
78+
only.
79+
80+
(spec_rstack_overflow=ibpb-vmexit)
81+
82+
In order to exploit vulnerability, an attacker needs to:
83+
84+
- gain local access on the machine
85+
86+
- break kASLR
87+
88+
- find gadgets in the running kernel in order to use them in the exploit
89+
90+
- potentially create and pin an additional workload on the sibling
91+
thread, depending on the microarchitecture (not necessary on fam 0x19)
92+
93+
- run the exploit
94+
95+
Considering the performance implications of each mitigation type, the
96+
default one is 'Mitigation: safe RET' which should take care of most
97+
attack vectors, including the local User->Kernel one.
98+
99+
As always, the user is advised to keep her/his system up-to-date by
100+
applying software updates regularly.
101+
102+
The default setting will be reevaluated when needed and especially when
103+
new attack vectors appear.
104+
105+
As one can surmise, 'Mitigation: safe RET' does come at the cost of some
106+
performance depending on the workload. If one trusts her/his userspace
107+
and does not want to suffer the performance impact, one can always
108+
disable the mitigation with spec_rstack_overflow=off.
109+
110+
Similarly, 'Mitigation: IBPB' is another full mitigation type employing
111+
an indrect branch prediction barrier after having applied the required
112+
microcode patch for one's system. This mitigation comes also at
113+
a performance cost.
114+
115+
Mitigation: safe RET
116+
--------------------
117+
118+
The mitigation works by ensuring all RET instructions speculate to
119+
a controlled location, similar to how speculation is controlled in the
120+
retpoline sequence. To accomplish this, the __x86_return_thunk forces
121+
the CPU to mispredict every function return using a 'safe return'
122+
sequence.
123+
124+
To ensure the safety of this mitigation, the kernel must ensure that the
125+
safe return sequence is itself free from attacker interference. In Zen3
126+
and Zen4, this is accomplished by creating a BTB alias between the
127+
untraining function srso_untrain_ret_alias() and the safe return
128+
function srso_safe_ret_alias() which results in evicting a potentially
129+
poisoned BTB entry and using that safe one for all function returns.
130+
131+
In older Zen1 and Zen2, this is accomplished using a reinterpretation
132+
technique similar to Retbleed one: srso_untrain_ret() and
133+
srso_safe_ret().

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5875,6 +5875,17 @@
58755875
Not specifying this option is equivalent to
58765876
spectre_v2_user=auto.
58775877

5878+
spec_rstack_overflow=
5879+
[X86] Control RAS overflow mitigation on AMD Zen CPUs
5880+
5881+
off - Disable mitigation
5882+
microcode - Enable microcode mitigation only
5883+
safe-ret - Enable sw-only safe RET mitigation (default)
5884+
ibpb - Enable mitigation by issuing IBPB on
5885+
kernel entry
5886+
ibpb-vmexit - Issue IBPB only on VMEXIT
5887+
(cloud-specific mitigation)
5888+
58785889
spec_store_bypass_disable=
58795890
[HW] Control Speculative Store Bypass (SSB) Disable mitigation
58805891
(Speculative Store Bypass vulnerability)

arch/x86/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2593,6 +2593,13 @@ config CPU_IBRS_ENTRY
25932593
This mitigates both spectre_v2 and retbleed at great cost to
25942594
performance.
25952595

2596+
config CPU_SRSO
2597+
bool "Mitigate speculative RAS overflow on AMD"
2598+
depends on CPU_SUP_AMD && X86_64 && RETHUNK
2599+
default y
2600+
help
2601+
Enable the SRSO mitigation needed on AMD Zen1-4 machines.
2602+
25962603
config SLS
25972604
bool "Mitigate Straight-Line-Speculation"
25982605
depends on CC_HAS_SLS && X86_64

arch/x86/include/asm/cpufeatures.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@
309309
#define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */
310310
#define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */
311311

312+
#define X86_FEATURE_SRSO (11*32+24) /* "" AMD BTB untrain RETs */
313+
#define X86_FEATURE_SRSO_ALIAS (11*32+25) /* "" AMD BTB untrain RETs through aliasing */
314+
312315
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
313316
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
314317
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
@@ -484,4 +487,6 @@
484487
#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
485488
#define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
486489

490+
/* BUG word 2 */
491+
#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
487492
#endif /* _ASM_X86_CPUFEATURES_H */

arch/x86/include/asm/nospec-branch.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@
211211
* eventually turn into it's own annotation.
212212
*/
213213
.macro VALIDATE_UNRET_END
214-
#if defined(CONFIG_NOINSTR_VALIDATION) && defined(CONFIG_CPU_UNRET_ENTRY)
214+
#if defined(CONFIG_NOINSTR_VALIDATION) && \
215+
(defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO))
215216
ANNOTATE_RETPOLINE_SAFE
216217
nop
217218
#endif
@@ -296,6 +297,11 @@
296297
"call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \
297298
__stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH
298299
#endif
300+
301+
#ifdef CONFIG_CPU_SRSO
302+
ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \
303+
"call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS
304+
#endif
299305
.endm
300306

301307
.macro UNTRAIN_RET_FROM_CALL
@@ -307,6 +313,11 @@
307313
"call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \
308314
__stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH
309315
#endif
316+
317+
#ifdef CONFIG_CPU_SRSO
318+
ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \
319+
"call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS
320+
#endif
310321
.endm
311322

312323

@@ -332,6 +343,8 @@ extern retpoline_thunk_t __x86_indirect_jump_thunk_array[];
332343

333344
extern void __x86_return_thunk(void);
334345
extern void zen_untrain_ret(void);
346+
extern void srso_untrain_ret(void);
347+
extern void srso_untrain_ret_alias(void);
335348
extern void entry_ibpb(void);
336349

337350
#ifdef CONFIG_CALL_THUNKS

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,11 @@ extern u16 get_llc_id(unsigned int cpu);
682682
#ifdef CONFIG_CPU_SUP_AMD
683683
extern u32 amd_get_nodes_per_socket(void);
684684
extern u32 amd_get_highest_perf(void);
685+
extern bool cpu_has_ibpb_brtype_microcode(void);
685686
#else
686687
static inline u32 amd_get_nodes_per_socket(void) { return 0; }
687688
static inline u32 amd_get_highest_perf(void) { return 0; }
689+
static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; }
688690
#endif
689691

690692
extern unsigned long arch_align_stack(unsigned long sp);

arch/x86/kernel/alternative.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,9 @@ static int patch_return(void *addr, struct insn *insn, u8 *bytes)
707707
int i = 0;
708708

709709
/* Patch the custom return thunks... */
710-
if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) {
710+
if (cpu_feature_enabled(X86_FEATURE_RETHUNK) ||
711+
cpu_feature_enabled(X86_FEATURE_SRSO) ||
712+
cpu_feature_enabled(X86_FEATURE_SRSO_ALIAS)) {
711713
i = JMP32_INSN_SIZE;
712714
__text_gen_insn(bytes, JMP32_INSN_OPCODE, addr, x86_return_thunk, i);
713715
} else {

arch/x86/kernel/cpu/amd.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,3 +1235,17 @@ u32 amd_get_highest_perf(void)
12351235
return 255;
12361236
}
12371237
EXPORT_SYMBOL_GPL(amd_get_highest_perf);
1238+
1239+
bool cpu_has_ibpb_brtype_microcode(void)
1240+
{
1241+
u8 fam = boot_cpu_data.x86;
1242+
1243+
if (fam == 0x17) {
1244+
/* Zen1/2 IBPB flushes branch type predictions too. */
1245+
return boot_cpu_has(X86_FEATURE_AMD_IBPB);
1246+
} else if (fam == 0x19) {
1247+
return false;
1248+
}
1249+
1250+
return false;
1251+
}

0 commit comments

Comments
 (0)