+++ /dev/null
-From dc81e556f2a017d681251ace21bf06c126d5a192 Mon Sep 17 00:00:00 2001
-From: "Xin Li (Intel)" <xin@zytor.com>
-Date: Wed, 13 Nov 2024 09:59:34 -0800
-Subject: x86/fred: Clear WFE in missing-ENDBRANCH #CPs
-
-From: Xin Li (Intel) <xin@zytor.com>
-
-commit dc81e556f2a017d681251ace21bf06c126d5a192 upstream.
-
-An indirect branch instruction sets the CPU indirect branch tracker
-(IBT) into WAIT_FOR_ENDBRANCH (WFE) state and WFE stays asserted
-across the instruction boundary. When the decoder finds an
-inappropriate instruction while WFE is set ENDBR, the CPU raises a #CP
-fault.
-
-For the "kernel IBT no ENDBR" selftest where #CPs are deliberately
-triggered, the WFE state of the interrupted context needs to be
-cleared to let execution continue. Otherwise when the CPU resumes
-from the instruction that just caused the previous #CP, another
-missing-ENDBRANCH #CP is raised and the CPU enters a dead loop.
-
-This is not a problem with IDT because it doesn't preserve WFE and
-IRET doesn't set WFE. But FRED provides space on the entry stack
-(in an expanded CS area) to save and restore the WFE state, thus the
-WFE state is no longer clobbered, so software must clear it.
-
-Clear WFE to avoid dead looping in ibt_clear_fred_wfe() and the
-!ibt_fatal code path when execution is allowed to continue.
-
-Clobbering WFE in any other circumstance is a security-relevant bug.
-
-[ dhansen: changelog rewording ]
-
-Fixes: a5f6c2ace997 ("x86/shstk: Add user control-protection fault handler")
-Signed-off-by: Xin Li (Intel) <xin@zytor.com>
-Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
-Signed-off-by: Ingo Molnar <mingo@kernel.org>
-Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
-Cc: stable@vger.kernel.org
-Link: https://lore.kernel.org/all/20241113175934.3897541-1-xin%40zytor.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- arch/x86/kernel/cet.c | 30 ++++++++++++++++++++++++++++++
- 1 file changed, 30 insertions(+)
-
-diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
-index d2c732a34e5d..303bf74d175b 100644
---- a/arch/x86/kernel/cet.c
-+++ b/arch/x86/kernel/cet.c
-@@ -81,6 +81,34 @@ static void do_user_cp_fault(struct pt_regs *regs, unsigned long error_code)
-
- static __ro_after_init bool ibt_fatal = true;
-
-+/*
-+ * By definition, all missing-ENDBRANCH #CPs are a result of WFE && !ENDBR.
-+ *
-+ * For the kernel IBT no ENDBR selftest where #CPs are deliberately triggered,
-+ * the WFE state of the interrupted context needs to be cleared to let execution
-+ * continue. Otherwise when the CPU resumes from the instruction that just
-+ * caused the previous #CP, another missing-ENDBRANCH #CP is raised and the CPU
-+ * enters a dead loop.
-+ *
-+ * This is not a problem with IDT because it doesn't preserve WFE and IRET doesn't
-+ * set WFE. But FRED provides space on the entry stack (in an expanded CS area)
-+ * to save and restore the WFE state, thus the WFE state is no longer clobbered,
-+ * so software must clear it.
-+ */
-+static void ibt_clear_fred_wfe(struct pt_regs *regs)
-+{
-+ /*
-+ * No need to do any FRED checks.
-+ *
-+ * For IDT event delivery, the high-order 48 bits of CS are pushed
-+ * as 0s into the stack, and later IRET ignores these bits.
-+ *
-+ * For FRED, a test to check if fred_cs.wfe is set would be dropped
-+ * by compilers.
-+ */
-+ regs->fred_cs.wfe = 0;
-+}
-+
- static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
- {
- if ((error_code & CP_EC) != CP_ENDBR) {
-@@ -90,6 +118,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
-
- if (unlikely(regs->ip == (unsigned long)&ibt_selftest_noendbr)) {
- regs->ax = 0;
-+ ibt_clear_fred_wfe(regs);
- return;
- }
-
-@@ -97,6 +126,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
- if (!ibt_fatal) {
- printk(KERN_DEFAULT CUT_HERE);
- __warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
-+ ibt_clear_fred_wfe(regs);
- return;
- }
- BUG();
---
-2.47.1
-