[PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits

Sohil Mehta posted 15 patches 4 months ago
There is a newer version of this series
[PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Sohil Mehta 4 months ago
Linear Address Space Separation (LASS) is a security feature that
intends to prevent malicious virtual address space accesses across
user/kernel mode.

Such 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
pre-paging, 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. 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 and add a dependency on
SMAP.

LASS mitigates a class of side-channel speculative attacks, such as
Spectre LAM [1]. 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.

Link: https://download.vusec.net/papers/slam_sp24.pdf [1]
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>
---
v10:
 - Do not modify tools/**/cpufeatures.h as those are synced separately.
---
 arch/x86/Kconfig.cpufeatures                | 4 ++++
 arch/x86/include/asm/cpufeatures.h          | 1 +
 arch/x86/include/uapi/asm/processor-flags.h | 2 ++
 arch/x86/kernel/cpu/cpuid-deps.c            | 1 +
 4 files changed, 8 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 b2a562217d3f..1283f3bdda0d 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)
 
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
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Borislav Petkov 3 months, 3 weeks ago
On Mon, Oct 06, 2025 at 11:51:05PM -0700, Sohil Mehta wrote:
> Link: https://download.vusec.net/papers/slam_sp24.pdf [1]

Just give the full paper name and people can search for it. Links tend to get
stale over time.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Sohil Mehta 3 months, 2 weeks ago
On 10/16/2025 8:35 AM, Borislav Petkov wrote:
> On Mon, Oct 06, 2025 at 11:51:05PM -0700, Sohil Mehta wrote:
>> Link: https://download.vusec.net/papers/slam_sp24.pdf [1]
> 
> Just give the full paper name and people can search for it. Links tend to get
> stale over time.
> 

Sure, will do.
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Edgecombe, Rick P 4 months ago
On Mon, 2025-10-06 at 23:51 -0700, Sohil Mehta wrote:
> Linear Address Space Separation (LASS) is a security feature that
> intends to prevent malicious virtual address space accesses across
> user/kernel mode.
> 
> Such 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
> pre-paging, an attacker will not be able to derive paging-based timing

Nit: pre-page walk maybe? Otherwise it could sound like before paging is enabled
during boot.

> 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. 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 and add a dependency on
> SMAP.
> 
> LASS mitigates a class of side-channel speculative attacks, such as
> Spectre LAM [1]. 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.
> 
> Link: https://download.vusec.net/papers/slam_sp24.pdf [1]
> 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>
> ---
> v10:
>  - Do not modify tools/**/cpufeatures.h as those are synced separately.
> ---
>  arch/x86/Kconfig.cpufeatures                | 4 ++++
>  arch/x86/include/asm/cpufeatures.h          | 1 +
>  arch/x86/include/uapi/asm/processor-flags.h | 2 ++
>  arch/x86/kernel/cpu/cpuid-deps.c            | 1 +
>  4 files changed, 8 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
> +

All the other ones in the file are !X86_64. Why do this one 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 b2a562217d3f..1283f3bdda0d 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)
>  
> 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      },

Aha! So SMAP is required for LASS. This makes the stac/clac patch make more
sense. Please those comments less seriously. Although I think a comment is still
not unwarranted.

>  	{}
>  };
>  

Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Sohil Mehta 4 months ago
On 10/7/2025 11:19 AM, Edgecombe, Rick P wrote:
>> LASS provides the same mode-based protections as paging but without
>> traversing the paging structures. Because the protections are enforced
>> pre-paging, an attacker will not be able to derive paging-based timing
> 
> Nit: pre-page walk maybe? Otherwise it could sound like before paging is enabled
> during boot.
> 

How about: ... protections are enforced prior to page walks, an ...

>>  
>> +config X86_DISABLED_FEATURE_LASS
>> +	def_bool y
>> +	depends on X86_32
>> +
> 
> All the other ones in the file are !X86_64. Why do this one X86_32?
> 

The double negation (DISABLED and !X86_64) was harder to follow when
this was initially posted.

https://lore.kernel.org/lkml/73796800-819b-4433-b0ef-db852336d7a4@zytor.com/
https://lore.kernel.org/lkml/756e93a2-7e42-4323-ae21-a5437e71148e@infradead.org/

I don't have a strong preference. I guess the inconsistency makes it
confusing as well. Will change it back to !X86_64 unless Xin objects.
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Xin Li 4 months ago
On 10/8/2025 4:49 AM, Sohil Mehta wrote:
>>>   
>>> +config X86_DISABLED_FEATURE_LASS
>>> +	def_bool y
>>> +	depends on X86_32
>>> +
>> All the other ones in the file are !X86_64. Why do this one X86_32?
>>
> The double negation (DISABLED and !X86_64) was harder to follow when
> this was initially posted.
> 
> https://lore.kernel.org/lkml/73796800-819b-4433-b0ef-db852336d7a4@zytor.com/
> https://lore.kernel.org/lkml/756e93a2-7e42-4323-ae21- 
> a5437e71148e@infradead.org/
> 
> I don't have a strong preference. I guess the inconsistency makes it
> confusing as well. Will change it back to !X86_64 unless Xin objects.

I prefer to use X86_32, which is more direct.

Now the only disabled feature when !X86_64 is X86_DISABLED_FEATURE_PCID.
And I would expect the disabled features due to lack of 32-bit enabling 
will keep growing until we remove 32-bit kernel code.  I was also thinking
to move all such disabled features to a dedicated file when the total
reaches 3.  But hopefully removing 32-bit will happen first.
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Edgecombe, Rick P 4 months ago
On Wed, 2025-10-08 at 07:16 +0800, Xin Li wrote:
> > 
> > I don't have a strong preference. I guess the inconsistency makes it
> > confusing as well. Will change it back to !X86_64 unless Xin objects.
> 
> I prefer to use X86_32, which is more direct.

Fine by me, I was just noticing the asymmetry. I do think that anything like
that, that sticks out, is good to mention in the log.
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Dave Hansen 4 months ago
On 10/7/25 11:19, Edgecombe, Rick P wrote:
>>  	{ X86_FEATURE_SPEC_CTRL_SSBD,		X86_FEATURE_SPEC_CTRL },
>> +	{ X86_FEATURE_LASS,			X86_FEATURE_SMAP      },
> Aha! So SMAP is required for LASS. This makes the stac/clac patch make more
> sense. Please those comments less seriously. Although I think a comment is still
> not unwarranted.

STAC/CLAC are also architected to:

	#UD - If CPUID.(EAX=07H, ECX=0H):EBX.SMAP[bit 20] = 0.

So, even though LASS _technically_ doesn't require SMAP, it would be a
real pain without SMAP and STAC/CLAC. Thus, this series relies on SMAP
being present.

Actually, it might be worth breaking this dependency hunk out into its
own patch, just so there's a nice clean place to discuss this.
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Sohil Mehta 4 months ago
On 10/7/2025 11:28 AM, Dave Hansen wrote:

> STAC/CLAC are also architected to:
> 
> 	#UD - If CPUID.(EAX=07H, ECX=0H):EBX.SMAP[bit 20] = 0.
> 
> So, even though LASS _technically_ doesn't require SMAP, it would be a
> real pain without SMAP and STAC/CLAC. Thus, this series relies on SMAP
> being present.
> 

The spec says,
"A supervisor-mode data access causes a LASS violation if it would
access a linear address of which bit 63 is 0, supervisor-mode access
protection is enabled (by setting CR4.SMAP), and either RFLAGS.AC = 0 or
the access is an implicit supervisor-mode access."

One could argue that the LASS hardware enforcement of the kernel data
accesses *depends* on SMAP being enabled.

> Actually, it might be worth breaking this dependency hunk out into its
> own patch, just so there's a nice clean place to discuss this.

Sure, we can talk about the above wording in the spec, as well as the
STAC/CLAC dependency in a separate patch.

I included some information in the cover letter to explain that:

When there are valid reasons for the kernel to access memory in the user
half, it can temporarily suspend LASS 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.
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by H. Peter Anvin 3 months, 3 weeks ago
On 2025-10-07 13:20, Sohil Mehta wrote:
> 
> The spec says,
> "A supervisor-mode data access causes a LASS violation if it would
> access a linear address of which bit 63 is 0, supervisor-mode access
> protection is enabled (by setting CR4.SMAP), and either RFLAGS.AC = 0 or
> the access is an implicit supervisor-mode access."
> 
> One could argue that the LASS hardware enforcement of the kernel data
> accesses *depends* on SMAP being enabled.
> 
>> Actually, it might be worth breaking this dependency hunk out into its
>> own patch, just so there's a nice clean place to discuss this.
> 
> Sure, we can talk about the above wording in the spec, as well as the
> STAC/CLAC dependency in a separate patch.
> 
> I included some information in the cover letter to explain that:
> 
> When there are valid reasons for the kernel to access memory in the user
> half, it can temporarily suspend LASS 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.

Just to be clear: there is no reason to spend any time whatsoever on
supporting LASS without SMAP, because no such hardware is ever expected to
exist. The CPU feature dependencies are not all necessarily architectural, but
also Linux implementation choices -- Linux is in no way somehow required to be
optimized for every combination of features, and a lot of the time it makes
perfect sense to say "you don't have X, so I won't use Y either."

	-hpa
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Edgecombe, Rick P 4 months ago
On Tue, 2025-10-07 at 13:20 -0700, Sohil Mehta wrote:
> > STAC/CLAC are also architected to:
> > 
> >  	#UD - If CPUID.(EAX=07H, ECX=0H):EBX.SMAP[bit 20] = 0.
> > 
> > So, even though LASS _technically_ doesn't require SMAP, it would be a
> > real pain without SMAP and STAC/CLAC. Thus, this series relies on SMAP
> > being present.

Ah, ok.

> 
> 
> The spec says,
> "A supervisor-mode data access causes a LASS violation if it would
> access a linear address of which bit 63 is 0, supervisor-mode access
> protection is enabled (by setting CR4.SMAP), and either RFLAGS.AC = 0 or
> the access is an implicit supervisor-mode access."
> 
> One could argue that the LASS hardware enforcement of the kernel data
> accesses *depends* on SMAP being enabled.

The fetch part doesn't though?
Re: [PATCH v10 01/15] x86/cpu: Enumerate the LASS feature bits
Posted by Sohil Mehta 4 months ago
On 10/7/2025 1:38 PM, Edgecombe, Rick P wrote:
>> One could argue that the LASS hardware enforcement of the kernel data
>> accesses *depends* on SMAP being enabled.
> 
> The fetch part doesn't though?

That's right. The instruction fetches could have depended on SMEP but
the spec explicitly calls out that it does not.

"A supervisor-mode instruction fetch causes a LASS violation if it would
accesses a linear address of which bit 63 is 0. (Unlike paging, this
behavior of LASS applies regardless of the setting of CR4.SMEP.)"