setjmp & longjmp at thread start & exit

Szabolcs Nagy szabolcs.nagy@arm.com
Tue Jun 23 16:33:25 GMT 2020


The 06/23/2020 15:42, Matthew Malcomson wrote:
> Hello
> 
> The pthread unwinding longjmp/setjmp setup seems a little confusing and
> I'd like to ask about the viability of a change.
> 
> As I understand it there is a __libc_unwind_longjmp in unwind_stop that
> either jumps to the non-interceptable setjmp in __libc_start_main, or to
> the setjmp that can be intercepted which was called in the pthread_create.c
> function start_thread.
> 
> Is there anything requiring the non-interceptable setjmp in
> __libc_start_main?

jmp_buf layout is libc internal, only its size and
alignment is public abi. (i.e. layout may change
between glibc releases.)

so to intercept setjmp you have to ensure that all
public apis that rely on jmp_buf layout are intercepted.
(e.g. __siglongjmp or ___longjmp_chk are examples.)

and libc should continue to use its own jmp_buf apis
via interanl symbol names, not the intercepted symbols,
since it relies on its own jmp_buf layout (e.g. in
cancellation handling). i.e. you don't need PLT or
other indirection in libc.so: only intercept jmp_buf
apis in user code.

and this all only works if libc code is not instrumented
with hwasan and never jumps across user code when it uses
its internal jmpbuf apis. (i think this is guaranteed).

if you want to instrument glibc itself then you just
have to add hwasan support to it (without interception).

> (Maybe something I don't know around dynamic linking at startup?)
> If not, is there any chance of adding the PLT indirection to allow
> interception?
> I'm asking on the off-chance it's acceptable to the community, since I
> do recognise intercepting setjmp & longjmp is not something user code
> should usually be doing.
> 
> 
> To explain why I'm asking:
> I'm trying to handle longjmp and setjmp in a library that maintains a
> shadow stack and I'm having trouble with these non-local jumps.
> (hwasan -- hardware address sanitizer,
> https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html).
> 
> 
> To explain why I can't follow what ASAN does (which I expect would be
> the first question on most people's minds):
> 
> ASAN intercepts all longjmp variants and no setjmp variants.
> ASAN clears the entire shadow stack in these interceptors.  HWASAN can't
> do the equivalent since it doesn't (in general) have a "valid" byte to
> set on the shadow stack -- tags in the pointer used must match tags in
> the shadow space.
> (There *is* a HWASAN option to have a special match-all tag that's
> always valid, but it's not the default and I wouldn't like require such
> an approach for userspace santization with a GNU libc).

i think for hwasan you will need to add support
code into the libc.

and even then guaranteeing correct stack maintenance
may be difficult (e.g. swapcontext can switch to a
different stack or jump to a previous stackframe
and you may not be able to tell which happened.
or longjmp may jump out of a signal handler if that
interrupted signal-safe code, but the signal handler
stack may be different from the stack where longjump
lands, etc).

> 
> 
> Thanks for any answers,
> Matthew


More information about the Libc-alpha mailing list