[PATCH v4 0/5] aarch64: support shadow stack in clone3
Yury Khrustalev
yury.khrustalev@arm.com
Fri Dec 19 11:26:17 GMT 2025
On Thu, Dec 11, 2025 at 10:42:03AM -0300, Adhemerval Zanella Netto wrote:
>
> On 07/11/25 06:35, Yury Khrustalev wrote:
> > Kernel extends clone3() interface to allow specifying a shadow stack
> > when creating a new thread or process [1].
> >
> > In this patch series we make use of this extended interface on aarch64
> > when GCS is available. We also suggest a new API to set and query the
> > size of the shadow stack used for new threads.
> >
> > Part of the difficulty is versioning of the clone3() syscall in terms of
> > the struct clone_args as discussed in [2] and that a system can support
> > HWCAP_GCS without supporting extended struct clone_args. We check this
> > by doing a dummy clone3 syscall with a specific size of the struct and
> > looking for the E2BIG errno.
> >
> > Regarding the new thread_attr_{get,set}shadowstacksize functions, they
> > are added for all targets supporting thread_attr_{get,set}stacksize()
> > however the targets that don't currently use shadow stack allocated
> > by Glibc the default shadows stack size is going to be zero. It is OK
> > to set a new value for the shadow stack size, but it would have no effect
> > on such targets since no shadow stack is allocated.
> >
> > Regression was tested on aarch64 and x86, and no regression has been found.
> >
> > New pthread_attr_...() functions checked with the build-many-glibcs.py
> > script for all affected targets.
> >
> > Corresponding Linux kernel patch is [1] and can be checked out from [3]
> > (based on v6.18-rc1) which is the same as [4] applied on top of [1].
> >
> > The plan is to use [4] in the subsequent Glibc patch to support re-using
> > shadow stack mappings in order to avoid unnecessarily un-mapping shadow
> > stacks for each new thread.
> >
> > This change can be tested on the FVP model as described in [5].
>
> I am still not fully sure how useful this interface would be for glibc.
The idea is to give some form of control over the size of shadow stack
because current default (that Glibc uses internally for makecontext()
and that the kernel uses on its side for normal threads) may be too big.
Using pthread_attr_...() functions is just one example how this can be
done. There are probably other ways. In the end, we should be able to
configure size of shadow stack in some form. Or is this something we
don't agree on as well?
> AFAIK, the GCS does use demand paging, and VMA usage is hardly a problem
> except in very specific cases (like sanitizers that also require a very
> complex runtime that hooks into libc anyway).
>
> In theory, users can tune VMA usage and squeeze some minor performance
> gains, but I agree with Elliott Hughes that this kind of API has historically
> been a source of bugs (I see from time to time users reporting issues with
> musl because it creates a thread with a smaller stack size than glibc).
IMHO, if someone misuses some API and gets bugs, it's not a reason to not have
this API at all. Otherwise, we should get rid of printf() probably :)
> Not being able to disable GCS usage is confusing
I'm not sure what you mean by that. You can disable GCS usage and shadow
stack will not be allocated in this case. If you refer to an issue in the
current implementation of user-side allocation of shadow stacks, then we
should just fix it.
> and does not align with
> the current pthread semantics for other configurable features (such as guard
> pages). And GCS being created even when callers use pthread_attr_setstack
> might be another source of confusion,
Again, not follow you here. Normal stack (provided via pthread_attr_setstack())
is supposed to be independent of the shadow stack allocation. Whether shadow
shack is used or not is orthogonal to how user allocates normal stack.
> since POSIX states that it is the
> application's responsibility to manage stack overflow, along with stack
> allocation and management (but this is since the GCS support was added).
>
> And I am not very fond of replicating, in userland, a logic that the kernel
> provides transparently (allocate and manage guarded stack lifetime).
We already have this logic anyway (used for makecontext()) so why not use
it to provide API to control shadow stack size?
More information about the Libc-alpha
mailing list