diff options
author | Florian Weimer <fweimer@redhat.com> | 2021-09-23 09:55:54 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2021-09-23 09:56:07 +0200 |
commit | 2849e2f53311b66853cb5159b64cba2bddbfb854 (patch) | |
tree | 24a4ff2579b422e3689d254bfeb297ec8cf9a08b /nptl | |
parent | b3f27d8150d4f3c64063a9a257ec1d228de66398 (diff) | |
download | glibc-2849e2f53311b66853cb5159b64cba2bddbfb854.zip glibc-2849e2f53311b66853cb5159b64cba2bddbfb854.tar.gz glibc-2849e2f53311b66853cb5159b64cba2bddbfb854.tar.bz2 |
nptl: Avoid setxid deadlock with blocked signals in thread exit [BZ #28361]
As part of the fix for bug 12889, signals are blocked during
thread exit, so that application code cannot run on the thread that
is about to exit. This would cause problems if the application
expected signals to be delivered after the signal handler revealed
the thread to still exist, despite pthread_kill can no longer be used
to send signals to it. However, glibc internally uses the SIGSETXID
signal in a way that is incompatible with signal blocking, due to the
way the setxid handshake delays thread exit until the setxid operation
has completed. With a blocked SIGSETXID, the handshake can never
complete, causing a deadlock.
As a band-aid, restore the previous handshake protocol by not blocking
SIGSETXID during thread exit.
The new test sysdeps/pthread/tst-pthread-setuid-loop.c is based on
a downstream test by Martin Osvald.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'nptl')
-rw-r--r-- | nptl/pthread_create.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index a559f86..d6ea43a 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -487,8 +487,16 @@ start_thread (void *arg) /* This prevents sending a signal from this thread to itself during its final stages. This must come after the exit call above - because atexit handlers must not run with signals blocked. */ - __libc_signal_block_all (NULL); + because atexit handlers must not run with signals blocked. + + Do not block SIGSETXID. The setxid handshake below expects the + signal to be delivered. (SIGSETXID cannot run application code, + nor does it use pthread_kill.) Reuse the pd->sigmask space for + computing the signal mask, to save stack space. */ + __sigfillset (&pd->sigmask); + __sigdelset (&pd->sigmask, SIGSETXID); + INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &pd->sigmask, NULL, + __NSIG_BYTES); /* Tell __pthread_kill_internal that this thread is about to exit. If there is a __pthread_kill_internal in progress, this delays |