[PATCH v4 0/5] aarch64: support shadow stack in clone3

enh enh@google.com
Fri Dec 19 19:12:37 GMT 2025


On Fri, Dec 19, 2025 at 6:27 AM Yury Khrustalev <yury.khrustalev@arm.com> wrote:
>
> 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?

i don't think so ... "why do i care if it's too big? it's just address
space". i'm already paying for the vma, and that's the resource i
actually care about (because of the kernel-side per-vma cost).

shrinking thread stack sizes makes people feel better but isn't useful
in practice, and does store up future trouble if/when functions in
some callee-of-a-callee-of-a-callee need more space.

> > 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 :)

the difference here is that if you fuck up your format string, you
find out _today_. your test doesn't pass _today_.

the whole problem with manually shrinking stack sizes is that you're
hard-coding assumptions from today that restrict _future_ changes
(often in someone else's code, hence the
"callee-of-a-callee-of-a-callee" comment above).

> > 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?

here your printf() argument _does_ work, albeit in reverse --- "just
because we already have broken api like getwd() doesn't mean should
add more bad api that takes a char* without a size_t" :-P


More information about the Libc-alpha mailing list