Re: [PATCH 1/2] x86/shstk: support via prctl

Bill Roberts <[email protected]> Mon, 3 Aug 2026 12:41:34 -0500
Newsgroups org.kernel.vger.linux-kselftest,org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 7/29/26 8:29 AM, Edgecombe, Rick P wrote:
> On Tue, 2026-07-14 at 10:47 -0500, Bill Roberts wrote:
>> Historically, managing the user-space shadow stack state on x86 has
>> been handled exclusively through the arch_prctl() interface via the
>> ARCH_SHSTK_* operations. However, other architectures (such as arm64 and
>> riscv) do not implement arch_prctl() and instead utilize the newer,
>> arch-agnostic, prctl() interface (i.e. PR_GET_SHADOW_STACK_STATUS and
>> PR_SET_SHADOW_STACK_STATUS).
>>
>> To provide language runtimes, toolchains, and libc implementations with a
>> consistent, cross-architecture interface for managing control-flow
>> integrity, wire up the generic shadow stack prctl handlers for x86.
> I think glibc doesn't handles this in arch code, right?

Did you mean "I think glibc does handle this in arch code, right?". If 
so, yes, glibc handles this in arch
code. It would be nice if could also merge this for all architectures in 
the future.

> So the point of this is
> only your SE Linux patches. Or is there other cross-arch code that wants to
> handle shadow stack?
>
> BTW, for non security module people, can you explain why it needs this design?

Yes will add this to the commit message for v2. But as you know, the 
gist would be,
if we lock the front door of the house, we should lock the back door too 
or the lock
is useless.

>
>> Map the generic PR_SHADOW_STACK_ENABLE, PR_SHADOW_STACK_DISABLE, and
>> PR_SHADOW_STACK_LOCK operations onto the underlying x86 internal CET helper
>> routines. This allows portable userspace applications to toggle or query
>> shadow stack states without relying on architecture-specific system calls,
>> while maintaining backward compatibility with existing arch_prctl() calls.
> Can you explain why not to include ARCH_SHSTK_UNLOCK?
> https://lore.kernel.org/lkml/[email protected]
 From what I can tell, there is no analogous operation in the common 
flow, you lock the thread features, and
the features are locked in perpetuity for the thread. If you need fluid 
changes to these bits, you just don't lock
it. If in the future the generic interface gets this, then it would make 
sense for sure.
>
>> Signed-off-by: Bill Roberts <[email protected]>
>> ---
>>   arch/x86/kernel/shstk.c | 35 +++++++++++++++++++++++++++++++++++
>>   1 file changed, 35 insertions(+)
>>
>> diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c
>> index 0ca64900192f..ef3db94eec6a 100644
>> --- a/arch/x86/kernel/shstk.c
>> +++ b/arch/x86/kernel/shstk.c
>> @@ -18,6 +18,7 @@
>>   #include <linux/sizes.h>
>>   #include <linux/user.h>
>>   #include <linux/syscalls.h>
>> +#include <linux/prctl.h>
>>   #include <asm/msr.h>
>>   #include <asm/fpu/xstate.h>
>>   #include <asm/fpu/types.h>
>> @@ -630,3 +631,37 @@ bool shstk_is_enabled(void)
>>   {
>>   	return features_enabled(ARCH_SHSTK_SHSTK);
>>   }
>> +
>> +/* We assume the prctl() feature bits line up with the arch_prctl() specific
>> ones. */
>> +static_assert(PR_SHADOW_STACK_ENABLE == ARCH_SHSTK_SHSTK);
>> +static_assert(PR_SHADOW_STACK_WRITE  == ARCH_SHSTK_WRSS);
> This is only needed for arch_get_shadow_stack_status()? So can we put it near by
> and explain why?
>
>> +
>> +/* Handles the generic prctl interface for PR_SET_SHADOW_STACK_STATUS and its
>> feature bits */
>> +int arch_set_shadow_stack_status(struct task_struct *t, unsigned long status)
>> +{
>> +	int rc;
> It needs to reject invalid options for status.
>
>> +
>> +	/* x86 arch_prctl is single bit at a time, so handle these one at
>> time */
>> +	if (!status & PR_SHADOW_STACK_ENABLE)
>> +		return shstk_prctl(t, ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK);
>> +
>> +	rc = shstk_prctl(t, ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK);
>> +	if (rc)
>> +		return rc;
>> +
>> +	if (status & PR_SHADOW_STACK_WRITE)
>> +		return shstk_prctl(t, ARCH_SHSTK_ENABLE, ARCH_SHSTK_WRSS);
>> +
>> +	return shstk_prctl(t, ARCH_SHSTK_DISABLE, ARCH_SHSTK_WRSS);
>> +}
>> +
>> +/* Handles the generic prctl interface for PR_LOCK_SHADOW_STACK_STATUS and
>> its feature bits */
>> +int arch_lock_shadow_stack_status(struct task_struct *t, unsigned long
>> status)
>> +{
>> +	return shstk_prctl(t, ARCH_SHSTK_LOCK, status);
>> +}
>> +
>> +int arch_get_shadow_stack_status(struct task_struct *t, unsigned long __user
>> *status)
>> +{
>> +	return shstk_prctl(t, ARCH_SHSTK_STATUS, (unsigned long)status);
>> +}