From patchwork Wed Dec 21 20:15:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 707945 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tkQrb69r1z9t0w for ; Thu, 22 Dec 2016 07:15:43 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="wg4d/WVi"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:cc:from:message-id:date :mime-version:in-reply-to:content-type; q=dns; s=default; b=veBy G0QcsyyZZZ80l7xemJPa6hGBQSeZzdpXbqlvXQaYZyn/W/qw+QWs1FvlbKQnWpRs knJ8rbAq7UnglLF8uOAA+Te+iu03XTvSq9tkzxIbGHXcA1de+Z25xi0qJXvEfA+t KR5ccWt9Z9hV2O1SfrCkkh9cx0lXuL46jm9IkxA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:cc:from:message-id:date :mime-version:in-reply-to:content-type; s=default; bh=bxyos2RUtN h1unvch4IZPM0WHzg=; b=wg4d/WViIYExxPECf/rlqULV2UoZa+Y3gXjibPwoxj 1wEoKB1pK3JngkKt7aG5owQxyVe9Re7wr9FYDIOFEhUThkGh/S4Ql9h+O9ZS5UFl OPOaGqFgu160W7HWjna6wQR3sy9qw86kHE0idykeOwPpmy8PJJ/L3kaQNIQ/eLEx U= Received: (qmail 85712 invoked by alias); 21 Dec 2016 20:15:32 -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 85671 invoked by uid 89); 21 Dec 2016 20:15:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.0 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=subsequently X-HELO: mx1.redhat.com Subject: Re: [PATCH 02/15] Initialize the stack guard earlier when linking statically. To: Nix References: <20161219111528.14969-1-nix@esperi.org.uk> <20161219111528.14969-3-nix@esperi.org.uk> <5a33f534-3001-0741-66d2-2b19fcaab819@redhat.com> Cc: libc-alpha@sourceware.org From: Florian Weimer Message-ID: <1c236707-0c8c-2033-28b7-abc427d56942@redhat.com> Date: Wed, 21 Dec 2016 21:15:08 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 In-Reply-To: <5a33f534-3001-0741-66d2-2b19fcaab819@redhat.com> On 12/21/2016 03:16 PM, Florian Weimer wrote: > I'm changing this to call __libc_setup_tls directly. This functions is > in csu/ and thus automatically exempted from stack protection. There is > no need to go indirectly through a definition in nptl/. I should have attached the patch. Florian 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). 2016-12-21 Nick Alcock Florian Weimer [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. diff --git a/csu/libc-start.c b/csu/libc-start.c index 99c040a..cc59073 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -29,7 +29,6 @@ extern int __libc_multiple_libcs; #include #ifndef SHARED # include -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,22 +174,11 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), } } -# ifdef DL_SYSDEP_OSCHECK - if (!__libc_multiple_libcs) - { - /* This needs to run to initiliaze _dl_osversion before TLS - setup might check it. */ - DL_SYSDEP_OSCHECK (__libc_fatal); - } -# 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 (); + /* 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); @@ -200,6 +188,19 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __stack_chk_guard = stack_chk_guard; # endif +# ifdef DL_SYSDEP_OSCHECK + if (!__libc_multiple_libcs) + { + /* This needs to run to initiliaze _dl_osversion before TLS + setup might check it. */ + DL_SYSDEP_OSCHECK (__libc_fatal); + } +# 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, stack_chk_guard); diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 8f92234..454f165 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -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); -} diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c index 0fd54a0..8494b26 100644 --- a/nptl/nptl-init.c +++ b/nptl/nptl-init.c @@ -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); diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 34d7ec1..bb67840 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -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)