Blob Blame History Raw
From: Peter Zijlstra <peterz@infradead.org>
Date: Tue, 14 Jun 2022 23:15:53 +0200
Subject: x86/entry: Add kernel IBRS implementation
Git-commit: 2dbb887e875b1de3ca8f40ddf26bcfe55798c609
Patch-mainline: Queued in tip for 5.19
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
References: bsc#1199657 CVE-2022-29900 CVE-2022-29901

Implement Kernel IBRS - currently the only known option to mitigate RSB
underflow speculation issues on Skylake hardware.

Note: since IBRS_ENTER requires fuller context established than
UNTRAIN_RET, it must be placed after it. However, since UNTRAIN_RET
itself implies a RET, it must come after IBRS_ENTER. This means
IBRS_ENTER needs to also move UNTRAIN_RET.

Note 2: KERNEL_IBRS is sub-optimal for XenPV.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>

  [ bp: Use the IBRS implementation which is already present in the SLE kernel ]

Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/entry/entry_64.S        |   14 ++++++++------
 arch/x86/entry/entry_64_compat.S |    8 ++++----
 2 files changed, 12 insertions(+), 10 deletions(-)

--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -3,7 +3,6 @@
  *
  * Copyright 2000-2002 Andi Kleen, SuSE Labs.
  */
-#include "calling.h"
 #include <asm/asm-offsets.h>
 #include <asm/current.h>
 #include <asm/errno.h>
@@ -17,6 +16,8 @@
 #include <linux/linkage.h>
 #include <linux/err.h>
 
+#include "calling.h"
+
 	.section .entry.text, "ax"
 
 /*
@@ -54,8 +55,6 @@ ENTRY(entry_SYSENTER_compat)
 	SWITCH_TO_KERNEL_CR3 scratch_reg=%rsp
 
 	movq	PER_CPU_VAR(cpu_current_top_of_stack), %rsp
-	/* Restrict Indirect Branch Speculation */
-	RESTRICT_IB_SPEC
 
 	/*
 	 * User tracing code (ptrace or signal handlers) might assume that
@@ -108,6 +107,8 @@ ENTRY(entry_SYSENTER_compat)
 	xorl	%r15d, %r15d		/* nospec   r15 */
 	cld
 
+
+	RESTRICT_IB_SPEC
 	UNTRAIN_RET
 
 	/*
@@ -250,7 +251,6 @@ GLOBAL(entry_SYSCALL_compat_after_hwfram
 
 	/* Restrict Indirect Branch Speculation. All registers are saved already */
 	RESTRICT_IB_SPEC_CLOBBER
-
 	UNTRAIN_RET
 
 	/* User mode is traced as though IRQs are on, and SYSENTER
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -215,8 +215,6 @@ ENTRY(entry_SYSCALL_64)
 	 */
 	movq	%rsp, PER_CPU_VAR(rsp_scratch)
 	movq	PER_CPU_VAR(cpu_current_top_of_stack), %rsp
-	/* Restrict Indirect Branch Speculation */
-	RESTRICT_IB_SPEC
 
 	/* Construct struct pt_regs on stack */
 	pushq	$__USER_DS			/* pt_regs->ss */
@@ -234,6 +232,9 @@ GLOBAL(entry_SYSCALL_64_after_hwframe)
 	/* IRQs are off. */
 	movq	%rsp, %rdi
 
+	/* Restrict Indirect Branch Speculation */
+	RESTRICT_IB_SPEC
+
 	UNTRAIN_RET
 
 	call	do_syscall_64		/* returns with IRQs disabled */
@@ -1192,6 +1193,7 @@ ENTRY(paranoid_entry)
 	SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
 	/* Restrict Indirect Branch speculation */
 	RESTRICT_IB_SPEC_SAVE_AND_CLOBBER save_reg=%r13d
+	UNTRAIN_RET
 	/*
 	 * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an
 	 * unconditional CR3 write, even in the PTI case.  So do an lfence
@@ -1420,10 +1422,6 @@ ENTRY(nmi)
 	movq	%rsp, %rdx
 	movq	PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
-	/* Restrict Indirect Branch Speculation */
-	RESTRICT_IB_SPEC
-	UNTRAIN_RET
-
 	UNWIND_HINT_IRET_REGS base=%rdx offset=8
 	pushq	5*8(%rdx)	/* pt_regs->ss */
 	pushq	4*8(%rdx)	/* pt_regs->rsp */
@@ -1435,6 +1433,10 @@ ENTRY(nmi)
 	PUSH_AND_CLEAR_REGS rdx=(%rdx)
 	ENCODE_FRAME_POINTER
 
+	/* Restrict Indirect Branch Speculation */
+	RESTRICT_IB_SPEC
+	UNTRAIN_RET
+
 	/*
 	 * At this point we no longer need to worry about stack damage
 	 * due to nesting -- we're on the normal thread stack and we're