2014-07-15 22:48:18 +00:00
|
|
|
/* Send a signal to a specific pthread. Stub version.
|
2024-01-01 18:12:26 +00:00
|
|
|
Copyright (C) 2014-2024 Free Software Foundation, Inc.
|
2014-07-15 22:48:18 +00:00
|
|
|
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
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
2014-07-15 22:48:18 +00:00
|
|
|
|
2021-09-13 09:06:08 +00:00
|
|
|
#include <libc-lock.h>
|
2020-12-03 14:28:58 +00:00
|
|
|
#include <unistd.h>
|
2014-07-15 22:48:18 +00:00
|
|
|
#include <pthreadP.h>
|
2020-12-03 14:43:25 +00:00
|
|
|
#include <shlib-compat.h>
|
2014-07-15 22:48:18 +00:00
|
|
|
|
2021-09-20 12:56:08 +00:00
|
|
|
/* Sends SIGNO to THREADID. If the thread is about to exit or has
|
|
|
|
already exited on the kernel side, return NO_TID. Otherwise return
|
|
|
|
0 or an error code. */
|
|
|
|
static int
|
|
|
|
__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid)
|
2014-07-15 22:48:18 +00:00
|
|
|
{
|
|
|
|
struct pthread *pd = (struct pthread *) threadid;
|
2020-12-07 19:21:55 +00:00
|
|
|
if (pd == THREAD_SELF)
|
|
|
|
{
|
2021-09-13 09:06:08 +00:00
|
|
|
/* Use the actual TID from the kernel, so that it refers to the
|
|
|
|
current thread even if called after vfork. There is no
|
|
|
|
signal blocking in this case, so that the signal is delivered
|
|
|
|
immediately, before __pthread_kill_internal returns: a signal
|
|
|
|
sent to the thread itself needs to be delivered
|
|
|
|
synchronously. (It is unclear if Linux guarantees the
|
|
|
|
delivery of all pending signals after unblocking in the code
|
|
|
|
below. POSIX only guarantees delivery of a single signal,
|
|
|
|
which may not be the right one.) */
|
|
|
|
pid_t tid = INTERNAL_SYSCALL_CALL (gettid);
|
2021-10-01 16:16:41 +00:00
|
|
|
int ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), tid, signo);
|
2021-09-13 09:06:08 +00:00
|
|
|
return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
|
2020-12-07 19:21:55 +00:00
|
|
|
}
|
2021-09-13 09:06:08 +00:00
|
|
|
|
|
|
|
/* Block all signals, as required by pd->exit_lock. */
|
2022-04-21 12:41:59 +00:00
|
|
|
internal_sigset_t old_mask;
|
|
|
|
internal_signal_block_all (&old_mask);
|
2021-09-13 09:06:08 +00:00
|
|
|
__libc_lock_lock (pd->exit_lock);
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
if (pd->exiting)
|
|
|
|
/* The thread is about to exit (or has exited). Sending the
|
|
|
|
signal is either not observable (the target thread has already
|
|
|
|
blocked signals at this point), or it will fail, or it might be
|
|
|
|
delivered to a new, unrelated thread that has reused the TID.
|
2021-09-20 12:56:08 +00:00
|
|
|
So do not actually send the signal. */
|
|
|
|
ret = no_tid;
|
2020-12-07 19:21:55 +00:00
|
|
|
else
|
2021-09-13 09:06:08 +00:00
|
|
|
{
|
|
|
|
ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), pd->tid, signo);
|
|
|
|
ret = INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
__libc_lock_unlock (pd->exit_lock);
|
2022-04-21 12:41:59 +00:00
|
|
|
internal_signal_restore_set (&old_mask);
|
2020-12-07 19:21:55 +00:00
|
|
|
|
2021-09-13 09:06:08 +00:00
|
|
|
return ret;
|
2014-07-15 22:48:18 +00:00
|
|
|
}
|
2020-12-07 20:17:24 +00:00
|
|
|
|
stdlib: Make abort/_Exit AS-safe (BZ 26275)
The recursive lock used on abort does not synchronize with a new process
creation (either by fork-like interfaces or posix_spawn ones), nor it
is reinitialized after fork().
Also, the SIGABRT unblock before raise() shows another race condition,
where a fork or posix_spawn() call by another thread, just after the
recursive lock release and before the SIGABRT signal, might create
programs with a non-expected signal mask. With the default option
(without POSIX_SPAWN_SETSIGDEF), the process can see SIG_DFL for
SIGABRT, where it should be SIG_IGN.
To fix the AS-safe, raise() does not change the process signal mask,
and an AS-safe lock is used if a SIGABRT is installed or the process
is blocked or ignored. With the signal mask change removal,
there is no need to use a recursive loc. The lock is also taken on
both _Fork() and posix_spawn(), to avoid the spawn process to see the
abort handler as SIG_DFL.
A read-write lock is used to avoid serialize _Fork and posix_spawn
execution. Both sigaction (SIGABRT) and abort() requires to lock
as writer (since both change the disposition).
The fallback is also simplified: there is no need to use a loop of
ABORT_INSTRUCTION after _exit() (if the syscall does not terminate the
process, the system is broken).
The proposed fix changes how setjmp works on a SIGABRT handler, where
glibc does not save the signal mask. So usage like the below will now
always abort.
static volatile int chk_fail_ok;
static jmp_buf chk_fail_buf;
static void
handler (int sig)
{
if (chk_fail_ok)
{
chk_fail_ok = 0;
longjmp (chk_fail_buf, 1);
}
else
_exit (127);
}
[...]
signal (SIGABRT, handler);
[....]
chk_fail_ok = 1;
if (! setjmp (chk_fail_buf))
{
// Something that can calls abort, like a failed fortify function.
chk_fail_ok = 0;
printf ("FAIL\n");
}
Such cases will need to use sigsetjmp instead.
The _dl_start_profile calls sigaction through _profil, and to avoid
pulling abort() on loader the call is replaced with __libc_sigaction.
Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Reviewed-by: DJ Delorie <dj@redhat.com>
2024-10-03 18:41:10 +00:00
|
|
|
/* Send the signal SIGNO to the caller. Used by abort and called where the
|
|
|
|
signals are being already blocked and there is no need to synchronize with
|
|
|
|
exit_lock. */
|
|
|
|
int
|
|
|
|
__pthread_raise_internal (int signo)
|
|
|
|
{
|
|
|
|
/* Use the gettid syscall so it works after vfork. */
|
|
|
|
int ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), __gettid(), signo);
|
|
|
|
return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
|
|
|
|
}
|
|
|
|
|
2021-09-20 12:56:08 +00:00
|
|
|
int
|
|
|
|
__pthread_kill_internal (pthread_t threadid, int signo)
|
|
|
|
{
|
|
|
|
/* Do not report an error in the no-tid case because the threadid
|
|
|
|
argument is still valid (the thread ID lifetime has not ended),
|
|
|
|
and ESRCH (for example) would be misleading. */
|
|
|
|
return __pthread_kill_implementation (threadid, signo, 0);
|
|
|
|
}
|
|
|
|
|
2020-12-07 20:17:24 +00:00
|
|
|
int
|
|
|
|
__pthread_kill (pthread_t threadid, int signo)
|
|
|
|
{
|
|
|
|
/* Disallow sending the signal we use for cancellation, timers,
|
|
|
|
for the setxid implementation. */
|
2022-04-21 12:41:59 +00:00
|
|
|
if (is_internal_signal (signo))
|
2020-12-07 20:17:24 +00:00
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
return __pthread_kill_internal (threadid, signo);
|
|
|
|
}
|
2021-09-20 12:56:08 +00:00
|
|
|
|
2020-12-07 19:21:55 +00:00
|
|
|
/* Some architectures (for instance arm) might pull raise through libgcc, so
|
|
|
|
avoid the symbol version if it ends up being used on ld.so. */
|
|
|
|
#if !IS_IN(rtld)
|
|
|
|
libc_hidden_def (__pthread_kill)
|
2020-12-03 14:43:25 +00:00
|
|
|
versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34);
|
|
|
|
|
2020-12-07 19:21:55 +00:00
|
|
|
# if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34)
|
2021-09-20 12:56:08 +00:00
|
|
|
/* Variant which returns ESRCH in the no-TID case, for backwards
|
|
|
|
compatibility. */
|
|
|
|
int
|
|
|
|
attribute_compat_text_section
|
|
|
|
__pthread_kill_esrch (pthread_t threadid, int signo)
|
|
|
|
{
|
2022-04-21 12:41:59 +00:00
|
|
|
if (is_internal_signal (signo))
|
2021-09-20 12:56:08 +00:00
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
return __pthread_kill_implementation (threadid, signo, ESRCH);
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0);
|
2020-12-07 19:21:55 +00:00
|
|
|
# endif
|
2020-12-03 14:43:25 +00:00
|
|
|
#endif
|