[PATCH v10 14/15] x86/traps: Provide additional hints for a kernel stack segment fault

Sohil Mehta
2025-10-07T06:54:07Z

From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>

Kernel triggered #SS exceptions are rare, and the faulting instruction
may not even have a memory operand. In cases where it does, hints about
the cause of the fault can be useful.

LASS throws a #GP for any violation except for stack register access,
which instead triggers a #SS. Handle a kernel #SS similarly to a #GP and
reuse the address decode logic to provide additional hints, such as a
non-canonical address or an LASS violation.

In case of FRED, before handling #SS as a kernel violation, check if
there's a fixup for the exception. Redirect the #SS due to invalid user
context on ERETU to userspace. See commit 5105e7687ad3 ("x86/fred: Fixup
fault on ERETU by jumping to fred_entrypoint_user") for details.

Originally-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
---
v10:
- Remove the LASS feature check to always provide hints independent of
LASS being enabled.
- Update printk to use KERN_DEFAULT (checkpatch warning).
- Add code comments.
---
arch/x86/kernel/traps.c | 43 +++++++++++++++++++++++++++++++++++------
1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 3ee8a36a4e6a..864c614cddab 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -418,12 +418,6 @@ DEFINE_IDTENTRY_ERRORCODE(exc_segment_not_present)
SIGBUS, 0, NULL);
}

-DEFINE_IDTENTRY_ERRORCODE(exc_stack_segment)
-{
- do_error_trap(regs, error_code, "stack segment", X86_TRAP_SS, SIGBUS,
- 0, NULL);
-}
-
DEFINE_IDTENTRY_ERRORCODE(exc_alignment_check)
{
char *str = "alignment check";
@@ -873,6 +867,43 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
cond_local_irq_disable(regs);
}

+#define SSFSTR "stack segment fault"
+
+DEFINE_IDTENTRY_ERRORCODE(exc_stack_segment)
+{
+ enum kernel_exc_hint hint;
+ unsigned long exc_addr;
+
+ if (user_mode(regs))
+ goto error_trap;
+
+ /*
+ * With FRED enabled, an invalid user context can lead to an #SS
+ * trap on ERETU. Fixup the exception and redirect the fault to
+ * userspace in that case.
+ */
+ if (cpu_feature_enabled(X86_FEATURE_FRED) &&
+ fixup_exception(regs, X86_TRAP_SS, error_code, 0))
+ return;
+
+ if (notify_die(DIE_TRAP, SSFSTR, regs, error_code, X86_TRAP_SS, SIGBUS) == NOTIFY_STOP)
+ return;
+
+ hint = get_kernel_exc_address(regs, &exc_addr);
+ if (hint != EXC_NO_HINT)
+ printk(KERN_DEFAULT SSFSTR ", %s 0x%lx", kernel_exc_hint_help[hint], exc_addr);
+
+ /* KASAN only cares about the non-canonical case, clear it otherwise */
+ if (hint != EXC_NON_CANONICAL)
+ exc_addr = 0;
+
+ die_addr(SSFSTR, regs, error_code, exc_addr);
+ return;
+
+error_trap:
+ do_error_trap(regs, error_code, SSFSTR, X86_TRAP_SS, SIGBUS, 0, NULL);
+}
+
static bool do_int3(struct pt_regs *regs)
{
int res;
--
2.43.0