Skip to content

Commit c995efd

Browse files
dwmw2KAGA-KOKO
authored andcommitted
x86/retpoline: Fill RSB on context switch for affected CPUs
On context switch from a shallow call stack to a deeper one, as the CPU does 'ret' up the deeper side it may encounter RSB entries (predictions for where the 'ret' goes to) which were populated in userspace. This is problematic if neither SMEP nor KPTI (the latter of which marks userspace pages as NX for the kernel) are active, as malicious code in userspace may then be executed speculatively. Overwrite the CPU's return prediction stack with calls which are predicted to return to an infinite loop, to "capture" speculation if this happens. This is required both for retpoline, and also in conjunction with IBRS for !SMEP && !KPTI. On Skylake+ the problem is slightly different, and an *underflow* of the RSB may cause errant branch predictions to occur. So there it's not so much overwrite, as *filling* the RSB to attempt to prevent it getting empty. This is only a partial solution for Skylake+ since there are many other conditions which may result in the RSB becoming empty. The full solution on Skylake+ is to use IBRS, which will prevent the problem even when the RSB becomes empty. With IBRS, the RSB-stuffing will not be required on context switch. [ tglx: Added missing vendor check and slighty massaged comments and changelog ] Signed-off-by: David Woodhouse <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Arjan van de Ven <[email protected]> Cc: [email protected] Cc: Rik van Riel <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: [email protected] Cc: Peter Zijlstra <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Jiri Kosina <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Kees Cook <[email protected]> Cc: Tim Chen <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Paul Turner <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 0d39e26 commit c995efd

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

arch/x86/entry/entry_32.S

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,17 @@ ENTRY(__switch_to_asm)
244244
movl %ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
245245
#endif
246246

247+
#ifdef CONFIG_RETPOLINE
248+
/*
249+
* When switching from a shallower to a deeper call stack
250+
* the RSB may either underflow or use entries populated
251+
* with userspace addresses. On CPUs where those concerns
252+
* exist, overwrite the RSB with entries which capture
253+
* speculative execution to prevent attack.
254+
*/
255+
FILL_RETURN_BUFFER %ebx, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
256+
#endif
257+
247258
/* restore callee-saved registers */
248259
popl %esi
249260
popl %edi

arch/x86/entry/entry_64.S

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,17 @@ ENTRY(__switch_to_asm)
487487
movq %rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset
488488
#endif
489489

490+
#ifdef CONFIG_RETPOLINE
491+
/*
492+
* When switching from a shallower to a deeper call stack
493+
* the RSB may either underflow or use entries populated
494+
* with userspace addresses. On CPUs where those concerns
495+
* exist, overwrite the RSB with entries which capture
496+
* speculative execution to prevent attack.
497+
*/
498+
FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
499+
#endif
500+
490501
/* restore callee-saved registers */
491502
popq %r15
492503
popq %r14

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@
211211
#define X86_FEATURE_AVX512_4FMAPS ( 7*32+17) /* AVX-512 Multiply Accumulation Single precision */
212212

213213
#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */
214+
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */
214215

215216
/* Virtualization flags: Linux defined, word 8 */
216217
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */

arch/x86/kernel/cpu/bugs.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <asm/alternative.h>
2424
#include <asm/pgtable.h>
2525
#include <asm/set_memory.h>
26+
#include <asm/intel-family.h>
2627

2728
static void __init spectre_v2_select_mitigation(void);
2829

@@ -155,6 +156,23 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
155156
return SPECTRE_V2_CMD_NONE;
156157
}
157158

159+
/* Check for Skylake-like CPUs (for RSB handling) */
160+
static bool __init is_skylake_era(void)
161+
{
162+
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
163+
boot_cpu_data.x86 == 6) {
164+
switch (boot_cpu_data.x86_model) {
165+
case INTEL_FAM6_SKYLAKE_MOBILE:
166+
case INTEL_FAM6_SKYLAKE_DESKTOP:
167+
case INTEL_FAM6_SKYLAKE_X:
168+
case INTEL_FAM6_KABYLAKE_MOBILE:
169+
case INTEL_FAM6_KABYLAKE_DESKTOP:
170+
return true;
171+
}
172+
}
173+
return false;
174+
}
175+
158176
static void __init spectre_v2_select_mitigation(void)
159177
{
160178
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -213,6 +231,24 @@ static void __init spectre_v2_select_mitigation(void)
213231

214232
spectre_v2_enabled = mode;
215233
pr_info("%s\n", spectre_v2_strings[mode]);
234+
235+
/*
236+
* If neither SMEP or KPTI are available, there is a risk of
237+
* hitting userspace addresses in the RSB after a context switch
238+
* from a shallow call stack to a deeper one. To prevent this fill
239+
* the entire RSB, even when using IBRS.
240+
*
241+
* Skylake era CPUs have a separate issue with *underflow* of the
242+
* RSB, when they will predict 'ret' targets from the generic BTB.
243+
* The proper mitigation for this is IBRS. If IBRS is not supported
244+
* or deactivated in favour of retpolines the RSB fill on context
245+
* switch is required.
246+
*/
247+
if ((!boot_cpu_has(X86_FEATURE_PTI) &&
248+
!boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) {
249+
setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
250+
pr_info("Filling RSB on context switch\n");
251+
}
216252
}
217253

218254
#undef pr_fmt

0 commit comments

Comments
 (0)