From patchwork Sun Feb 28 16:41:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nix X-Patchwork-Id: 11122 Received: (qmail 82775 invoked by alias); 28 Feb 2016 16:41:41 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 82746 invoked by uid 89); 28 Feb 2016 16:41:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.4 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=statically, UD:7.0.198.g6dd47b6, UD:2.7.0.198.g6dd47b6, sk:2.7.0.1 X-HELO: mail.esperi.org.uk From: Nix To: libc-alpha@sourceware.org Subject: [PATCH 02/16] Initialize the stack guard earlier when linking statically. Date: Sun, 28 Feb 2016 16:41:21 +0000 Message-Id: <1456677695-29778-3-git-send-email-nix@esperi.org.uk> In-Reply-To: <1456677695-29778-1-git-send-email-nix@esperi.org.uk> References: <1456677695-29778-1-git-send-email-nix@esperi.org.uk> X-DCC-URT-Metrics: spindle 1060; Body=1 Fuz1=1 Fuz2=1 From: Nick Alcock 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. So split out the part of pthread initialization that sets up the TCB (and, more generally, the TLS area) into a separate function (twice -- there is one implementation in libpthread.a, and another outside it for programs that do not link with libpthread), then call it at initialization time. Call that, and move the stack guard initialization above the DL_SYSDEP_OSCHECK hook, which if set will probably call functions which are stack-protected (it does on Linux and NaCL too). We do not move apply_irel() up, because applying irels can require state set up by the DL_SYSDEP_OSCHECK hook on some platforms. This means, as a consequence, that __pthread_initialize_tcb_internal() had better not call anything that requires ifuncs. (This is dealt with in a later patch.) v2: describe why we don't move apply_irel() up, and the consequences. --- csu/libc-start.c | 20 ++++++++++++-------- csu/libc-tls.c | 8 ++++++++ nptl/nptl-init.c | 11 +++++++---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/csu/libc-start.c b/csu/libc-start.c index f4aa01a..140b079 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -33,6 +33,7 @@ extern int __libc_multiple_libcs; #ifndef SHARED # include extern void __pthread_initialize_minimal (void); +extern void __pthread_initialize_tcb_internal (void); # ifndef THREAD_SET_STACK_GUARD /* Only exported for architectures that don't store the stack guard canary in thread local area. */ @@ -178,6 +179,17 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), } } + /* The stack guard goes into the TCB. */ + __pthread_initialize_tcb_internal (); + + /* 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) { @@ -195,14 +207,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), 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 - /* Set up the pointer guard value. */ uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); diff --git a/csu/libc-tls.c b/csu/libc-tls.c index d6425e0..3d67a64 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -241,5 +241,13 @@ void __attribute__ ((weak)) __pthread_initialize_minimal (void) { +} + +/* This is the minimal initialization function used when libpthread is + not used. */ +void +__attribute__ ((weak)) +__pthread_initialize_tcb_internal (void) +{ __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN); } diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c index bdbdfed..a4626be 100644 --- a/nptl/nptl-init.c +++ b/nptl/nptl-init.c @@ -296,21 +296,24 @@ extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); /* This can be set by the debugger before initialization is complete. */ static bool __nptl_initial_report_events __attribute_used__; +#ifndef SHARED void -__pthread_initialize_minimal_internal (void) +__pthread_initialize_tcb_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 + /* We must prevent gcc from being clever after inlining and moving 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 - +void +__pthread_initialize_minimal_internal (void) +{ /* Minimal initialization of the thread descriptor. */ struct pthread *pd = THREAD_SELF; __pthread_initialize_pids (pd);