[PATCH v2 2/3] nptl: Add libc allocated shadow stack for new threads
Mark Brown
broonie@kernel.org
Thu Sep 4 13:58:10 GMT 2025
On Thu, Sep 04, 2025 at 09:51:59AM -0300, Adhemerval Zanella Netto wrote:
> On 03/09/25 17:46, Mark Brown wrote:
> > On Wed, Sep 03, 2025 at 04:46:47PM -0300, Adhemerval Zanella Netto wrote:
> >> There is currently no logic to resize the thread cache; it only adjusts the
> >> guarded control stack as needed. Remapping would defeat the cache’s main
> >> benefit, since allocating a new stack is typically faster (and, in cases
> >> where virtual memory area constraints are significant, users can already
> >> limit the cache size).
> > Note that you need a token on the shadow stack so reuse of an already
> > used one is perhaps more trouble to arrange than it's worth for glibc.
> > The security requirements do result in some overhead.
> Wouldn't be possible to kernel setup the guard shadow token stack during
> clone3?
No, the whole point of the token is to ensure that you can't use
clone3() to set an arbitrary GCSPTR_EL0 - clone3() checks that a token
is present and will report an error if one is not already present. We
need something to ensure that clone3() isn't simply being pointed at an
already active shadow stack since that would open up attacks. The API
does this by treating the clone3() as being similar to a shadow stack
switch.
> And the security overhead is expected, it is just that if we could allocate
> both the stack and the guard shadow region as a single block it would simplify
> userland management.
Like I say you can pick the address used for map_shadow_stack() so if
it's just about picking addresses that's available, though things having
to be unmapped is annoying there.
> >> As a side-note, things would be a lot more straightforward if userland could
> >> simply allocate a region such as [stack + guard control stack], and the kernel
> >> offered an API (e.g., via `madvise`) to establish the control-guarded region.
> > That was discussed as part of the API design when the x86 shadow stack
> > support was being merged, from what I remember of reading the discussion
> > people weren't very happy with the security issues surrounding being
> > able to madvise() existing blocks of memory to be shadow stacks due to
> > the ease with which race conditions or other bugs could be introduced.
> > This is especially true given the need to place a token in the shadow
> > stack, something needs to place the token and half the goal is that
> > userspace can't write to the shadow stack.
> Would this possible race-condition due the token setup, since madvise is not
> expected to change the memory contents of the input region?
I'd need to go and dig into all the concerns people had, but yes token
setup is a big part of it, as is the more general potential for
something to write to the shadow stack memory if the shadow stack memory
is ever writable by userspace before it gets marked as a shadow stack.
Another part of the concern was keeping the interface simple to reason
about, there's a lot of complexity with the memory management
interfaces.
> In agree that tying this to clone3 is not the best approach; my idea is
> if we could place the GCS adjacent to the thread stack itself it could be
> used as the pthread guard region for free. But now that we we support
> MADV_GUARD_INSTALL to setup the guard page, I guess the potential gains
> are not that much.
Yes, if you pass a suitable address to map_shadow_stack() you can
do that, though note that the shadow stack is read only so the guard
would only prevent writes.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20250904/a96fe96a/attachment.sig>
More information about the Libc-alpha
mailing list