[PATCH v2 2/3] nptl: Add libc allocated shadow stack for new threads

Catalin Marinas catalin.marinas@arm.com
Thu Sep 18 17:27:15 GMT 2025


Thanks Adhemerval for the feedback so far. Adding Will and Christian for
the kernel implementation:

https://lore.kernel.org/all/20250916-clone3-shadow-stack-v21-0-910493527013@kernel.org/

On Thu, Sep 18, 2025 at 10:02:49AM -0300, Adhemerval Zanella wrote:
> On 17/09/25 19:13, Mark Brown wrote:
> > On Wed, Sep 17, 2025 at 04:29:36PM -0300, Adhemerval Zanella Netto wrote:
[... lots of text trimmed ...]
> >> What I am trying to say is that with the current ABI, it only adds an extra burden on 
> >> userland to manage the shadow stacks for most runtimes. However, if the defined kernel 
> >> ABI is used, it can work out this on glibc. 
> > 
> > There is no requirement to use this interface at all, if userspace
> > doesn't use this interface it will continue to see the existing
> > behaviour.

I'd like to have at least a user of such interface, otherwise we just
maintain a user-kernel ABI that never gets exercised, other than
kselftests.

> Right, and I think adding a pthread extension to set up the shadow stack size would 
> be really error-prone and difficult to use. It would require callers to know the call 
> stack size and tune accordingly. I have seen reports where programs fail with 
> different stack sizes because either the C runtime has a different size than glibc, 
> or the user uses a smaller size than the required one. This issue tends to be difficult 
> to debug, but it may be less pronounced with the shadow stack. 
> 
> I think a prctl to adjust the factor might work better, and we can add a tunable so 
> users might adjust during process startup. It will not be per-thread, though.

A short summary from the kernel side: we first added clone() support
with some large default size for the shadow stack to cope with all
scenarios (to match the x86 ABI and also allow GCS on deployments that
don't work well with clone3() due to SECCOMP). The kernel allocates and
frees the shadow stack on thread creation/release.

At the time I also asked for clone3() support to be able to handle the
shadow stack in a similar way to the main stack - managed by the user
and not just the size but the placement. I had not realised at the time
that shadow stack reuse is problematic and glibc may not gain much by
moving to the new interface. I tend to agree that, at least for
glibc/nptl, the new interface doesn't help if the shadow stack can't be
easily reused, other than being able to control the size.

Given that the kernel patches are possibly going into 6.18, we need some
quick decision on:

1. Defer the kernel patches to 6.19 (or later) until the glibc
   discussion settles

2. Keep the clone3() interface as is and separately add a patch to
   re-instate the token on the shadow stack to facilitate reuse

3. Another mechanism that allows shadow stack reuse independent of the
   clone3() interface

4. Change the clone3() interface to allow a NULL shadow stack pointer
   but introduce a size to struct clone_args (it implies (1) above). The
   kernel would allocate the shadow stack accordingly

5. Any other option? This likely implies (1)

The prctl() to set a default shadow stack size is a good discussion to
have but complementary to the clone3() interface.

So, if Yury's nptl patches using clone3() aren't going in, I'd rather
opt for (1) w.r.t. the kernel patches. I know we had these patches
around for nearly two years but I also like to see some users of the
interface longer term.

-- 
Catalin


More information about the Libc-alpha mailing list