mirror of https://github.com/torvalds/linux.git
x86/traps: Communicate a LASS violation in #GP message
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> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com> Link: https://patch.msgid.link/20251118182911.2983253-7-sohil.mehta%40intel.com
This commit is contained in:
parent
731d43750c
commit
42fea0a3a7
|
|
@ -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,28 @@ 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;
|
||||
|
||||
/*
|
||||
* A NULL pointer dereference usually causes a #PF. However, it
|
||||
* can result in a #GP when LASS is active. Provide the same
|
||||
* hint in the rare case that the condition is hit without LASS.
|
||||
*/
|
||||
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 +857,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
|
||||
|
|
|
|||
Loading…
Reference in New Issue