From: Dave Hansen <dave.hansen@linux.intel.com>
To: linux-kernel@vger.kernel.org
Cc: Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Edgecombe, Rick P <rick.p.edgecombe@intel.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
the arch/x86 maintainers <x86@kernel.org>,
Kees Cook <kees@kernel.org>,
Pawan Gupta <pawan.kumar.gupta@linux.intel.com>,
Borislav Petkov <bp@alien8.de>, Thomas Gleixner <tglx@kernel.org>,
Dave Hansen <dave.hansen@linux.intel.com>
Subject: [RFC][PATCH 21/24] x86/extable: Update shadow stack entry frame during RIP overwrites
Date: Wed, 21 Oct 2026 12:51:49 -0700 [thread overview]
Message-ID: <20261021195149.174475BA@davehans-spike.ostc.intel.com> (raw)
In-Reply-To: <20261021195120.E61EC737@davehans-spike.ostc.intel.com>
Previous work stashed the entry SSP value on the regular (RSP) stack.
Use that stashed value to locate the FRED entry frame on the shadow
stack. Update the "LIP" value in that frame to match the updated
regs->rip value.
The now-matching values will keep FRED happy during ERETS.
Also include a stub function for non-CET builds.
This "rewrite rip" infrastructure will get used in quite a few other
locations. The extable site is the most critical. Do it first. A
normal kernel won't boot without it because it allows kernel
exceptions to be "stepped over" for "safe" variants like wrmsr_safe().
---
b/arch/x86/include/asm/insn-eval.h | 12 +++++++
b/arch/x86/include/asm/special_insns.h | 7 ++++
b/arch/x86/kernel/cet.c | 54 +++++++++++++++++++++++++++++++++
b/arch/x86/mm/extable.c | 2 -
4 files changed, 74 insertions(+), 1 deletion(-)
diff -puN arch/x86/include/asm/insn-eval.h~fred-entry-ssp-muck arch/x86/include/asm/insn-eval.h
--- a/arch/x86/include/asm/insn-eval.h~fred-entry-ssp-muck 2026-10-21 12:36:43.032890836 -0700
+++ b/arch/x86/include/asm/insn-eval.h 2026-10-21 12:36:43.041890854 -0700
@@ -82,4 +82,16 @@ static inline void insn_assign_reg(unsig
}
}
+#ifdef CONFIG_X86_CET
+void regs_set_return_ip(struct pt_regs *regs, unsigned long ip);
+#else
+static inline void regs_set_return_ip(struct pt_regs *regs, unsigned long ip)
+{
+ /* This is only for changing kernel return addresses: */
+ WARN_ON_ONCE(user_mode(regs));
+
+ regs->ip = ip;
+}
+#endif
+
#endif /* _ASM_X86_INSN_EVAL_H */
diff -puN arch/x86/include/asm/special_insns.h~fred-entry-ssp-muck arch/x86/include/asm/special_insns.h
--- a/arch/x86/include/asm/special_insns.h~fred-entry-ssp-muck 2026-10-21 12:36:43.034890840 -0700
+++ b/arch/x86/include/asm/special_insns.h 2026-10-21 12:36:43.042890856 -0700
@@ -303,6 +303,13 @@ static __always_inline void tile_release
asm volatile(".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0");
}
+static __always_inline void wrss(u64 val, u64 *addr)
+{
+ asm volatile("wrssq %[val], %[addr]"
+ : [addr] "=m" (*addr)
+ : [val] "r" (val));
+}
+
#endif /* __KERNEL__ */
#endif /* _ASM_X86_SPECIAL_INSNS_H */
diff -puN arch/x86/kernel/cet.c~fred-entry-ssp-muck arch/x86/kernel/cet.c
--- a/arch/x86/kernel/cet.c~fred-entry-ssp-muck 2026-10-21 12:36:43.036890844 -0700
+++ b/arch/x86/kernel/cet.c 2026-10-21 12:36:43.042890856 -0700
@@ -4,6 +4,8 @@
#include <asm/bugs.h>
#include <asm/msr.h>
#include <asm/traps.h>
+#include <asm/insn-eval.h>
+#include <asm/special_insns.h>
enum cp_error_code {
CP_EC = (1 << 15) - 1,
@@ -160,3 +162,55 @@ DEFINE_IDTENTRY_ERRORCODE(exc_control_pr
do_unexpected_cp(regs, error_code);
}
}
+
+/*
+ * FRED hardware pushes this frame on to the shadow stack for
+ * kernel=>kernel entry. First (lowest address) in this struct
+ * is the last entry pushed by the hardware.
+ */
+struct fred_shstk_entry_frame {
+ u64 ssef_ssp;
+ u64 ssef_lip;
+ u64 ssef_cs;
+};
+
+/*
+ * The kernel=>kernel entry code pushes SSP on to the entry stack.
+ * This only occurs for kernel=>kernel entry. Not userspace.
+ *
+ * SSP is pushed on to the frame below pt_regs. At the point it is
+ * pushed, it points to a special FRED entry frame.
+ */
+struct fred_kernel_frame {
+ struct fred_shstk_entry_frame *ssef;
+ struct pt_regs regs;
+};
+
+/*
+ * Change the return IP of an event. Use this instead of directly
+ * manipulating regs->ip.
+ *
+ * The hardware saves a special FRED entry frame on to the shadow
+ * stack. It contains the RIP of the interrupted context. ERETS
+ * ensures that this matches regs->ip.
+ *
+ * Update the FRED entry frame in addition to regs->ip.
+ */
+void regs_set_return_ip(struct pt_regs *regs, unsigned long ip)
+{
+ struct fred_shstk_entry_frame *ssef;
+
+ regs->ip = ip;
+
+ if (!cpu_feature_enabled(X86_FEATURE_KERN_SHSTK))
+ return;
+
+ /* Only kernel-mode events save the 'ssef' pointer. */
+ WARN_ON_ONCE(user_mode(regs));
+
+ ssef = container_of(regs, struct fred_kernel_frame, regs)->ssef;
+ if (!ssef)
+ return;
+
+ wrss(ip, &ssef->ssef_lip);
+}
diff -puN arch/x86/mm/extable.c~fred-entry-ssp-muck arch/x86/mm/extable.c
--- a/arch/x86/mm/extable.c~fred-entry-ssp-muck 2026-10-21 12:36:43.039890850 -0700
+++ b/arch/x86/mm/extable.c 2026-10-21 12:36:43.042890856 -0700
@@ -38,7 +38,7 @@ static bool ex_handler_default(const str
if (e->data & EX_FLAG_CLEAR_DX)
regs->dx = 0;
- regs->ip = ex_fixup_addr(e);
+ regs_set_return_ip(regs, ex_fixup_addr(e));
return true;
}
_
next prev parent reply other threads:[~2026-10-21 19:51 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 19:51 [RFC][PATCH 00/24] x86 Kernel Shadow Stacks Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 01/24] kernel/fork: Break out vmap task allocation into helper Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 02/24] kernel/fork: Use sizeof() union instead of TASK_SIZE Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 03/24] kernel/sched: Move thread stack to its own structure Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 04/24] kernel/fork: Allow arch-specific stack initialization Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 05/24] kernel/task: Add shadow stack to thread structure Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 06/24] kernel/task: Add "runtime" check for shadow stack support Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 07/24] kernel/fork: Clear shadow stacks alongside normal stacks Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 08/24] x86/cpu: Add basic x86 kernel shadow stack infrastructure Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 09/24] x86/cea: Refactor "CEA" macros to deal with multiple stacks Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 10/24] x86/cea: Refactor stack mapping macros Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 11/24] x86/mm: Add kernel shadow stack permission macros Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 12/24] x86/cea: Map and use FRED exception shadow stacks Dave Hansen
2026-10-21 21:40 ` Peter Zijlstra
2026-10-21 22:59 ` Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 13/24] x86/task: Grow thread_union for " Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 14/24] x86/mm: Establish shadow stack permissions in thread mapping Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 15/24] x86/task: Hook up arch hook to detect shadow stack enabling Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 16/24] x86/mm: Kill shadow stack page permission warning Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 17/24] x86/task: Context switch the kernel shadow stack register value Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 18/24] kernel/task: Add a helper to get the thread_union Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 19/24] x86/process: Initialize cloned task shadow stack Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 20/24] x86/entry: Stash kernel SSP on FRED entry Dave Hansen
2026-10-21 19:51 ` Dave Hansen [this message]
2026-10-21 19:51 ` [RFC][PATCH 22/24] kernel/task: Add a helper to locate the top of the shadow stack Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 23/24] x86/entry: Populate FRED register for user=>kernel transitions Dave Hansen
2026-10-21 19:51 ` [RFC][PATCH 24/24] [DO NOT MERGE] x86/shstk: Depend out everything incompatible with kernel shadow stacks Dave Hansen
2026-10-21 21:36 ` [RFC][PATCH 00/24] x86 Kernel Shadow Stacks Peter Zijlstra
2026-10-21 21:53 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261021195149.174475BA@davehans-spike.ostc.intel.com \
--to=dave.hansen@linux.intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=bp@alien8.de \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=pawan.kumar.gupta@linux.intel.com \
--cc=peterz@infradead.org \
--cc=rick.p.edgecombe@intel.com \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®