|
Borislav Petkov |
b64e2f |
From: Peter Zijlstra <peterz@infradead.org>
|
|
Borislav Petkov |
b64e2f |
Date: Tue, 14 Jun 2022 23:16:02 +0200
|
|
Borislav Petkov |
b64e2f |
Subject: x86/bugs: Add retbleed=ibpb
|
|
Borislav Petkov |
b64e2f |
Git-commit: 3ebc170068885b6fc7bedda6c667bb2c4d533159
|
|
Borislav Petkov |
d06c64 |
Patch-mainline: v5.19-rc4
|
|
Borislav Petkov |
b64e2f |
References: bsc#1199657 CVE-2022-29900 CVE-2022-29901
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
jmp2ret mitigates the easy-to-attack case at relatively low overhead.
|
|
Borislav Petkov |
b64e2f |
It mitigates the long speculation windows after a mispredicted RET, but
|
|
Borislav Petkov |
b64e2f |
it does not mitigate the short speculation window from arbitrary
|
|
Borislav Petkov |
b64e2f |
instruction boundaries.
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
On Zen2, there is a chicken bit which needs setting, which mitigates
|
|
Borislav Petkov |
b64e2f |
"arbitrary instruction boundaries" down to just "basic block boundaries".
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
But there is no fix for the short speculation window on basic block
|
|
Borislav Petkov |
b64e2f |
boundaries, other than to flush the entire BTB to evict all attacker
|
|
Borislav Petkov |
b64e2f |
predictions.
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
On the spectrum of "fast & blurry" -> "safe", there is (on top of STIBP
|
|
Borislav Petkov |
b64e2f |
or no-SMT):
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
1) Nothing System wide open
|
|
Borislav Petkov |
b64e2f |
2) jmp2ret May stop a script kiddy
|
|
Borislav Petkov |
b64e2f |
3) jmp2ret+chickenbit Raises the bar rather further
|
|
Borislav Petkov |
b64e2f |
4) IBPB Only thing which can count as "safe".
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
Tentative numbers put IBPB-on-entry at a 2.5x hit on Zen2, and a 10x hit
|
|
Borislav Petkov |
b64e2f |
on Zen1 according to lmbench.
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
[ bp: Fixup feature bit comments, document option, 32-bit build fix. ]
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
Suggested-by: Andrew Cooper <Andrew.Cooper3@citrix.com>
|
|
Borislav Petkov |
b64e2f |
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
|
|
Borislav Petkov |
b64e2f |
Signed-off-by: Borislav Petkov <bp@suse.de>
|
|
Borislav Petkov |
b64e2f |
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
|
|
Borislav Petkov |
b64e2f |
Signed-off-by: Borislav Petkov <bp@suse.de>
|
|
Borislav Petkov |
b64e2f |
---
|
|
Borislav Petkov |
b64e2f |
Documentation/admin-guide/kernel-parameters.txt | 3 +
|
|
Borislav Petkov |
b64e2f |
arch/x86/entry/Makefile | 2 -
|
|
Borislav Petkov |
b64e2f |
arch/x86/entry/entry.S | 32 +++++++++++++++++
|
|
Borislav Petkov |
b64e2f |
arch/x86/include/asm/cpufeatures.h | 2 -
|
|
Borislav Petkov |
b64e2f |
arch/x86/include/asm/nospec-branch.h | 8 +++-
|
|
Borislav Petkov |
b64e2f |
arch/x86/kernel/cpu/bugs.c | 43 ++++++++++++++++++------
|
|
Borislav Petkov |
b64e2f |
6 files changed, 77 insertions(+), 13 deletions(-)
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
--- /dev/null
|
|
Borislav Petkov |
b64e2f |
+++ b/arch/x86/entry/entry.S
|
|
Borislav Petkov |
b64e2f |
@@ -0,0 +1,32 @@
|
|
Borislav Petkov |
b64e2f |
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
Borislav Petkov |
b64e2f |
+/*
|
|
Borislav Petkov |
b64e2f |
+ * Common place for both 32- and 64-bit entry routines.
|
|
Borislav Petkov |
b64e2f |
+ */
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+#include <linux/linkage.h>
|
|
Borislav Petkov |
b64e2f |
+#include <asm/export.h>
|
|
Borislav Petkov |
b64e2f |
+#include <asm/msr-index.h>
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+.pushsection .noinstr.text, "ax"
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ENTRY(entry_ibpb)
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ push %rax
|
|
Borislav Petkov |
b64e2f |
+ push %rcx
|
|
Borislav Petkov |
b64e2f |
+ push %rdx
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ movl $MSR_IA32_PRED_CMD, %ecx
|
|
Borislav Petkov |
b64e2f |
+ movl $PRED_CMD_IBPB, %eax
|
|
Borislav Petkov |
b64e2f |
+ xorl %edx, %edx
|
|
Borislav Petkov |
b64e2f |
+ wrmsr
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ pop %rdx
|
|
Borislav Petkov |
b64e2f |
+ pop %rcx
|
|
Borislav Petkov |
b64e2f |
+ pop %rax
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ RET
|
|
Borislav Petkov |
b64e2f |
+END(entry_ibpb)
|
|
Borislav Petkov |
b64e2f |
+/* For KVM */
|
|
Borislav Petkov |
b64e2f |
+EXPORT_SYMBOL_GPL(entry_ibpb);
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+.popsection
|
|
Borislav Petkov |
b64e2f |
--- a/arch/x86/entry/Makefile
|
|
Borislav Petkov |
b64e2f |
+++ b/arch/x86/entry/Makefile
|
|
Borislav Petkov |
b64e2f |
@@ -6,7 +6,7 @@ OBJECT_FILES_NON_STANDARD_entry_64_compa
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
CFLAGS_syscall_64.o += $(call cc-option,-Wno-override-init,)
|
|
Borislav Petkov |
b64e2f |
CFLAGS_syscall_32.o += $(call cc-option,-Wno-override-init,)
|
|
Borislav Petkov |
b64e2f |
-obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
|
|
Borislav Petkov |
b64e2f |
+obj-y := entry.o entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
|
|
Borislav Petkov |
b64e2f |
obj-y += common.o
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
obj-y += vdso/
|
|
Borislav Petkov |
b64e2f |
--- a/arch/x86/include/asm/cpufeatures.h
|
|
Borislav Petkov |
b64e2f |
+++ b/arch/x86/include/asm/cpufeatures.h
|
|
Borislav Petkov |
b64e2f |
@@ -283,7 +283,7 @@
|
|
Borislav Petkov |
b64e2f |
#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */
|
|
Borislav Petkov |
b64e2f |
#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
|
|
Borislav Petkov |
b64e2f |
#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
|
|
Borislav Petkov |
b64e2f |
-/* FREE! (11*32+10) */
|
|
Borislav Petkov |
b64e2f |
+#define X86_FEATURE_ENTRY_IBPB (11*32+10) /* "" Issue an IBPB on kernel entry */
|
|
Borislav Petkov |
b64e2f |
/* FREE! (11*32+11) */
|
|
Borislav Petkov |
b64e2f |
#define X86_FEATURE_RETPOLINE (11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
|
|
Borislav Petkov |
b64e2f |
#define X86_FEATURE_RETPOLINE_LFENCE (11*32+13) /* "" Use LFENCE for Spectre variant 2 */
|
|
Borislav Petkov |
b64e2f |
--- a/arch/x86/include/asm/nospec-branch.h
|
|
Borislav Petkov |
b64e2f |
+++ b/arch/x86/include/asm/nospec-branch.h
|
|
Borislav Petkov |
b64e2f |
@@ -155,14 +155,17 @@
|
|
Borislav Petkov |
b64e2f |
* return thunk isn't mapped into the userspace tables (then again, AMD
|
|
Borislav Petkov |
b64e2f |
* typically has NO_MELTDOWN).
|
|
Borislav Petkov |
b64e2f |
*
|
|
Borislav Petkov |
b64e2f |
- * Doesn't clobber any registers but does require a stable stack.
|
|
Borislav Petkov |
b64e2f |
+ * While zen_untrain_ret() doesn't clobber anything but requires stack,
|
|
Borislav Petkov |
b64e2f |
+ * entry_ibpb() will clobber AX, CX, DX.
|
|
Borislav Petkov |
b64e2f |
*
|
|
Borislav Petkov |
b64e2f |
* As such, this must be placed after every *SWITCH_TO_KERNEL_CR3 at a point
|
|
Borislav Petkov |
b64e2f |
* where we have a stack but before any RET instruction.
|
|
Borislav Petkov |
b64e2f |
*/
|
|
Borislav Petkov |
b64e2f |
.macro UNTRAIN_RET
|
|
Borislav Petkov |
b64e2f |
#ifdef CONFIG_RETPOLINE
|
|
Borislav Petkov |
b64e2f |
- ALTERNATIVE "", "call zen_untrain_ret", X86_FEATURE_UNRET
|
|
Borislav Petkov |
b64e2f |
+ ALTERNATIVE_2 "", \
|
|
Borislav Petkov |
b64e2f |
+ "call zen_untrain_ret", X86_FEATURE_UNRET, \
|
|
Borislav Petkov |
b64e2f |
+ "call entry_ibpb", X86_FEATURE_ENTRY_IBPB
|
|
Borislav Petkov |
b64e2f |
#endif
|
|
Borislav Petkov |
b64e2f |
.endm
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
@@ -185,6 +188,7 @@
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
extern void __x86_return_thunk(void);
|
|
Borislav Petkov |
b64e2f |
extern void zen_untrain_ret(void);
|
|
Borislav Petkov |
b64e2f |
+extern void entry_ibpb(void);
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
/*
|
|
Borislav Petkov |
b64e2f |
* Inline asm uses the %V modifier which is only in newer GCC
|
|
Borislav Petkov |
b64e2f |
--- a/arch/x86/kernel/cpu/bugs.c
|
|
Borislav Petkov |
b64e2f |
+++ b/arch/x86/kernel/cpu/bugs.c
|
|
Borislav Petkov |
b64e2f |
@@ -878,6 +878,7 @@ static enum spectre_v2_mitigation spectr
|
|
Borislav Petkov |
b64e2f |
enum retbleed_mitigation {
|
|
Borislav Petkov |
b64e2f |
RETBLEED_MITIGATION_NONE,
|
|
Borislav Petkov |
b64e2f |
RETBLEED_MITIGATION_UNRET,
|
|
Borislav Petkov |
b64e2f |
+ RETBLEED_MITIGATION_IBPB,
|
|
Borislav Petkov |
b64e2f |
RETBLEED_MITIGATION_IBRS,
|
|
Borislav Petkov |
b64e2f |
RETBLEED_MITIGATION_EIBRS,
|
|
Borislav Petkov |
b64e2f |
};
|
|
Borislav Petkov |
b64e2f |
@@ -886,11 +887,13 @@ enum retbleed_mitigation_cmd {
|
|
Borislav Petkov |
b64e2f |
RETBLEED_CMD_OFF,
|
|
Borislav Petkov |
b64e2f |
RETBLEED_CMD_AUTO,
|
|
Borislav Petkov |
b64e2f |
RETBLEED_CMD_UNRET,
|
|
Borislav Petkov |
b64e2f |
+ RETBLEED_CMD_IBPB,
|
|
Borislav Petkov |
b64e2f |
};
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
const char * const retbleed_strings[] = {
|
|
Borislav Petkov |
b64e2f |
[RETBLEED_MITIGATION_NONE] = "Vulnerable",
|
|
Borislav Petkov |
b64e2f |
[RETBLEED_MITIGATION_UNRET] = "Mitigation: untrained return thunk",
|
|
Borislav Petkov |
b64e2f |
+ [RETBLEED_MITIGATION_IBPB] = "Mitigation: IBPB",
|
|
Borislav Petkov |
b64e2f |
[RETBLEED_MITIGATION_IBRS] = "Mitigation: IBRS",
|
|
Borislav Petkov |
b64e2f |
[RETBLEED_MITIGATION_EIBRS] = "Mitigation: Enhanced IBRS",
|
|
Borislav Petkov |
b64e2f |
};
|
|
Borislav Petkov |
b64e2f |
@@ -920,6 +923,8 @@ static int __init retbleed_parse_cmdline
|
|
Borislav Petkov |
b64e2f |
retbleed_cmd = RETBLEED_CMD_AUTO;
|
|
Borislav Petkov |
b64e2f |
} else if (!strcmp(str, "unret")) {
|
|
Borislav Petkov |
b64e2f |
retbleed_cmd = RETBLEED_CMD_UNRET;
|
|
Borislav Petkov |
b64e2f |
+ } else if (!strcmp(str, "ibpb")) {
|
|
Borislav Petkov |
b64e2f |
+ retbleed_cmd = RETBLEED_CMD_IBPB;
|
|
Borislav Petkov |
b64e2f |
} else if (!strcmp(str, "nosmt")) {
|
|
Borislav Petkov |
b64e2f |
retbleed_nosmt = true;
|
|
Borislav Petkov |
b64e2f |
} else {
|
|
Borislav Petkov |
b64e2f |
@@ -934,11 +939,13 @@ static int __init retbleed_parse_cmdline
|
|
Borislav Petkov |
b64e2f |
early_param("retbleed", retbleed_parse_cmdline);
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
#define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"
|
|
Borislav Petkov |
b64e2f |
-#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler!\n"
|
|
Borislav Petkov |
b64e2f |
+#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler; falling back to IBPB!\n"
|
|
Borislav Petkov |
b64e2f |
#define RETBLEED_INTEL_MSG "WARNING: Spectre v2 mitigation leaves CPU vulnerable to RETBleed attacks, data leaks possible!\n"
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
static void __init retbleed_select_mitigation(void)
|
|
Borislav Petkov |
b64e2f |
{
|
|
Borislav Petkov |
b64e2f |
+ bool mitigate_smt = false;
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
if (!boot_cpu_has_bug(X86_BUG_RETBLEED))
|
|
Borislav Petkov |
b64e2f |
return;
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
@@ -950,11 +957,21 @@ static void __init retbleed_select_mitig
|
|
Borislav Petkov |
b64e2f |
retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
|
|
Borislav Petkov |
b64e2f |
break;
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
+ case RETBLEED_CMD_IBPB:
|
|
Borislav Petkov |
b64e2f |
+ retbleed_mitigation = RETBLEED_MITIGATION_IBPB;
|
|
Borislav Petkov |
b64e2f |
+ break;
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
case RETBLEED_CMD_AUTO:
|
|
Borislav Petkov |
b64e2f |
default:
|
|
Borislav Petkov |
b64e2f |
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
|
|
Borislav Petkov |
b64e2f |
- boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
|
|
Borislav Petkov |
b64e2f |
- retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
|
|
Borislav Petkov |
b64e2f |
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ if (IS_ENABLED(CONFIG_RETPOLINE) &&
|
|
Borislav Petkov |
b64e2f |
+ IS_ENABLED(CONFIG_CC_HAS_RETURN_THUNK))
|
|
Borislav Petkov |
b64e2f |
+ retbleed_mitigation = RETBLEED_MITIGATION_UNRET;
|
|
Borislav Petkov |
b64e2f |
+ else
|
|
Borislav Petkov |
b64e2f |
+ retbleed_mitigation = RETBLEED_MITIGATION_IBPB;
|
|
Borislav Petkov |
b64e2f |
+ }
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
/*
|
|
Borislav Petkov |
b64e2f |
* The Intel mitigation (IBRS) was already selected in
|
|
Borislav Petkov |
b64e2f |
@@ -970,26 +987,34 @@ static void __init retbleed_select_mitig
|
|
Borislav Petkov |
b64e2f |
if (!IS_ENABLED(CONFIG_RETPOLINE) ||
|
|
Borislav Petkov |
b64e2f |
!IS_ENABLED(CONFIG_CC_HAS_RETURN_THUNK)) {
|
|
Borislav Petkov |
b64e2f |
pr_err(RETBLEED_COMPILER_MSG);
|
|
Borislav Petkov |
b64e2f |
- retbleed_mitigation = RETBLEED_MITIGATION_NONE;
|
|
Borislav Petkov |
b64e2f |
- break;
|
|
Borislav Petkov |
b64e2f |
+ retbleed_mitigation = RETBLEED_MITIGATION_IBPB;
|
|
Borislav Petkov |
b64e2f |
+ goto retbleed_force_ibpb;
|
|
Borislav Petkov |
b64e2f |
}
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
setup_force_cpu_cap(X86_FEATURE_RETHUNK);
|
|
Borislav Petkov |
b64e2f |
setup_force_cpu_cap(X86_FEATURE_UNRET);
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
- if (!boot_cpu_has(X86_FEATURE_STIBP) &&
|
|
Borislav Petkov |
b64e2f |
- (retbleed_nosmt || cpu_mitigations_auto_nosmt()))
|
|
Borislav Petkov |
b64e2f |
- cpu_smt_disable(false);
|
|
Borislav Petkov |
b64e2f |
-
|
|
Borislav Petkov |
b64e2f |
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
|
|
Borislav Petkov |
b64e2f |
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
|
|
Borislav Petkov |
b64e2f |
pr_err(RETBLEED_UNTRAIN_MSG);
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ mitigate_smt = true;
|
|
Borislav Petkov |
b64e2f |
+ break;
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
+ case RETBLEED_MITIGATION_IBPB:
|
|
Borislav Petkov |
b64e2f |
+retbleed_force_ibpb:
|
|
Borislav Petkov |
b64e2f |
+ setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB);
|
|
Borislav Petkov |
b64e2f |
+ mitigate_smt = true;
|
|
Borislav Petkov |
b64e2f |
break;
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
default:
|
|
Borislav Petkov |
b64e2f |
break;
|
|
Borislav Petkov |
b64e2f |
}
|
|
Borislav Petkov |
b64e2f |
|
|
Borislav Petkov |
b64e2f |
+ if (mitigate_smt && !boot_cpu_has(X86_FEATURE_STIBP) &&
|
|
Borislav Petkov |
b64e2f |
+ (retbleed_nosmt || cpu_mitigations_auto_nosmt()))
|
|
Borislav Petkov |
b64e2f |
+ cpu_smt_disable(false);
|
|
Borislav Petkov |
b64e2f |
+
|
|
Borislav Petkov |
b64e2f |
/*
|
|
Borislav Petkov |
b64e2f |
* Let IBRS trump all on Intel without affecting the effects of the
|
|
Borislav Petkov |
b64e2f |
* retbleed= cmdline option.
|
|
Borislav Petkov |
b64e2f |
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
Borislav Petkov |
b64e2f |
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
Borislav Petkov |
b64e2f |
@@ -3986,6 +3986,9 @@
|
|
Borislav Petkov |
b64e2f |
disabling SMT if necessary for
|
|
Borislav Petkov |
b64e2f |
the full mitigation (only on Zen1
|
|
Borislav Petkov |
b64e2f |
and older without STIBP).
|
|
Borislav Petkov |
b64e2f |
+ ibpb - mitigate short speculation windows on
|
|
Borislav Petkov |
b64e2f |
+ basic block boundaries too. Safe, highest
|
|
Borislav Petkov |
b64e2f |
+ perf impact.
|
|
Borislav Petkov |
b64e2f |
unret - force enable untrained return thunks,
|
|
Borislav Petkov |
b64e2f |
only effective on AMD f15h-f17h
|
|
Borislav Petkov |
b64e2f |
based systems.
|