2017-11-04 00:37:55 +00:00
|
|
|
/* Special use of signals internally. Linux version.
|
2025-01-01 18:14:45 +00:00
|
|
|
Copyright (C) 2014-2025 Free Software Foundation, Inc.
|
2014-07-31 18:37:48 +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-31 18:37:48 +00:00
|
|
|
|
2017-11-04 00:37:55 +00:00
|
|
|
#ifndef __INTERNAL_SIGNALS_H
|
|
|
|
# define __INTERNAL_SIGNALS_H
|
|
|
|
|
2022-04-21 12:41:59 +00:00
|
|
|
#include <internal-sigset.h>
|
|
|
|
#include <limits.h>
|
2016-01-19 19:33:32 +00:00
|
|
|
#include <signal.h>
|
Remove __need macros from signal.h.
The types affected are __sig_atomic_t, sig_atomic_t, __sigset_t,
sigset_t, sigval_t, sigevent_t, and siginfo_t. __sig_atomic_t is a
scalar, so it's now directly available from bits/types.h. The others
get bits/types/ headers.
Side effects include: There have been small changes to which
non-signal headers expose which subset of the signal-related types.
A couple of architectures' nested siginfo_t fields had to be renamed
to prevent undesired macro expansion. Internal code that wants to
manipulate signal masks must now include <sigsetops.h> (which is not
installed) and should be aware that __sigaddset, __sigandset,
__sigdelset, __sigemptyset, and __sigorset no longer return a value
(unlike the public API). Relatedly, the public signal.h no longer
declares any of those functions. The obsolete sigmask() macro no
longer has a system-specific definition -- in the cases where it
matters, it didn't work anyway.
New Linux architectures should create bits/siginfo-arch.h and/or
bits/siginfo-consts-arch.h to customize their siginfo_t, rather than
duplicating everything in bits/siginfo.h (which no longer exists).
Add new __SI_* macros if necessary. Ports to other operating systems
are strongly encouraged to generalize this scheme further.
* bits/sigevent-consts.h
* bits/siginfo-consts.h
* bits/types/__sigset_t.h
* bits/types/sigevent_t.h
* bits/types/siginfo_t.h
* sysdeps/unix/sysv/linux/bits/sigevent-consts.h
* sysdeps/unix/sysv/linux/bits/siginfo-consts.h
* sysdeps/unix/sysv/linux/bits/types/__sigset_t.h
* sysdeps/unix/sysv/linux/bits/types/sigevent_t.h
* sysdeps/unix/sysv/linux/bits/types/siginfo_t.h:
New system-dependent bits headers.
* sysdeps/unix/sysv/linux/bits/siginfo-arch.h
* sysdeps/unix/sysv/linux/bits/siginfo-consts-arch.h
* sysdeps/unix/sysv/linux/ia64/bits/siginfo-arch.h
* sysdeps/unix/sysv/linux/ia64/bits/siginfo-consts-arch.h
* sysdeps/unix/sysv/linux/mips/bits/siginfo-arch.h
* sysdeps/unix/sysv/linux/sparc/bits/siginfo-arch.h
* sysdeps/unix/sysv/linux/tile/bits/siginfo-arch.h
* sysdeps/unix/sysv/linux/tile/bits/siginfo-consts-arch.h
* sysdeps/unix/sysv/linux/x86/bits/siginfo-arch.h:
New Linux-only system-dependent bits headers.
* signal/bits/types/sig_atomic_t.h
* signal/bits/types/sigset_t.h
* signal/bits/types/sigval_t.h:
New non-system-dependent bits headers.
* sysdeps/generic/sigsetops.h
* sysdeps/unix/sysv/linux/sigsetops.h:
New internal headers.
* include/bits/types/sig_atomic_t.h
* include/bits/types/sigset_t.h
* include/bits/types/sigval_t.h:
New wrappers.
* signal/sigsetops.h
* bits/siginfo.h
* bits/sigset.h
* sysdeps/unix/sysv/linux/bits/siginfo.h
* sysdeps/unix/sysv/linux/bits/sigset.h
* sysdeps/unix/sysv/linux/ia64/bits/siginfo.h
* sysdeps/unix/sysv/linux/mips/bits/siginfo.h
* sysdeps/unix/sysv/linux/s390/bits/siginfo.h
* sysdeps/unix/sysv/linux/sparc/bits/siginfo.h
* sysdeps/unix/sysv/linux/tile/bits/siginfo.h
* sysdeps/unix/sysv/linux/x86/bits/siginfo.h:
Deleted.
* signal/Makefile, sysdeps/unix/sysv/linux/Makefile:
Update lists of installed headers.
* posix/bits/types.h: Define __sig_atomic_t here.
* signal/signal.h: Use the new bits headers; no need to handle
__need_sig_atomic_t nor __need_sigset_t. Don't use __sigmask
to define sigmask.
* include/signal.h: No need to handle __need_sig_atomic_t
nor __need_sigset_t. Don't define __sigemptyset.
* io/sys/poll.h, setjmp/setjmp.h
* sysdeps/arm/sys/ucontext.h, sysdeps/generic/sys/ucontext.h
* sysdeps/i386/sys/ucontext.h, sysdeps/m68k/sys/ucontext.h
* sysdeps/mach/hurd/i386/bits/sigcontext.h
* sysdeps/mips/sys/ucontext.h, sysdeps/powerpc/novmxsetjmp.h
* sysdeps/pthread/bits/sigthread.h
* sysdeps/unix/sysv/linux/hppa/sys/ucontext.h
* sysdeps/unix/sysv/linux/m68k/sys/ucontext.h
* sysdeps/unix/sysv/linux/mips/sys/ucontext.h
* sysdeps/unix/sysv/linux/nios2/sys/ucontext.h
* sysdeps/unix/sysv/linux/powerpc/sys/ucontext.h
* sysdeps/unix/sysv/linux/s390/sys/ucontext.h
* sysdeps/unix/sysv/linux/sh/sys/ucontext.h
* sysdeps/unix/sysv/linux/sparc/sys/ucontext.h
* sysdeps/unix/sysv/linux/tile/sys/ucontext.h
* sysdeps/unix/sysv/linux/x86/sys/ucontext.h:
Use bits/types/__sigset_t.h.
* misc/sys/select.h, posix/spawn.h
* sysdeps/unix/sysv/linux/powerpc/sys/ucontext.h
* sysdeps/unix/sysv/linux/sys/epoll.h
* sysdeps/unix/sysv/linux/sys/signalfd.h:
Use bits/types/sigset_t.h.
* resolv/netdb.h, rt/mqueue.h: Use bits/types/sigevent_t.h.
* rt/aio.h: Use bits/types/sigevent_t.h and bits/sigevent-consts.h.
* socket/sys/socket.h: Don't include bits/sigset.h.
* login/utmp_file.c, shadow/lckpwdf.c, signal/sigandset.c
* signal/sigisempty.c, stdlib/abort.c, sysdeps/posix/profil.c
* sysdeps/posix/sigignore.c, sysdeps/posix/sigintr.c
* sysdeps/posix/signal.c, sysdeps/posix/sigset.c
* sysdeps/posix/sprofil.c, sysdeps/posix/sysv_signal.c
* sysdeps/unix/sysv/linux/nptl-signals.h:
Include sigsetops.h.
* signal/sigaddset.c, signal/sigandset.c, signal/sigdelset.c
* signal/sigorset.c, stdlib/abort.c, sysdeps/posix/sigignore.c
* sysdeps/posix/signal.c, sysdeps/posix/sigset.c:
__sigaddset, __sigandset, __sigdelset, __sigemptyset, __sigorset
now return no value.
* signal/sigaddset.c, signal/sigdelset.c, signal/sigismem.c
Include <errno.h>, <signal.h>, and <sigsetops.h> instead of
"sigsetops.h".
* signal/sigsetops.c: Explicitly define __sigismember,
__sigaddset, and __sigdelset as compatibility symbols.
* signal/Versions: Correct commentary on __sigpause,
__sigaddset, __sigdelset, __sigismember.
* inet/rcmd.c: Include sigsetops.h. Convert old code using
__sigblock/__sigsetmask to use __sigprocmask and friends.
2016-12-02 00:24:13 +00:00
|
|
|
#include <sigsetops.h>
|
2017-11-01 01:10:37 +00:00
|
|
|
#include <stdbool.h>
|
2020-02-04 13:29:04 +00:00
|
|
|
#include <stddef.h>
|
2017-11-01 01:10:37 +00:00
|
|
|
#include <sysdep.h>
|
2016-01-19 19:33:32 +00:00
|
|
|
|
2014-07-31 18:37:48 +00:00
|
|
|
/* The signal used for asynchronous cancelation. */
|
|
|
|
#define SIGCANCEL __SIGRTMIN
|
|
|
|
|
|
|
|
|
|
|
|
/* Signal needed for the kernel-supported POSIX timer implementation.
|
|
|
|
We can reuse the cancellation signal since we can distinguish
|
|
|
|
cancellation from timer expirations. */
|
|
|
|
#define SIGTIMER SIGCANCEL
|
|
|
|
|
|
|
|
|
|
|
|
/* Signal used to implement the setuid et.al. functions. */
|
|
|
|
#define SIGSETXID (__SIGRTMIN + 1)
|
|
|
|
|
2016-01-19 19:33:32 +00:00
|
|
|
|
2021-03-15 20:22:15 +00:00
|
|
|
/* How many signal numbers need to be reserved for libpthread's private uses
|
|
|
|
(SIGCANCEL and SIGSETXID). */
|
|
|
|
#define RESERVED_SIGRT 2
|
|
|
|
|
|
|
|
|
2016-01-19 19:33:32 +00:00
|
|
|
/* Return is sig is used internally. */
|
2017-11-01 01:10:37 +00:00
|
|
|
static inline bool
|
2022-04-21 12:41:59 +00:00
|
|
|
is_internal_signal (int sig)
|
2016-01-19 19:33:32 +00:00
|
|
|
{
|
2017-11-04 00:37:55 +00:00
|
|
|
return (sig == SIGCANCEL) || (sig == SIGSETXID);
|
2016-01-19 19:33:32 +00:00
|
|
|
}
|
|
|
|
|
2016-04-22 12:25:20 +00:00
|
|
|
/* Remove internal glibc signal from the mask. */
|
|
|
|
static inline void
|
2022-04-21 12:41:59 +00:00
|
|
|
clear_internal_signals (sigset_t *set)
|
2016-04-22 12:25:20 +00:00
|
|
|
{
|
|
|
|
__sigdelset (set, SIGCANCEL);
|
|
|
|
__sigdelset (set, SIGSETXID);
|
|
|
|
}
|
|
|
|
|
2022-04-21 12:41:59 +00:00
|
|
|
static const internal_sigset_t sigall_set = {
|
|
|
|
.__val = {[0 ... __NSIG_WORDS-1 ] = -1 }
|
2019-12-09 17:33:33 +00:00
|
|
|
};
|
|
|
|
|
2022-04-21 12:41:59 +00:00
|
|
|
/* Obtain and change blocked signals, including internal glibc ones. */
|
|
|
|
static inline int
|
|
|
|
internal_sigprocmask (int how, const internal_sigset_t *set,
|
|
|
|
internal_sigset_t *oldset)
|
2016-04-22 12:25:20 +00:00
|
|
|
{
|
2022-04-21 12:41:59 +00:00
|
|
|
return INTERNAL_SYSCALL_CALL (rt_sigprocmask, how, set, oldset,
|
|
|
|
__NSIG_BYTES);
|
2016-04-22 12:25:20 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 12:41:59 +00:00
|
|
|
/* Block all signals, including internal glibc ones. */
|
2019-12-05 17:56:06 +00:00
|
|
|
static inline void
|
2022-04-21 12:41:59 +00:00
|
|
|
internal_signal_block_all (internal_sigset_t *oset)
|
2016-04-22 12:25:20 +00:00
|
|
|
{
|
2022-04-21 12:41:59 +00:00
|
|
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigall_set, oset,
|
2020-04-23 13:58:01 +00:00
|
|
|
__NSIG_BYTES);
|
2016-04-22 12:25:20 +00:00
|
|
|
}
|
|
|
|
|
2022-04-21 12:41:59 +00:00
|
|
|
/* Restore current process signal mask. */
|
2019-12-09 17:33:33 +00:00
|
|
|
static inline void
|
2022-04-21 12:41:59 +00:00
|
|
|
internal_signal_restore_set (const internal_sigset_t *set)
|
2019-12-09 17:33:33 +00:00
|
|
|
{
|
2022-04-21 12:41:59 +00:00
|
|
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, set, NULL,
|
2020-04-23 13:58:01 +00:00
|
|
|
__NSIG_BYTES);
|
2019-12-09 17:33:33 +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
|
|
|
static inline void
|
|
|
|
internal_signal_unblock_signal (int sig)
|
|
|
|
{
|
|
|
|
internal_sigset_t set;
|
|
|
|
internal_sigemptyset (&set);
|
|
|
|
internal_sigaddset (&set, sig);
|
|
|
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &set, NULL,
|
|
|
|
__NSIG_BYTES);
|
|
|
|
}
|
2019-12-09 17:33:33 +00:00
|
|
|
|
2022-04-21 12:41:59 +00:00
|
|
|
/* It is used on timer_create code directly on sigwaitinfo call, so it can not
|
|
|
|
use the internal_sigset_t definitions. */
|
|
|
|
static const sigset_t sigtimer_set = {
|
|
|
|
.__val = { [0] = __sigmask (SIGTIMER),
|
|
|
|
[1 ... _SIGSET_NWORDS-1] = 0
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Unblock only SIGTIMER. */
|
2019-12-05 17:56:06 +00:00
|
|
|
static inline void
|
2022-04-21 12:41:59 +00:00
|
|
|
signal_unblock_sigtimer (void)
|
2016-04-22 12:25:20 +00:00
|
|
|
{
|
2022-04-21 12:41:59 +00:00
|
|
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sigtimer_set, NULL,
|
2020-04-23 13:58:01 +00:00
|
|
|
__NSIG_BYTES);
|
2016-04-22 12:25:20 +00:00
|
|
|
}
|
2022-04-21 12:41:59 +00:00
|
|
|
|
2017-11-04 00:37:55 +00:00
|
|
|
#endif
|