Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAJt8pk898VS4ugU5cFpi0+NGxaNfeWRzdvvcPS=y0FdXAQA_Ug@mail.gmail.com>
Date: Wed, 9 Sep 2026 10:35:39 +0200
From: Pavel Labath <labath@...gle.com>
To: libc-coord@...ts.openwall.com
Subject: An async-signal-safe way to get thread’s stack

Hello libc-coord,

there are many situations where a thread needs to know its stack
boundaries, but there is no standard way to get that, leading many
projects to maintain their own web of #ifdefs for this purpose (e.g.
https://searchfox.org/firefox-main/source/js/src/util/NativeStack.cpp
and https://github.com/WebKit/WebKit/blob/b008d85bb026f03ac31665a9f99536906c88bf77/Source/WTF/wtf/StackBounds.cpp).

In Linux, we have pthread_getattr_np as a de-facto standard. This (in
conjunction with pthread_attr_getstack) lets us get the stack
boundary, but this approach has the problem of not working in
async-signal contexts. pthread_getattr_np is a complicated function.
E.g., the GLIBC implementation takes locks, opens files and allocates
memory, all of which are async-signal-unsafe operations. A lot of this
complexity is due to the main thread, which has a kernel-managed
dynamically expanding stack.

Yet, there are use cases where one needs this information from inside
a signal handler. E.g. an (in process) unwinder or a profiler can use
this information to read the stack quickly, without risking a SIGSEGV.

There is some prior art in this space. One is pthread_stackseg_np in
OpenBSD <https://man.openbsd.org/pthread_stackseg_np.3>
<https://github.com/openbsd/src/blob/88e222c6018bdf12ed942519539f8780ce322467/lib/librthread/rthread_np.c#L83>.
The function isn’t documented as async-signal-safe, though the
implementation /mostly/ appears to be so (the first call to the
function initializes some data structures, which likely isn’t safe).
The implementation uses RLIMIT_STACK to get the stack size of the main
thread. The function also uses stack_t in an unusual way (returning
the bottom of the stack instead of the lowest address).

We also have stack_getbounds on Solaris
<https://docs.oracle.com/cd/E88353_01/html/E37843/stack-getbounds-3c.html>
<https://github.com/kofemann/opensolaris/blob/master/usr/src/lib/libc/port/gen/stack.c#L39>.
The function is documented as async-signal-safe.  The stack bounds for
the main thread are initialized at startup using RLIMIT_STACK, with
ss_size set to zero for RLIM_INFINITY.

I’ve added a pthread_getstack_np extension
<https://github.com/llvm/llvm-project/pull/217049> to LLVM-libc. The
function has a pthread_attr_getstack-like API. For the main thread it
behaves similar to Solaris stack_getbounds, except that it sets the
size to zero (PTHREAD_STACK_DYNAMIC_NP) unconditionally. However,
please don’t take this email as a request to adopt this API. This is
something that we created for experimentation and I’d be happy to
change that API if we come up with a better one. In fact, I am hoping
that’s exactly what will happen.

Would it be possible to coordinate on a common API to perform this
operation? I suspect the main point of contention will be the main
thread, as all of the mentioned approaches have their downsides. The
two properties I’m looking for are async-safety and a guarantee that
returned info identifies the readable portion of the stack.

Comments?

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.