Initialize the stack guard earlier when linking statically [BZ #7065]

The address of the stack canary is stored in a per-thread variable,
which means that we must ensure that the TLS area is intialized before
calling any -fstack-protector'ed functions.  For dynamically linked
applications, we ensure this (in a later patch) by disabling
-fstack-protector for the whole dynamic linker, but for static
applications, the AT_ENTRY address is called directly by the kernel, so
we must deal with the problem differently.

In static appliations, __libc_setup_tls performs the TCB setup and TLS
initialization, so this commit arranges for it to be called early and
unconditionally.  The call (and the stack guard initialization) is
before the DL_SYSDEP_OSCHECK hook, which if set will probably call
functions which are stack-protected (it does on Linux and NaCL too).  We
also move apply_irel up, so that we can still safely call functions that
require ifuncs while in __libc_setup_tls (though if stack-protection is
enabled we still have to avoid calling functions that are not
stack-protected at this stage).
This commit is contained in:
Nick Alcock 2016-12-26 10:08:34 +01:00 committed by Florian Weimer
parent 03baef1c9c
commit 003a27e819
5 changed files with 51 additions and 45 deletions

View File

@ -1,3 +1,22 @@
2016-12-26 Nick Alcock <nick.alcock@oracle.com>
Florian Weimer <fweimer@redhat.com>
[BZ #7065]
Initialize the stack guard earlier when linking statically.
* sysdeps/generic/ldsodefs.h (__libc_setup_tls)
(__pthread_initialize_minimal): Declare.
* csu/libc-start.c (__pthread_initialize_minimal): Remove
declaration.
(LIBC_START_MAIN): Call __libc_setup_tls early and directly. Move
stack canary and apply_irel initialization up. Call
__pthread_initialize_minimal only if linked in.
* csu/libc-tls.c (__libc_setup_tls): Replace arguments with their
constant values.
(__pthread_initialize_minimal): Remove.
* nptl/nptl-init.c (__libc_setup_tls): Remove declaration.
(__pthread_initialize_minimal_internal): Do not call
__libc_setup_tls.
2016-12-26 Nick Alcock <nick.alcock@oracle.com>
[BZ #7065]

View File

@ -29,7 +29,6 @@ extern int __libc_multiple_libcs;
#include <tls.h>
#ifndef SHARED
# include <dl-osinfo.h>
extern void __pthread_initialize_minimal (void);
# ifndef THREAD_SET_STACK_GUARD
/* Only exported for architectures that don't store the stack guard canary
in thread local area. */
@ -175,6 +174,20 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
}
}
/* Perform IREL{,A} relocations. */
apply_irel ();
/* The stack guard goes into the TCB, so initialize it early. */
__libc_setup_tls ();
/* Set up the stack checker's canary. */
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
# ifdef THREAD_SET_STACK_GUARD
THREAD_SET_STACK_GUARD (stack_chk_guard);
# else
__stack_chk_guard = stack_chk_guard;
# endif
# ifdef DL_SYSDEP_OSCHECK
if (!__libc_multiple_libcs)
{
@ -184,21 +197,9 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
}
# endif
/* Perform IREL{,A} relocations. */
apply_irel ();
/* Initialize the thread library at least a bit since the libgcc
functions are using thread functions if these are available and
we need to setup errno. */
__pthread_initialize_minimal ();
/* Set up the stack checker's canary. */
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
# ifdef THREAD_SET_STACK_GUARD
THREAD_SET_STACK_GUARD (stack_chk_guard);
# else
__stack_chk_guard = stack_chk_guard;
# endif
/* Initialize libpthread if linked in. */
if (__pthread_initialize_minimal != NULL)
__pthread_initialize_minimal ();
/* Set up the pointer guard value. */
uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,

View File

@ -102,14 +102,14 @@ init_static_tls (size_t memsz, size_t align)
}
void
__libc_setup_tls (size_t tcbsize, size_t tcbalign)
__libc_setup_tls (void)
{
void *tlsblock;
size_t memsz = 0;
size_t filesz = 0;
void *initimage = NULL;
size_t align = 0;
size_t max_align = tcbalign;
size_t max_align = TCB_ALIGNMENT;
size_t tcb_offset;
const ElfW(Phdr) *phdr;
@ -142,9 +142,9 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
_dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
and dl_tls_static_align. */
tcb_offset = roundup (memsz + GL(dl_tls_static_size), max_align);
tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
#elif TLS_DTV_AT_TP
tcb_offset = roundup (tcbsize, align ?: 1);
tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
tlsblock = __sbrk (tcb_offset + memsz + max_align
+ TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
tlsblock += TLS_PRE_TCB_SIZE;
@ -215,12 +215,3 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
}
/* This is the minimal initialization function used when libpthread is
not used. */
void
__attribute__ ((weak))
__pthread_initialize_minimal (void)
{
__libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
}

View File

@ -70,10 +70,6 @@ int __have_futex_clock_realtime;
static const char nptl_version[] __attribute_used__ = VERSION;
#ifndef SHARED
extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
#endif
#ifdef SHARED
static
#else
@ -288,18 +284,6 @@ static bool __nptl_initial_report_events __attribute_used__;
void
__pthread_initialize_minimal_internal (void)
{
#ifndef SHARED
/* Unlike in the dynamically linked case the dynamic linker has not
taken care of initializing the TLS data structures. */
__libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
/* We must prevent gcc from being clever and move any of the
following code ahead of the __libc_setup_tls call. This function
will initialize the thread register which is subsequently
used. */
__asm __volatile ("");
#endif
/* Minimal initialization of the thread descriptor. */
struct pthread *pd = THREAD_SELF;
__pthread_initialize_pids (pd);

View File

@ -994,6 +994,17 @@ extern size_t _dl_count_modids (void) internal_function attribute_hidden;
/* Calculate offset of the TLS blocks in the static TLS block. */
extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden;
#ifndef SHARED
/* Set up the TCB for statically linked applications. This is called
early during startup because we always use TLS (for errno and the
stack protector, among other things). */
void __libc_setup_tls (void);
/* Initialization of libpthread for statically linked applications.
If libpthread is not linked in, this is an empty function. */
void __pthread_initialize_minimal (void) weak_function;
#endif
/* Allocate memory for static TLS block (unless MEM is nonzero) and dtv. */
extern void *_dl_allocate_tls (void *mem) internal_function;
rtld_hidden_proto (_dl_allocate_tls)