Re: [PATCHv6 01/16] x86/cpu: Enumerate the LASS feature bits

H. Peter Anvin
2025-06-25T18:52:39Z

On June 20, 2025 11:14:56 AM PDT, Sohil Mehta <sohil.mehta@intel.com> wrote:
>On 6/20/2025 6:53 AM, Kirill A. Shutemov wrote:
>>
>> +/*
>> + * The CLAC/STAC instructions toggle enforcement of X86_FEATURE_SMAP.
>> + *
>> + * X86_FEATURE_LASS requires flipping the AC flag when accessing the lower half
>> + * of the virtual address space, regardless of the _PAGE_BIT_USER bit in the
>> + * page tables. lass_clac/stac() should be used for these cases.
>> + *
>
>Is this supposed to be "regardless" or only when the _PAGE_BIT_USER bit
>it set? The way the sentence is worded it would seem that the kernel
>could always use lass_clac()/stac() since the value in _PAGE_BIT_USER
>doesn't matter.
>
>Please correct me if I am wrong, but here is my understanding:
>
>X86_FEATURE_SMAP and X86_FEATURE_LASS both complain when the kernel
>tries to access the lower half of the virtual addresses.
>
>SMAP flags an issue if _PAGE_BIT_USER is not set. LASS would #GP in both
>cases with or without the _PAGE_BIT_USER being set.
>
>However, in terms of usage, we want to use LASS specific stac()/clac()
>only when _PAGE_BIT_USER is set. Since this won't be flagged by SMAP.
>
>@Dave Hansen, you had suggested separating out the SMAP/LASS AC toggle
>functions. But, the difference in usage between both of them seems very
>subtle. Could this be easily misused?
>
>For example, there is no failure that would happen if someone
>incorrectly uses the SMAP specific clac()/stac() calls instead of the
>LASS ones.
>
>> + * 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);
>> }
>>
>> +static __always_inline void lass_clac(void)
>> +{
>> + alternative("", "clac", X86_FEATURE_LASS);
>> +}
>> +
>> +static __always_inline void lass_stac(void)
>> +{
>> + alternative("", "stac", X86_FEATURE_LASS);
>> +}
>> +

"Regardless" is correct. LASS only considers which hemisphere the virtual address is located in, because it is explicitly designed to prevent walking the page tables in the "wrong" hemisphere and therefore speculative accesses that happen to form pointers into user space addresses will not cause TLB or cache fills that might be possible to probe.

The obvious exception is when the kernel is intentionally performing accesses on behalf of user space, which is exactly what SMAP tells the hardware already.