[PATCH v11 7/9] x86/traps: Communicate a LASS violation in #GP message

Sohil Mehta posted 9 patches 1 month, 2 weeks ago
[PATCH v11 7/9] x86/traps: Communicate a LASS violation in #GP message
Posted by Sohil Mehta 1 month, 2 weeks ago
From: Alexander Shishkin <alexander.shishkin@linux.intel.com>

A LASS violation typically results in a #GP. With LASS active, any
invalid access to user memory (including the first page frame) would be
reported as a #GP, instead of a #PF.

Unfortunately, the #GP error messages provide limited information about
the cause of the fault. This could be confusing for kernel developers
and users who are accustomed to the friendly #PF messages.

To make the transition easier, enhance the #GP Oops message to include a
hint about LASS violations. Also, add a special hint for kernel NULL
pointer dereferences to match with the existing #PF message.

Signed-off-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>
---
v11:
 - Improve commit log.

v10:
 - Minor improvement to code comments and hints.
---
 arch/x86/kernel/traps.c | 45 ++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 6b22611e69cc..30d5c690f9a1 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -635,13 +635,23 @@ DEFINE_IDTENTRY(exc_bounds)
 enum kernel_gp_hint {
 	GP_NO_HINT,
 	GP_NON_CANONICAL,
-	GP_CANONICAL
+	GP_CANONICAL,
+	GP_LASS_VIOLATION,
+	GP_NULL_POINTER,
+};
+
+static const char * const kernel_gp_hint_help[] = {
+	[GP_NON_CANONICAL]	= "probably for non-canonical address",
+	[GP_CANONICAL]		= "maybe for address",
+	[GP_LASS_VIOLATION]	= "probably LASS violation for address",
+	[GP_NULL_POINTER]	= "kernel NULL pointer dereference",
 };
 
 /*
  * When an uncaught #GP occurs, try to determine the memory address accessed by
  * the instruction and return that address to the caller. Also, try to figure
- * out whether any part of the access to that address was non-canonical.
+ * out whether any part of the access to that address was non-canonical or
+ * across privilege levels.
  */
 static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
 						 unsigned long *addr)
@@ -663,14 +673,27 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
 		return GP_NO_HINT;
 
 #ifdef CONFIG_X86_64
-	/*
-	 * Check that:
-	 *  - the operand is not in the kernel half
-	 *  - the last byte of the operand is not in the user canonical half
-	 */
-	if (*addr < ~__VIRTUAL_MASK &&
-	    *addr + insn.opnd_bytes - 1 > __VIRTUAL_MASK)
+	/* Operand is in the kernel half */
+	if (*addr >= ~__VIRTUAL_MASK)
+		return GP_CANONICAL;
+
+	/* The last byte of the operand is not in the user canonical half */
+	if (*addr + insn.opnd_bytes - 1 > __VIRTUAL_MASK)
 		return GP_NON_CANONICAL;
+
+	/*
+	 * If LASS is active, a NULL pointer dereference generates a #GP
+	 * instead of a #PF.
+	 */
+	if (*addr < PAGE_SIZE)
+		return GP_NULL_POINTER;
+
+	/*
+	 * Assume that LASS caused the exception, because the address is
+	 * canonical and in the user half.
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_LASS))
+		return GP_LASS_VIOLATION;
 #endif
 
 	return GP_CANONICAL;
@@ -833,9 +856,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
 
 	if (hint != GP_NO_HINT)
 		snprintf(desc, sizeof(desc), GPFSTR ", %s 0x%lx",
-			 (hint == GP_NON_CANONICAL) ? "probably for non-canonical address"
-						    : "maybe for address",
-			 gp_addr);
+			 kernel_gp_hint_help[hint], gp_addr);
 
 	/*
 	 * KASAN is interested only in the non-canonical case, clear it
-- 
2.43.0
Re: [PATCH v11 7/9] x86/traps: Communicate a LASS violation in #GP message
Posted by Dave Hansen 1 month, 1 week ago
On 10/29/25 14:03, Sohil Mehta wrote:
> To make the transition easier, enhance the #GP Oops message to include a
> hint about LASS violations. Also, add a special hint for kernel NULL
> pointer dereferences to match with the existing #PF message.

Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>

This also reminds me... Are there tests for this somewhere? How did you
test all these new messages?
Re: [PATCH v11 7/9] x86/traps: Communicate a LASS violation in #GP message
Posted by Sohil Mehta 1 month, 1 week ago
On 10/31/2025 10:16 AM, Dave Hansen wrote:
> On 10/29/25 14:03, Sohil Mehta wrote:
>> To make the transition easier, enhance the #GP Oops message to include a
>> hint about LASS violations. Also, add a special hint for kernel NULL
>> pointer dereferences to match with the existing #PF message.
> 
> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
> 
> This also reminds me... Are there tests for this somewhere? How did you
> test all these new messages?

I have some very simple kernel modules that access invalid user memory
and generate these faults. I configure the kernel not to panic/reboot.
But, I have been running them manually.

Invalid accesses from the kernel generate:
#PF (without LASS):
  BUG: kernel NULL pointer dereference, address: 0000000000000000
  BUG: unable to handle page fault for address: 0000000000100000

#GP (with LASS):
  Oops: general protection fault, kernel NULL pointer dereference 0x0: 0000
  Oops: general protection fault, probably LASS violation for address
0x100000: 0000

For testing user SIGSEGVs, the Vsyscall tests have been sufficient to
cover all scenarios.

Were you looking for anything specific? I can clean them up and post
them if required.
Re: [PATCH v11 7/9] x86/traps: Communicate a LASS violation in #GP message
Posted by Dave Hansen 1 month, 1 week ago
On 10/31/25 12:59, Sohil Mehta wrote:
> Were you looking for anything specific? I can clean them up and post
> them if required.

It would be nice to have these in-kernel somehow, even if they were
silly debugfs knobs or something. Ira had some tests for PKS that never
went in but you might be able to reuse some of his techniques.
Re: [PATCH v11 7/9] x86/traps: Communicate a LASS violation in #GP message
Posted by Andy Lutomirski 1 month, 1 week ago

On Fri, Oct 31, 2025, at 12:59 PM, Sohil Mehta wrote:
> On 10/31/2025 10:16 AM, Dave Hansen wrote:
>> On 10/29/25 14:03, Sohil Mehta wrote:
>>> To make the transition easier, enhance the #GP Oops message to include a
>>> hint about LASS violations. Also, add a special hint for kernel NULL
>>> pointer dereferences to match with the existing #PF message.
>> 
>> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
>> 
>> This also reminds me... Are there tests for this somewhere? How did you
>> test all these new messages?
>
> I have some very simple kernel modules that access invalid user memory
> and generate these faults. I configure the kernel not to panic/reboot.
> But, I have been running them manually.
>
> Invalid accesses from the kernel generate:
> #PF (without LASS):
>   BUG: kernel NULL pointer dereference, address: 0000000000000000
>   BUG: unable to handle page fault for address: 0000000000100000
>
> #GP (with LASS):
>   Oops: general protection fault, kernel NULL pointer dereference 0x0: 0000
>   Oops: general protection fault, probably LASS violation for address
> 0x100000: 0000
>
> For testing user SIGSEGVs, the Vsyscall tests have been sufficient to
> cover all scenarios.
>
> Were you looking for anything specific? I can clean them up and post
> them if required.

LKDTM is basically meant for this use case. If you can’t provoke a LASS failure from there, maybe just add another failure type?  I would expect that LKDTM can already do a SMAP violation.