nptl: Do not set signal mask on second setjmp return [BZ #28607]

__libc_signal_restore_set was in the wrong place: It also ran
when setjmp returned the second time (after pthread_exit or
pthread_cancel).  This is observable with blocked pending
signals during thread exit.

Fixes commit b3cae39dcb
("nptl: Start new threads with all signals blocked [BZ #25098]").

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
(cherry picked from commit e186fc5a31)
This commit is contained in:
Florian Weimer 2021-11-24 08:59:54 +01:00
parent a2539f5b1d
commit b923e061d4
4 changed files with 49 additions and 2 deletions

1
NEWS
View File

@ -23,6 +23,7 @@ The following bugs are resolved with this release:
[26932] libc: sh: Multiple floating point functions defined as stubs only
[27130] "rep movsb" performance issue
[27177] GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on doesn't work
[28607] Masked signals are delivered on thread exit
Version 2.32

View File

@ -416,8 +416,6 @@ START_THREAD_DEFN
unwind_buf.priv.data.prev = NULL;
unwind_buf.priv.data.cleanup = NULL;
__libc_signal_restore_set (&pd->sigmask);
/* Allow setxid from now onwards. */
if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
@ -427,6 +425,8 @@ START_THREAD_DEFN
/* Store the new cleanup handler info. */
THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
__libc_signal_restore_set (&pd->sigmask);
/* We are either in (a) or (b), and in either case we either own
PD already (2) or are about to own PD (1), and so our only
restriction would be that we can't free PD until we know we

View File

@ -107,6 +107,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
tst-unload \
tst-unwind-thread \
tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
tst-pthread-exit-signal \
# Files which must not be linked with libpthread.

View File

@ -0,0 +1,45 @@
/* Test that pending signals are not delivered on thread exit (bug 28607).
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* Due to bug 28607, pthread_kill (or pthread_cancel) restored the
signal mask during during thread exit, triggering the delivery of a
blocked pending signal (SIGUSR1 in this test). */
#include <support/xthread.h>
#include <support/xsignal.h>
static void *
threadfunc (void *closure)
{
sigset_t sigmask;
sigfillset (&sigmask);
xpthread_sigmask (SIG_SETMASK, &sigmask, NULL);
xpthread_kill (pthread_self (), SIGUSR1);
pthread_exit (NULL);
return NULL;
}
static int
do_test (void)
{
pthread_t thr = xpthread_create (NULL, threadfunc, NULL);
xpthread_join (thr);
return 0;
}
#include <support/test-driver.c>