mirror of git://sourceware.org/git/glibc.git
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>
|
||
|---|---|---|
| .. | ||
| Depend | ||
| Makefile | ||
| Versions | ||
| asprintf_chk.c | ||
| backtrace-tst.c | ||
| backtrace.c | ||
| backtracesyms.c | ||
| backtracesymsfd.c | ||
| chk_fail.c | ||
| confstr_chk.c | ||
| dprintf_chk.c | ||
| execinfo.h | ||
| explicit_bzero_chk.c | ||
| fdelt_chk.c | ||
| fgets_chk.c | ||
| fgets_u_chk.c | ||
| fgetws_chk.c | ||
| fgetws_u_chk.c | ||
| fortify_fail.c | ||
| fprintf_chk.c | ||
| fread_chk.c | ||
| fread_u_chk.c | ||
| fwprintf_chk.c | ||
| getcwd_chk.c | ||
| getdomainname_chk.c | ||
| getgroups_chk.c | ||
| gethostname_chk.c | ||
| gets_chk.c | ||
| getwd_chk.c | ||
| longjmp_chk.c | ||
| mbsnrtowcs_chk.c | ||
| mbsrtowcs_chk.c | ||
| mbstowcs_chk.c | ||
| memcpy_chk.c | ||
| memmove_chk.c | ||
| mempcpy_chk.c | ||
| memset_chk.c | ||
| noophooks.c | ||
| obprintf_chk.c | ||
| pcprofile.c | ||
| pcprofiledump.c | ||
| poll_chk.c | ||
| ppoll_chk.c | ||
| pread64_chk.c | ||
| pread_chk.c | ||
| printf_chk.c | ||
| read_chk.c | ||
| readlink_chk.c | ||
| readlinkat_chk.c | ||
| readonly-area.c | ||
| realpath_chk.c | ||
| recv_chk.c | ||
| recvfrom_chk.c | ||
| snprintf_chk.c | ||
| sprintf_chk.c | ||
| stack_chk_fail.c | ||
| stack_chk_fail_local.c | ||
| stpcpy_chk.c | ||
| stpncpy_chk.c | ||
| strcat_chk.c | ||
| strcpy_chk.c | ||
| strlcat_chk.c | ||
| strlcpy_chk.c | ||
| strncat_chk.c | ||
| strncpy_chk.c | ||
| swprintf_chk.c | ||
| test-stpcpy_chk.c | ||
| test-strcpy_chk.c | ||
| tst-backtrace.h | ||
| tst-backtrace2.c | ||
| tst-backtrace3.c | ||
| tst-backtrace4.c | ||
| tst-backtrace5.c | ||
| tst-backtrace6.c | ||
| tst-chk-cancel.c | ||
| tst-fortify-syslog.c | ||
| tst-fortify-wide.c | ||
| tst-fortify.c | ||
| tst-longjmp_chk.c | ||
| tst-longjmp_chk2.c | ||
| tst-longjmp_chk3.c | ||
| tst-realpath-chk.c | ||
| tst-sprintf-fortify-rdonly.c | ||
| tst-sprintf-fortify-unchecked.c | ||
| tst-ssp-1.c | ||
| ttyname_r_chk.c | ||
| vasprintf_chk.c | ||
| vdprintf_chk.c | ||
| vfprintf_chk.c | ||
| vfwprintf_chk.c | ||
| vobprintf_chk.c | ||
| vprintf_chk.c | ||
| vsnprintf_chk.c | ||
| vsprintf_chk.c | ||
| vswprintf_chk.c | ||
| vwprintf_chk.c | ||
| wcpcpy_chk.c | ||
| wcpncpy_chk.c | ||
| wcrtomb_chk.c | ||
| wcscat_chk.c | ||
| wcscpy_chk.c | ||
| wcslcat_chk.c | ||
| wcslcpy_chk.c | ||
| wcsncat_chk.c | ||
| wcsncpy_chk.c | ||
| wcsnrtombs_chk.c | ||
| wcsrtombs_chk.c | ||
| wcstombs_chk.c | ||
| wctomb_chk.c | ||
| wmemcpy_chk.c | ||
| wmemmove_chk.c | ||
| wmempcpy_chk.c | ||
| wmemset_chk.c | ||
| wprintf_chk.c | ||
| xtrace.sh | ||