Patch [1/4] async-signal safe TLS.

2013-12-18  Andrew Hunter  <ahh@google.com>

	* sysdeps/generic/ldsodefs.h (_dl_mask_all_signals): New prototype.
	(_dl_unmask_signals): Likewise.
	* sysdeps/mach/hurd/dl-sysdep.h (_dl_mask_all_signals): New stub.
	(_dl_unmask_all_signals): Likewise.
	* sysdeps/unix/sysv/linux/dl-sysdep.h (_dl_mask_all_signals): New prototype.
	(_dl_unmask_all_signals): Likewise.
	* sysdeps/unix/sysv/linux/dl-sysdep.c (_dl_mask_all_signals): New function.
	(_dl_unmask_signals): Likewise.
This commit is contained in:
Paul Pluzhnikov 2013-12-18 15:07:11 -08:00
parent a588438951
commit 69a17d9d24
5 changed files with 73 additions and 0 deletions

View File

@ -1,3 +1,14 @@
2013-12-18 Andrew Hunter <ahh@google.com>
* sysdeps/generic/ldsodefs.h (_dl_mask_all_signals): New prototype.
(_dl_unmask_signals): Likewise.
* sysdeps/mach/hurd/dl-sysdep.h (_dl_mask_all_signals): New stub.
(_dl_unmask_all_signals): Likewise.
* sysdeps/unix/sysv/linux/dl-sysdep.h (_dl_mask_all_signals): New prototype.
(_dl_unmask_all_signals): Likewise.
* sysdeps/unix/sysv/linux/dl-sysdep.c (_dl_mask_all_signals): New function.
(_dl_unmask_signals): Likewise.
2013-12-18 Brooks Moses <bmoses@google.com>
[BZ #15846]

View File

@ -234,6 +234,11 @@ extern int _dl_name_match_p (const char *__name, const struct link_map *__map)
extern unsigned long int _dl_higher_prime_number (unsigned long int n)
internal_function;
/* Mask every signal, returning the previous sigmask in OLD. */
extern void _dl_mask_all_signals (sigset_t *old) internal_function;
/* Undo _dl_mask_all_signals. */
extern void _dl_unmask_signals (sigset_t *old) internal_function;
/* Function used as argument for `_dl_receive_error' function. The
arguments are the error code, error string, and the objname the
error occurred in. */

View File

@ -29,3 +29,10 @@
# define DL_ARGV_NOT_RELRO 1
# define LIBC_STACK_END_NOT_RELRO 1
#endif
#include <signal.h>
inline void _dl_mask_all_signals (sigset_t *) internal_function;
inline void _dl_mask_all_signals (sigset_t *) { }
inline void _dl_unmask_all_signals (sigset_t *) internal_function;
inline void _dl_unmask_all_signals (sigset_t *) { }

View File

@ -19,6 +19,7 @@
/* Linux needs some special initialization, but otherwise uses
the generic dynamic linker system interface code. */
#include <assert.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
@ -130,3 +131,48 @@ _dl_discover_osversion (void)
return version;
}
/* Mask every signal, returning the previous sigmask in OLD. */
void
internal_function
_dl_mask_all_signals (sigset_t *old)
{
int ret;
sigset_t new;
sigfillset (&new);
/* This function serves as a replacement to pthread_sigmask, which
isn't available from within the dynamic linker since it would require
linking with libpthread. We duplicate some of the functionality here
to avoid requiring libpthread. This isn't quite identical to
pthread_sigmask in that we do not mask internal signals used for
cancellation and setxid handling. This disables asynchronous
cancellation for the duration the signals are disabled, but it's a
small window, and prevents any problems with the use of TLS variables
in the signal handlers that would have executed. */
/* It's very important we don't touch errno here, as that's TLS; since this
gets called from get_tls_addr we might end up recursing. */
INTERNAL_SYSCALL_DECL (err);
ret = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &new, old,
_NSIG / 8);
assert (ret == 0);
}
/* Return sigmask to what it was before a call to _dl_mask_all_signals. */
void
internal_function
_dl_unmask_signals (sigset_t *old)
{
int ret;
INTERNAL_SYSCALL_DECL (err);
ret = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, old, NULL,
_NSIG / 8);
assert (ret == 0);
}

View File

@ -30,4 +30,8 @@
/* Get version of the OS. */
extern int _dl_discover_osversion (void) attribute_hidden;
# define HAVE_DL_DISCOVER_OSVERSION 1
#include <signal.h>
void _dl_mask_all_signals (sigset_t *) internal_function;
void _dl_unmask_all_signals (sigset_t *) internal_function;
#endif