* [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support
@ 2025-11-13 22:41 Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 1/8] x86/cpufeatures: Enumerate the LASS feature bits Sohil Mehta
` (7 more replies)
0 siblings, 8 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:41 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
This series continues the simplified trimmed-down approach from v11.
Overall, I think the patches are ready for merging.
Changes in v12
--------------
- Dropped the EFI toggle during SetVirtualAddressMap().
- Disable LASS if the EFI support is needed. (patch 8)
- Use lass_stac()/lass_clac() naming for AC bit toggling. (patch 4)
Unsupported features (for now)
------------------------------
- EFI support: EFI needs slightly more work because some boot services
memory could be accessed even after ExitBootServices(). Similarly,
some runtime services might cling to using physical addresses even
after SetVirtualAddressMap().
In future, we need to defer LASS enabling until EFI has completely
finished entering virtual mode (including efi_free_boot_services()).
Also, LASS would need to be temporarily disabled while switching to
efi_mm to avoid potential faults on runtime accesses to the 1:1
mapped regions.
Bits that were dropped earlier (v11):
- Vsyscall emulation: Legacy vsyscalls aren't required in newer
environments. For now, LASS is only enabled when vsyscall emulation
support is absent. In future, we would reuse the existing emulation
mechanism for #PF in the #GP handler with the vsyscall XONLY mode.
- CR pinning: Pinning CR4.LASS isn't strictly necessary because it
only mitigates speculative attacks beyond SMAP. The only benefit
would be to get a warning if LASS is accidentally disabled.
- #SS LASS hints: Kernel stack segment faults are very rare. Also, in
most cases, the faulting instruction is unlikely to have a memory
operand. There isn't any compelling reason to add LASS hints for
these right now.
Dropping the non-essential pieces reduces the patch count and code
changes by ~50%. Though this limits the initial LASS deployment, it
makes merging and reviews considerably easier. We have a path forward
for vsyscalls and EFI [6]. I plan to pursue that immediately after the
base series has merged.
See the sections below or the discussions in v11 for more information.
https://lore.kernel.org/lkml/20251029210310.1155449-1-sohil.mehta@intel.com/
Patch structure
---------------
Patch 1-2: Enumerate LASS and its dependency on SMAP
Patch 3-4: Update text poking
Patch 5: Update kexec flow
Patch 6-7: Expecting a #GP instead of #PF
Patch 8: Enable LASS (without EFI and vsyscall)
Please consider applying the series or providing acks if you have been
tracking the patches.
Testing
-------
The LKDTM suite tests a variety of kernel exception paths (such as NULL
dereference or invalid user access). They can be triggered directly via
debugfs as well. The same tests can be used for generating LASS
exceptions.
Also, the vsyscall tests have been updated and cover generating user
SIGSEGVs due to LASS.
Background
----------
Linear Address Space Separation (LASS) is a security feature [1] that
works prior to page-walks to prevent a class of side-channel attacks
that rely on speculative access across the user/kernel boundary.
Privilege mode based access protection already exists today with paging
and features such as SMEP and SMAP. However, to enforce these
protections, the processor must traverse the paging structures in
memory. An attacker can use timing information resulting from this
traversal to determine details about the paging structures, and to
determine the layout of the kernel memory.
The LASS mechanism provides the same mode-based protections as paging,
but without traversing the paging structures. Because the protections
enforced by LASS are applied before paging, an attacker will not be able
to derive timing information from the various caching structures such as
the TLBs, mid-level caches, page walkers, data caches, etc. LASS can
prevent probing using double page faults, TLB flush and reload, and
software prefetch instructions. See [2], [3], and [4] for research
on the related attack vectors.
Though LASS was developed in response to Meltdown, in hindsight, it
alone could have mitigated Meltdown had it been available. In addition,
LASS prevents an attack vector targeting Linear Address Masking (LAM)
described in the Spectre LAM (SLAM) whitepaper [5].
LASS enforcement relies on the typical kernel implementation dividing
the 64-bit virtual address space into two halves:
Addr[63]=0 -> User address space
Addr[63]=1 -> Kernel address space
Any data access or code execution across address spaces typically
results in a #GP, with an #SS generated in some rare cases.
Kernel accesses
---------------
When there are valid reasons for the kernel to access memory in the user
half, it can temporarily suspend LASS data access enforcement by
toggling the RFLAGS.AC bit. Most of these cases are already covered
today through the stac()/clac() pairs, which avoid SMAP violations.
However, there are kernel usages, such as text poking, that access
mappings (!_PAGE_USER) in the lower half of the address space.
LASS-specific AC bit toggling is added for these cases.
In cases where instruction fetches are done from a lower address,
toggling the AC bit is not sufficient as it only manages kernel data
accesses. So, CR4.LASS is modified during kexec relocate_kernel() to
avoid LASS violations.
Some EFI runtime and boot services may rely on 1:1 mappings in the lower
half during early boot and even after SetVirtualAddressMap(). For
example, efi_check_for_embedded_firmwares() accesses boot time data
after SVAM. For now, LASS is disabled if EFI support is compiled in.
In future, to avoid tripping LASS, the initial CR4 programming would
need to be delayed. Ideally we would delay LASS enabling until userspace
comes up. Also, we would likely toggle CR4.LASS every time while
switching to efi_mm to avoid potential faults on stray runtime accesses.
Userspace isn't mapped in efi_mm so the impact of this should be
limited. Even though the runtime accesses might be to data objects, we
can't rely on EFI to preserve the AC bit.
Exception handling
------------------
With LASS enabled, NULL pointer dereferences generate a #GP instead of a
#PF. Due to the limited error information available during #GP, some of
the helpful hints would no longer be printed. The patches enhance the
#GP address decoding logic to identify LASS violations and NULL pointer
exceptions.
For example, two invalid userspace accesses would now 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
Similar debug hints can be added for the #SS handling as well. But
running into a #SS is very rare and the complexity isn't worth it.
Userspace accesses
------------------
When LASS is enabled, userspace attempts to access any kernel address
generate a #GP instead of a #PF. A SIGSEGV is delivered to userspace in
both cases. However, the exception address present in the siginfo
structure for a #PF is absent for a #GP. This is a minor and expectedly
inconsequential change for userspace.
Legacy vsyscalls
----------------
Legacy vsyscall functions are located in the address range
0xffffffffff600000 - 0xffffffffff601000. Prior to LASS, accesses to the
vsyscall page would generate a #PF, and they would be emulated in the
#PF handler. Extending the emulation support to the #GP handler needs
complex instruction decoding and some refactoring.
Modern environments do not require legacy vsyscalls. To avoid breaking
user applications, LASS is disabled if vsyscall emulation support is
compiled in.
In case of XONLY (execute only) mode, the faulting address is readily
available in the RIP which should make it easier to reuse the #PF
emulation logic. OTOH, supporting the vsyscall full EMULATION mode
should likely be avoided because it is deprecated and would need complex
instruction decoding.
Links
-----
[1]: "Linear-Address Pre-Processing", Intel SDM (June 2025), Vol 3, Chapter 4.
[2]: "Practical Timing Side Channel Attacks against Kernel Space ASLR", https://www.ieee-security.org/TC/SP2013/papers/4977a191.pdf
[3]: "Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR", http://doi.acm.org/10.1145/2976749.2978356
[4]: "Harmful prefetch on Intel", https://ioactive.com/harmful-prefetch-on-intel/ (H/T Anders)
[5]: "Spectre LAM", https://download.vusec.net/papers/slam_sp24.pdf
[6]: https://lore.kernel.org/lkml/bbb68600-eea9-45d8-90d1-bc4619186a4d@intel.com/
Alexander Shishkin (1):
x86/traps: Communicate a LASS violation in #GP message
Peter Zijlstra (Intel) (1):
x86/asm: Introduce inline memcpy and memset
Sohil Mehta (6):
x86/cpufeatures: Enumerate the LASS feature bits
x86/cpu: Add an LASS dependency on SMAP
x86/alternatives: Disable LASS when patching kernel code
x86/kexec: Disable LASS during relocate kernel
selftests/x86: Update the negative vsyscall tests to expect a #GP
x86/cpu: Enable LASS during CPU initialization
arch/x86/Kconfig.cpufeatures | 4 ++
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/smap.h | 41 ++++++++++++++++++-
arch/x86/include/asm/string.h | 26 ++++++++++++
arch/x86/include/uapi/asm/processor-flags.h | 2 +
arch/x86/kernel/alternative.c | 18 ++++++++-
arch/x86/kernel/cpu/common.c | 24 ++++++++++-
arch/x86/kernel/cpu/cpuid-deps.c | 1 +
arch/x86/kernel/relocate_kernel_64.S | 7 +++-
arch/x86/kernel/traps.c | 45 +++++++++++++++------
tools/testing/selftests/x86/test_vsyscall.c | 21 +++++-----
11 files changed, 162 insertions(+), 28 deletions(-)
base-commit: e9a6fb0bcdd7609be6969112f3fbfcce3b1d4a7c
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v12 1/8] x86/cpufeatures: Enumerate the LASS feature bits
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
@ 2025-11-13 22:41 ` Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 2/8] x86/cpu: Add an LASS dependency on SMAP Sohil Mehta
` (6 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:41 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
Linear Address Space Separation (LASS) is a security feature that
mitigates a class of side-channel attacks relying on speculative access
across the user/kernel boundary.
Privilege mode based access protection already exists today with paging
and features such as SMEP and SMAP. However, to enforce these
protections, the processor must traverse the paging structures in
memory. An attacker can use timing information resulting from this
traversal to determine details about the paging structures, and to
determine the layout of the kernel memory.
LASS provides the same mode-based protections as paging but without
traversing the paging structures. Because the protections are enforced
prior to page-walks, an attacker will not be able to derive paging-based
timing information from the various caching structures such as the TLBs,
mid-level caches, page walker, data caches, etc.
LASS enforcement relies on the kernel implementation to divide the
64-bit virtual address space into two halves:
Addr[63]=0 -> User address space
Addr[63]=1 -> Kernel address space
Any data access or code execution across address spaces typically
results in a #GP fault, with an #SS generated in some rare cases. The
LASS enforcement for kernel data accesses is dependent on CR4.SMAP being
set. The enforcement can be disabled by toggling the RFLAGS.AC bit
similar to SMAP.
Define the CPU feature bits to enumerate LASS. Also, disable the feature
at compile time on 32-bit kernels. Use a direct dependency on X86_32
(instead of !X86_64) to make it easier to combine with similar 32-bit
specific dependencies in the future.
LASS mitigates a class of side-channel speculative attacks, such as
Spectre LAM, described in the paper, "Leaky Address Masking: Exploiting
Unmasked Spectre Gadgets with Noncanonical Address Translation".
Add the "lass" flag to /proc/cpuinfo to indicate that the feature is
supported by hardware and enabled by the kernel. This allows userspace
to determine if the system is secure against such attacks.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Xin Li (Intel) <xin@zytor.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Pick up review tag.
v11:
- Split the SMAP dependency hunk into a separate patch (patch 2).
- Improve commit message.
---
arch/x86/Kconfig.cpufeatures | 4 ++++
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/uapi/asm/processor-flags.h | 2 ++
3 files changed, 7 insertions(+)
diff --git a/arch/x86/Kconfig.cpufeatures b/arch/x86/Kconfig.cpufeatures
index 250c10627ab3..733d5aff2456 100644
--- a/arch/x86/Kconfig.cpufeatures
+++ b/arch/x86/Kconfig.cpufeatures
@@ -124,6 +124,10 @@ config X86_DISABLED_FEATURE_PCID
def_bool y
depends on !X86_64
+config X86_DISABLED_FEATURE_LASS
+ def_bool y
+ depends on X86_32
+
config X86_DISABLED_FEATURE_PKU
def_bool y
depends on !X86_INTEL_MEMORY_PROTECTION_KEYS
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 4091a776e37a..8d872eb08c16 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -314,6 +314,7 @@
#define X86_FEATURE_SM4 (12*32+ 2) /* SM4 instructions */
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* "avx_vnni" AVX VNNI instructions */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* "avx512_bf16" AVX512 BFLOAT16 instructions */
+#define X86_FEATURE_LASS (12*32+ 6) /* "lass" Linear Address Space Separation */
#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* CMPccXADD instructions */
#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* Intel Architectural PerfMon Extension */
#define X86_FEATURE_FZRM (12*32+10) /* Fast zero-length REP MOVSB */
diff --git a/arch/x86/include/uapi/asm/processor-flags.h b/arch/x86/include/uapi/asm/processor-flags.h
index f1a4adc78272..81d0c8bf1137 100644
--- a/arch/x86/include/uapi/asm/processor-flags.h
+++ b/arch/x86/include/uapi/asm/processor-flags.h
@@ -136,6 +136,8 @@
#define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT)
#define X86_CR4_CET_BIT 23 /* enable Control-flow Enforcement Technology */
#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT)
+#define X86_CR4_LASS_BIT 27 /* enable Linear Address Space Separation support */
+#define X86_CR4_LASS _BITUL(X86_CR4_LASS_BIT)
#define X86_CR4_LAM_SUP_BIT 28 /* LAM for supervisor pointers */
#define X86_CR4_LAM_SUP _BITUL(X86_CR4_LAM_SUP_BIT)
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 2/8] x86/cpu: Add an LASS dependency on SMAP
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 1/8] x86/cpufeatures: Enumerate the LASS feature bits Sohil Mehta
@ 2025-11-13 22:41 ` Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 3/8] x86/asm: Introduce inline memcpy and memset Sohil Mehta
` (5 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:41 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
With LASS enabled, any kernel data access to userspace typically results
in a #GP, or a #SS in some stack-related cases. When the kernel needs to
access user memory, it can suspend LASS enforcement by toggling the
RFLAGS.AC bit. Most of these cases are already covered by the
stac()/clac() pairs used to avoid SMAP violations.
Even though LASS could potentially be enabled independently, it would be
very painful without SMAP and the related stac()/clac() calls. There is
no reason to support such a configuration because all future hardware
with LASS is expected to have SMAP as well. Also, the STAC/CLAC
instructions are architected to:
#UD - If CPUID.(EAX=07H, ECX=0H):EBX.SMAP[bit 20] = 0.
So, make LASS depend on SMAP to conveniently reuse the existing AC bit
toggling already in place.
Note: Additional STAC/CLAC would still be needed for accesses such as
text poking which are not flagged by SMAP. This is because such mappings
are in the lower half but do not have the _PAGE_USER bit set which SMAP
uses for enforcement.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Pick up review tag.
v11:
- New patch (split from patch 1).
---
arch/x86/kernel/cpu/cpuid-deps.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 46efcbd6afa4..98d0cdd82574 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -89,6 +89,7 @@ static const struct cpuid_dep cpuid_deps[] = {
{ X86_FEATURE_SHSTK, X86_FEATURE_XSAVES },
{ X86_FEATURE_FRED, X86_FEATURE_LKGS },
{ X86_FEATURE_SPEC_CTRL_SSBD, X86_FEATURE_SPEC_CTRL },
+ { X86_FEATURE_LASS, X86_FEATURE_SMAP },
{}
};
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 3/8] x86/asm: Introduce inline memcpy and memset
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 1/8] x86/cpufeatures: Enumerate the LASS feature bits Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 2/8] x86/cpu: Add an LASS dependency on SMAP Sohil Mehta
@ 2025-11-13 22:41 ` Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 4/8] x86/alternatives: Disable LASS when patching kernel code Sohil Mehta
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:41 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
From: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Provide inline memcpy and memset functions that can be used instead of
the GCC builtins when necessary. The immediate use case is for the text
poking functions to avoid the standard memcpy()/memset() calls because
objtool complains about such dynamic calls within an AC=1 region. See
tools/objtool/Documentation/objtool.txt, warning #9, regarding function
calls with UACCESS enabled.
Some user copy functions such as copy_user_generic() and __clear_user()
have similar rep_{movs,stos} usages. But, those are highly specialized
and hard to combine or reuse for other things. Define these new helpers
for all other usages that need a completely unoptimized, strictly inline
version of memcpy() or memset().
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Pick up review tag.
v11:
- Improve commit log.
---
arch/x86/include/asm/string.h | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h
index c3c2c1914d65..9cb5aae7fba9 100644
--- a/arch/x86/include/asm/string.h
+++ b/arch/x86/include/asm/string.h
@@ -1,6 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_STRING_H
+#define _ASM_X86_STRING_H
+
#ifdef CONFIG_X86_32
# include <asm/string_32.h>
#else
# include <asm/string_64.h>
#endif
+
+static __always_inline void *__inline_memcpy(void *to, const void *from, size_t len)
+{
+ void *ret = to;
+
+ asm volatile("rep movsb"
+ : "+D" (to), "+S" (from), "+c" (len)
+ : : "memory");
+ return ret;
+}
+
+static __always_inline void *__inline_memset(void *s, int v, size_t n)
+{
+ void *ret = s;
+
+ asm volatile("rep stosb"
+ : "+D" (s), "+c" (n)
+ : "a" ((uint8_t)v)
+ : "memory");
+ return ret;
+}
+
+#endif /* _ASM_X86_STRING_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 4/8] x86/alternatives: Disable LASS when patching kernel code
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
` (2 preceding siblings ...)
2025-11-13 22:41 ` [PATCH v12 3/8] x86/asm: Introduce inline memcpy and memset Sohil Mehta
@ 2025-11-13 22:42 ` Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 5/8] x86/kexec: Disable LASS during relocate kernel Sohil Mehta
` (3 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:42 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
For patching, the kernel initializes a temporary mm area in the lower
half of the address range. LASS blocks these accesses because its
enforcement relies on bit 63 of the virtual address as opposed to SMAP
which depends on the _PAGE_BIT_USER bit in the page table. Disable LASS
enforcement by toggling the RFLAGS.AC bit during patching to avoid
triggering a #GP fault.
Introduce LASS-specific STAC/CLAC helpers to set the AC bit only on
platforms that need it. Name the wrappers as lass_stac()/_clac() instead
of lass_disable()/_enable() because they only control the kernel data
access enforcement. The entire LASS mechanism (including instruction
fetch enforcement) is controlled by the CR4.LASS bit.
Describe the usage of the new helpers in comparison to the ones used for
SMAP. Also, add comments to explain when the existing stac()/clac()
should be used. While at it, move the duplicated "barrier" comment to
the same block.
The Text poking functions use standard memcpy()/memset() while patching
kernel code. However, objtool complains about calling such dynamic
functions within an AC=1 region. See warning #9, regarding function
calls with UACCESS enabled, in tools/objtool/Documentation/objtool.txt.
To pacify objtool, one option is to add memcpy() and memset() to the
list of allowed-functions. However, that would provide a blanket
exemption for all usages of memcpy() and memset(). Instead, replace the
standard calls in the text poking functions with their unoptimized,
always-inlined versions. Considering that patching is usually small,
there is no performance impact expected.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Revert to lass_clac()/lass_stac() naming.
- Pick up review tag.
v11:
- Use lass_enable()/lass_disable() naming.
- Improve commit log and code comments.
---
arch/x86/include/asm/smap.h | 41 +++++++++++++++++++++++++++++++++--
arch/x86/kernel/alternative.c | 18 +++++++++++++--
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h
index 4f84d421d1cf..20a3baae9568 100644
--- a/arch/x86/include/asm/smap.h
+++ b/arch/x86/include/asm/smap.h
@@ -23,18 +23,55 @@
#else /* __ASSEMBLER__ */
+/*
+ * The CLAC/STAC instructions toggle the enforcement of
+ * X86_FEATURE_SMAP along with X86_FEATURE_LASS.
+ *
+ * SMAP enforcement is based on the _PAGE_BIT_USER bit in the page
+ * tables. The kernel is not allowed to touch pages with that bit set
+ * unless the AC bit is set.
+ *
+ * Use stac()/clac() when accessing userspace (_PAGE_USER) mappings,
+ * regardless of location.
+ *
+ * Note: a barrier is implicit in alternative().
+ */
+
static __always_inline void clac(void)
{
- /* Note: a barrier is implicit in alternative() */
alternative("", "clac", X86_FEATURE_SMAP);
}
static __always_inline void stac(void)
{
- /* Note: a barrier is implicit in alternative() */
alternative("", "stac", X86_FEATURE_SMAP);
}
+/*
+ * LASS enforcement is based on bit 63 of the virtual address. The
+ * kernel is not allowed to touch memory in the lower half of the
+ * virtual address space.
+ *
+ * Use lass_stac()/lass_clac() to toggle the AC bit for kernel data
+ * accesses (!_PAGE_USER) that are blocked by LASS, but not by SMAP.
+ *
+ * Even with the AC bit set, LASS will continue to block instruction
+ * fetches from the user half of the address space. To allow those,
+ * clear CR4.LASS to disable the LASS mechanism entirely.
+ *
+ * Note: a barrier is implicit in alternative().
+ */
+
+static __always_inline void lass_clac(void)
+{
+ alternative("", "clac", X86_FEATURE_LASS);
+}
+
+static __always_inline void lass_stac(void)
+{
+ alternative("", "stac", X86_FEATURE_LASS);
+}
+
static __always_inline unsigned long smap_save(void)
{
unsigned long flags;
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 8ee5ff547357..5b09f89070f0 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -2469,16 +2469,30 @@ void __init_or_module text_poke_early(void *addr, const void *opcode,
__ro_after_init struct mm_struct *text_poke_mm;
__ro_after_init unsigned long text_poke_mm_addr;
+/*
+ * Text poking creates and uses a mapping in the lower half of the
+ * address space. Relax LASS enforcement when accessing the poking
+ * address.
+ *
+ * objtool enforces a strict policy of "no function calls within AC=1
+ * regions". Adhere to the policy by using inline versions of
+ * memcpy()/memset() that will never result in a function call.
+ */
+
static void text_poke_memcpy(void *dst, const void *src, size_t len)
{
- memcpy(dst, src, len);
+ lass_stac();
+ __inline_memcpy(dst, src, len);
+ lass_clac();
}
static void text_poke_memset(void *dst, const void *src, size_t len)
{
int c = *(const int *)src;
- memset(dst, c, len);
+ lass_stac();
+ __inline_memset(dst, c, len);
+ lass_clac();
}
typedef void text_poke_f(void *dst, const void *src, size_t len);
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 5/8] x86/kexec: Disable LASS during relocate kernel
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
` (3 preceding siblings ...)
2025-11-13 22:42 ` [PATCH v12 4/8] x86/alternatives: Disable LASS when patching kernel code Sohil Mehta
@ 2025-11-13 22:42 ` Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message Sohil Mehta
` (2 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:42 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
The relocate kernel mechanism uses an identity mapping to copy the new
kernel, which leads to a LASS violation when executing from a low
address.
LASS must be disabled after the original CR4 value is saved because
kexec paths that preserve context need to restore CR4.LASS. But,
disabling it along with CET during identity_mapped() is too late. So,
disable LASS immediately after saving CR4, along with PGE, and before
jumping to the identity-mapped page.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Pick up review tag.
v11:
- Improve commit message.
---
arch/x86/kernel/relocate_kernel_64.S | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index 11e20bb13aca..4ffba68dc57b 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -95,9 +95,12 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
/* Leave CR4 in %r13 to enable the right paging mode later. */
movq %cr4, %r13
- /* Disable global pages immediately to ensure this mapping is RWX */
+ /*
+ * Disable global pages immediately to ensure this mapping is RWX.
+ * Disable LASS before jumping to the identity mapped page.
+ */
movq %r13, %r12
- andq $~(X86_CR4_PGE), %r12
+ andq $~(X86_CR4_PGE | X86_CR4_LASS), %r12
movq %r12, %cr4
/* Save %rsp and CRs. */
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
` (4 preceding siblings ...)
2025-11-13 22:42 ` [PATCH v12 5/8] x86/kexec: Disable LASS during relocate kernel Sohil Mehta
@ 2025-11-13 22:42 ` Sohil Mehta
2025-11-17 14:48 ` Borislav Petkov
2025-11-13 22:42 ` [PATCH v12 7/8] selftests/x86: Update the negative vsyscall tests to expect a #GP Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 8/8] x86/cpu: Enable LASS during CPU initialization Sohil Mehta
7 siblings, 1 reply; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:42 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
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>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Pick up review tag.
v11:
- Improve commit log.
---
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
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 7/8] selftests/x86: Update the negative vsyscall tests to expect a #GP
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
` (5 preceding siblings ...)
2025-11-13 22:42 ` [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message Sohil Mehta
@ 2025-11-13 22:42 ` Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 8/8] x86/cpu: Enable LASS during CPU initialization Sohil Mehta
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:42 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
Some of the vsyscall selftests expect a #PF when vsyscalls are disabled.
However, with LASS enabled, an invalid access results in a SIGSEGV due
to a #GP instead of a #PF. One such negative test fails because it is
expecting X86_PF_INSTR to be set.
Update the failing test to expect either a #GP or a #PF. Also, update
the printed messages to show the trap number (denoting the type of
fault) instead of assuming a #PF.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
v12:
- Pick up review tag.
v11:
- New patch (Fixes a vsyscall selftest failure)
---
tools/testing/selftests/x86/test_vsyscall.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c
index 05e1e6774fba..918eaec8bfbe 100644
--- a/tools/testing/selftests/x86/test_vsyscall.c
+++ b/tools/testing/selftests/x86/test_vsyscall.c
@@ -308,12 +308,13 @@ static void test_getcpu(int cpu)
#ifdef __x86_64__
static jmp_buf jmpbuf;
-static volatile unsigned long segv_err;
+static volatile unsigned long segv_err, segv_trapno;
static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
{
ucontext_t *ctx = (ucontext_t *)ctx_void;
+ segv_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
segv_err = ctx->uc_mcontext.gregs[REG_ERR];
siglongjmp(jmpbuf, 1);
}
@@ -336,7 +337,8 @@ static void test_vsys_r(void)
else if (can_read)
ksft_test_result_pass("We have read access\n");
else
- ksft_test_result_pass("We do not have read access: #PF(0x%lx)\n", segv_err);
+ ksft_test_result_pass("We do not have read access (trap=%ld, error=0x%lx)\n",
+ segv_trapno, segv_err);
}
static void test_vsys_x(void)
@@ -347,7 +349,7 @@ static void test_vsys_x(void)
return;
}
- ksft_print_msg("Make sure that vsyscalls really page fault\n");
+ ksft_print_msg("Make sure that vsyscalls really cause a fault\n");
bool can_exec;
if (sigsetjmp(jmpbuf, 1) == 0) {
@@ -358,13 +360,14 @@ static void test_vsys_x(void)
}
if (can_exec)
- ksft_test_result_fail("Executing the vsyscall did not page fault\n");
- else if (segv_err & (1 << 4)) /* INSTR */
- ksft_test_result_pass("Executing the vsyscall page failed: #PF(0x%lx)\n",
- segv_err);
+ ksft_test_result_fail("Executing the vsyscall did not fault\n");
+ /* #GP or #PF (with X86_PF_INSTR) */
+ else if ((segv_trapno == 13) || ((segv_trapno == 14) && (segv_err & (1 << 4))))
+ ksft_test_result_pass("Executing the vsyscall page failed (trap=%ld, error=0x%lx)\n",
+ segv_trapno, segv_err);
else
- ksft_test_result_fail("Execution failed with the wrong error: #PF(0x%lx)\n",
- segv_err);
+ ksft_test_result_fail("Execution failed with the wrong error (trap=%ld, error=0x%lx)\n",
+ segv_trapno, segv_err);
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v12 8/8] x86/cpu: Enable LASS during CPU initialization
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
` (6 preceding siblings ...)
2025-11-13 22:42 ` [PATCH v12 7/8] selftests/x86: Update the negative vsyscall tests to expect a #GP Sohil Mehta
@ 2025-11-13 22:42 ` Sohil Mehta
7 siblings, 0 replies; 14+ messages in thread
From: Sohil Mehta @ 2025-11-13 22:42 UTC (permalink / raw)
To: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Borislav Petkov
Cc: Jonathan Corbet, H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf,
Peter Zijlstra, Ard Biesheuvel, Kirill A . Shutemov, Sohil Mehta,
Xin Li, David Woodhouse, Sean Christopherson, Rick Edgecombe,
Vegard Nossum, Andrew Cooper, Randy Dunlap, Geert Uytterhoeven,
Kees Cook, Tony Luck, Alexander Shishkin, linux-doc, linux-kernel,
linux-efi
Linear Address Space Separation (LASS) mitigates a class of side-channel
attacks that rely on speculative access across the user/kernel boundary.
Enable LASS along with similar security features if the platform
supports it.
While at it, remove the comment above the SMAP/SMEP/UMIP/LASS setup
instead of updating it, as the whole sequence is quite self-explanatory.
Some EFI runtime and boot services may rely on 1:1 mappings in the lower
half during early boot and even after SetVirtualAddressMap(). To avoid
tripping LASS, the initial CR4 programming would need to be delayed
until EFI has completely finished entering virtual mode (including
efi_free_boot_services()). Also, LASS would need to be temporarily
disabled while switching to efi_mm to avoid potential faults on stray
runtime accesses.
Similarly, legacy vsyscall page accesses are flagged by LASS resulting
in a #GP (instead of a #PF). Without LASS, the #PF handler emulates the
accesses and returns the appropriate values. Equivalent emulation
support is required in the #GP handler with LASS enabled. In case of
vsyscall XONLY (execute only) mode, the faulting address is readily
available in the RIP which would make it easier to reuse the #PF
emulation logic.
For now, keep it simple and disable LASS if either of those are compiled
in. Though not ideal, this makes it easier to start testing LASS support
in some environments. In future, LASS support can easily be expanded to
support EFI and legacy vsyscalls.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
---
For reference, here are the relevant discussion links regarding EFI and
legacy vsyscalls:
https://lore.kernel.org/lkml/CAMj1kXGyTo=4Va1PevMQyCauEKSutfSPo6je0Ps09TabhTe4zQ@mail.gmail.com/
https://lore.kernel.org/lkml/bbb68600-eea9-45d8-90d1-bc4619186a4d@intel.com/
https://lore.kernel.org/lkml/CAMj1kXFQaGaz37MNKXXjhUKy_mP-5teCDj80-hjUPHw4x+TKrA@mail.gmail.com/
https://lore.kernel.org/lkml/d1b5698e-94ab-45a2-a472-4488895d55bb@intel.com/
v12:
- Disable LASS when EFI support is compiled in.
- Pick up review tag.
v11:
- Disable LASS if vsyscall emulation support is compiled in.
- Drop Rick's review tag because of the new changes.
---
arch/x86/kernel/cpu/common.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 02d97834a1d4..8afcbfd48a8a 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -405,6 +405,28 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
cr4_clear_bits(X86_CR4_UMIP);
}
+static __always_inline void setup_lass(struct cpuinfo_x86 *c)
+{
+ if (!cpu_feature_enabled(X86_FEATURE_LASS))
+ return;
+
+ /*
+ * Legacy vsyscall page access causes a #GP when LASS is active.
+ * Disable LASS because the #GP handler doesn't support vsyscall
+ * emulation.
+ *
+ * Also disable LASS when running under EFI, as some runtime and
+ * boot services rely on 1:1 mappings in the lower half.
+ */
+ if (IS_ENABLED(CONFIG_X86_VSYSCALL_EMULATION) ||
+ IS_ENABLED(CONFIG_EFI)) {
+ setup_clear_cpu_cap(X86_FEATURE_LASS);
+ return;
+ }
+
+ cr4_set_bits(X86_CR4_LASS);
+}
+
/* These bits should not change their value after CPU init is finished. */
static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED;
@@ -2015,10 +2037,10 @@ static void identify_cpu(struct cpuinfo_x86 *c)
/* Disable the PN if appropriate */
squash_the_stupid_serial_number(c);
- /* Set up SMEP/SMAP/UMIP */
setup_smep(c);
setup_smap(c);
setup_umip(c);
+ setup_lass(c);
/* Enable FSGSBASE instructions if available. */
if (cpu_has(c, X86_FEATURE_FSGSBASE)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message
2025-11-13 22:42 ` [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message Sohil Mehta
@ 2025-11-17 14:48 ` Borislav Petkov
2025-11-17 17:24 ` Sohil Mehta
0 siblings, 1 reply; 14+ messages in thread
From: Borislav Petkov @ 2025-11-17 14:48 UTC (permalink / raw)
To: Sohil Mehta
Cc: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Jonathan Corbet,
H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf, Peter Zijlstra,
Ard Biesheuvel, Kirill A . Shutemov, Xin Li, David Woodhouse,
Sean Christopherson, Rick Edgecombe, Vegard Nossum, Andrew Cooper,
Randy Dunlap, Geert Uytterhoeven, Kees Cook, Tony Luck,
Alexander Shishkin, linux-doc, linux-kernel, linux-efi
On Thu, Nov 13, 2025 at 02:42:02PM -0800, Sohil Mehta wrote:
> + /*
> + * If LASS is active, a NULL pointer dereference generates a #GP
> + * instead of a #PF.
> + */
I'm having trouble matching the comment...
> + if (*addr < PAGE_SIZE)
... to the conditional.
Aaaha:
"With LASS active, any invalid access to user memory (including the first page
frame) would be..."
Why is the first page frame special to justify a special check?
I must be missing something obvious here...
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message
2025-11-17 14:48 ` Borislav Petkov
@ 2025-11-17 17:24 ` Sohil Mehta
2025-11-17 18:29 ` Borislav Petkov
0 siblings, 1 reply; 14+ messages in thread
From: Sohil Mehta @ 2025-11-17 17:24 UTC (permalink / raw)
To: Borislav Petkov
Cc: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Jonathan Corbet,
H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf, Peter Zijlstra,
Ard Biesheuvel, Kirill A . Shutemov, Xin Li, David Woodhouse,
Sean Christopherson, Rick Edgecombe, Vegard Nossum, Andrew Cooper,
Randy Dunlap, Geert Uytterhoeven, Kees Cook, Tony Luck,
Alexander Shishkin, linux-doc, linux-kernel, linux-efi
On 11/17/2025 6:48 AM, Borislav Petkov wrote:
> Why is the first page frame special to justify a special check?
>
Any dereference to a very low address (the first page frame) is
typically considered as a "NULL" pointer dereference.
$ git log | grep "BUG: kernel NULL pointer dereference"
BUG: kernel NULL pointer dereference, address: 0000000000000000
BUG: kernel NULL pointer dereference, address: 0000000000000010
BUG: kernel NULL pointer dereference, address: 0000000000000008
BUG: kernel NULL pointer dereference, address: 0000000000000008
BUG: kernel NULL pointer dereference, address: 0000000000000040
BUG: kernel NULL pointer dereference, address: 0000000000000264
BUG: kernel NULL pointer dereference, address: 0000000000000000
BUG: kernel NULL pointer dereference, address: 0000000000000098
BUG: kernel NULL pointer dereference, address: 0000000000000000
BUG: kernel NULL pointer dereference, address: 00000000000003c0
The page fault error messages have similar logic:
if (address < PAGE_SIZE && !user_mode(regs))
pr_alert("BUG: kernel NULL pointer dereference, address: %px\n",
(void *)address);
I believe the check is to account for arithmetic or other operations
that may have happened on the "NULL" pointer before it is dereferenced.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message
2025-11-17 17:24 ` Sohil Mehta
@ 2025-11-17 18:29 ` Borislav Petkov
2025-11-17 19:45 ` Sohil Mehta
0 siblings, 1 reply; 14+ messages in thread
From: Borislav Petkov @ 2025-11-17 18:29 UTC (permalink / raw)
To: Sohil Mehta
Cc: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Jonathan Corbet,
H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf, Peter Zijlstra,
Ard Biesheuvel, Kirill A . Shutemov, Xin Li, David Woodhouse,
Sean Christopherson, Rick Edgecombe, Vegard Nossum, Andrew Cooper,
Randy Dunlap, Geert Uytterhoeven, Kees Cook, Tony Luck,
Alexander Shishkin, linux-doc, linux-kernel, linux-efi
On Mon, Nov 17, 2025 at 09:24:20AM -0800, Sohil Mehta wrote:
> The page fault error messages have similar logic:
>
> if (address < PAGE_SIZE && !user_mode(regs))
> pr_alert("BUG: kernel NULL pointer dereference, address: %px\n",
> (void *)address);
>
> I believe the check is to account for arithmetic or other operations
> that may have happened on the "NULL" pointer before it is dereferenced.
Ah ok, that makes sense. That comment still reads weird:
+ /*
+ * If LASS is active, a NULL pointer dereference generates a #GP
+ * instead of a #PF.
+ */
+ if (*addr < PAGE_SIZE)
It says "if LASS is active" but the check if
(cpu_feature_enabled(X86_FEATURE_LASS)) is below it.
I guess you want to have
if (cpu_feature_enabled(X86_FEATURE_LASS)) {
if (*addr < PAGE_SIZE)
return GP_NULL_POINTER;
else
return GP_LASS_VIOLATION;
}
so that it is perfectly clear.
Then the catch-all GP_CANONICAL will take care of the absurd cases, if we ever
hit them.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message
2025-11-17 18:29 ` Borislav Petkov
@ 2025-11-17 19:45 ` Sohil Mehta
2025-11-18 11:23 ` Borislav Petkov
0 siblings, 1 reply; 14+ messages in thread
From: Sohil Mehta @ 2025-11-17 19:45 UTC (permalink / raw)
To: Borislav Petkov
Cc: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Jonathan Corbet,
H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf, Peter Zijlstra,
Ard Biesheuvel, Kirill A . Shutemov, Xin Li, David Woodhouse,
Sean Christopherson, Rick Edgecombe, Vegard Nossum, Andrew Cooper,
Randy Dunlap, Geert Uytterhoeven, Kees Cook, Tony Luck,
Alexander Shishkin, linux-doc, linux-kernel, linux-efi
On 11/17/2025 10:29 AM, Borislav Petkov wrote:
>
> Ah ok, that makes sense. That comment still reads weird:
>
I see. The idea with the comment was to clarify why the check is outside
cpu_feature_enabled(X86_FEATURE_LASS). That clearly failed! :)
> I guess you want to have
>
> if (cpu_feature_enabled(X86_FEATURE_LASS)) {
> if (*addr < PAGE_SIZE)
> return GP_NULL_POINTER;
> else
> return GP_LASS_VIOLATION;
> }
>
> so that it is perfectly clear.
>
You are right. The condition would typically hit only with LASS enabled.
But since we are adding an extra hint for NULL pointers, I figured it
would be helpful even without LASS (even though it is unlikely to happen).
Therefore, the printed message isn't LASS specific either:
Oops: general protection fault, kernel NULL pointer dereference 0x0:
Also, it makes the code a tiny bit prettier (aesthetically, without the
nested if). We now have 4 hints and a check for each:
if (condition1)
return HINT_1;
...
if (condition4)
return HINT_4;
Would this update to the comment help clarify?
/*
* 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;
Though, I won't push for it further. Code clarity is more important than
reducing indentation.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message
2025-11-17 19:45 ` Sohil Mehta
@ 2025-11-18 11:23 ` Borislav Petkov
0 siblings, 0 replies; 14+ messages in thread
From: Borislav Petkov @ 2025-11-18 11:23 UTC (permalink / raw)
To: Sohil Mehta
Cc: x86, Dave Hansen, Thomas Gleixner, Ingo Molnar, Jonathan Corbet,
H . Peter Anvin, Andy Lutomirski, Josh Poimboeuf, Peter Zijlstra,
Ard Biesheuvel, Kirill A . Shutemov, Xin Li, David Woodhouse,
Sean Christopherson, Rick Edgecombe, Vegard Nossum, Andrew Cooper,
Randy Dunlap, Geert Uytterhoeven, Kees Cook, Tony Luck,
Alexander Shishkin, linux-doc, linux-kernel, linux-efi
On Mon, Nov 17, 2025 at 11:45:38AM -0800, Sohil Mehta wrote:
> Would this update to the comment help clarify?
Yap, that LGTM.
> /*
> * 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;
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-11-18 11:24 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-13 22:41 [PATCH v12 0/8] x86: Enable base Linear Address Space Separation support Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 1/8] x86/cpufeatures: Enumerate the LASS feature bits Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 2/8] x86/cpu: Add an LASS dependency on SMAP Sohil Mehta
2025-11-13 22:41 ` [PATCH v12 3/8] x86/asm: Introduce inline memcpy and memset Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 4/8] x86/alternatives: Disable LASS when patching kernel code Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 5/8] x86/kexec: Disable LASS during relocate kernel Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 6/8] x86/traps: Communicate a LASS violation in #GP message Sohil Mehta
2025-11-17 14:48 ` Borislav Petkov
2025-11-17 17:24 ` Sohil Mehta
2025-11-17 18:29 ` Borislav Petkov
2025-11-17 19:45 ` Sohil Mehta
2025-11-18 11:23 ` Borislav Petkov
2025-11-13 22:42 ` [PATCH v12 7/8] selftests/x86: Update the negative vsyscall tests to expect a #GP Sohil Mehta
2025-11-13 22:42 ` [PATCH v12 8/8] x86/cpu: Enable LASS during CPU initialization Sohil Mehta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).