From patchwork Wed May 4 16:47:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 53469 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2D9ED385782C for ; Wed, 4 May 2022 16:47:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2D9ED385782C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1651682879; bh=8NTQJ+xmau0U0fJSQUuFqjoz2rZ071CHDsJCr02sVNU=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=cFy0+qsPZMDwgXLY25lExR9SX/ol+GN4u3zLoGSD4ixswmE/CDAlHaZb9dv7Z+gS6 GRSHQFEhcFuYjDS5VkCynuu4hl6SOUn1JIqiV0Q7CGH8TlTfUQIOdx53wq1hgFSb3z S5kvHiLEs6G9ZaqU9O1cyeahDxLzcDiwD+8b7kzg= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 768F23858C53 for ; Wed, 4 May 2022 16:47:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 768F23858C53 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-104-2evou7_fMVG_ozMfhYLKmg-1; Wed, 04 May 2022 12:47:37 -0400 X-MC-Unique: 2evou7_fMVG_ozMfhYLKmg-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DAB5C800B21; Wed, 4 May 2022 16:47:36 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.40]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0CD29455D69; Wed, 4 May 2022 16:47:35 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH v2 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro X-From-Line: aaebc7f81d38f328e69ee39b970be9f01bed33a7 Mon Sep 17 00:00:00 2001 Message-Id: Date: Wed, 04 May 2022 18:47:34 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" And keep the previous definition if it exists. This allows disabling IA64_USE_NEW_STUB while keeping USE_DL_SYSINFO defined. --- v2: New patch. sysdeps/unix/sysv/linux/ia64/brk.c | 3 +-- sysdeps/unix/sysv/linux/ia64/sysdep.h | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) base-commit: c1b68685d438373efe64e5f076f4215723004dfb diff --git a/sysdeps/unix/sysv/linux/ia64/brk.c b/sysdeps/unix/sysv/linux/ia64/brk.c index 65142aeae9..e1fa88f9b0 100644 --- a/sysdeps/unix/sysv/linux/ia64/brk.c +++ b/sysdeps/unix/sysv/linux/ia64/brk.c @@ -16,7 +16,6 @@ License along with the GNU C Library; if not, see . */ -#include /* brk is used by statup before TCB is properly set. */ -#undef USE_DL_SYSINFO +#define IA64_USE_NEW_STUB 0 #include diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h index 193ecee023..72b72acb6f 100644 --- a/sysdeps/unix/sysv/linux/ia64/sysdep.h +++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h @@ -44,12 +44,17 @@ #undef SYS_ify #define SYS_ify(syscall_name) __NR_##syscall_name -#if defined USE_DL_SYSINFO \ +#ifndef IA64_USE_NEW_STUB +# if defined USE_DL_SYSINFO \ && (IS_IN (libc) \ || IS_IN (libpthread) || IS_IN (librt)) -# define IA64_USE_NEW_STUB -#else -# undef IA64_USE_NEW_STUB +# define IA64_USE_NEW_STUB 1 +# else +# define IA64_USE_NEW_STUB 0 +# endif +#endif +#if IA64_USE_NEW_STUB && !USE_DL_SYSINFO +# error IA64_USE_NEW_STUB needs USE_DL_SYSINFO #endif #ifdef __ASSEMBLER__ @@ -101,7 +106,7 @@ mov r15=num; \ break __IA64_BREAK_SYSCALL -#ifdef IA64_USE_NEW_STUB +#if IA64_USE_NEW_STUB # ifdef SHARED # define DO_CALL(num) \ .prologue; \ @@ -185,7 +190,7 @@ (non-negative) errno on error or the return value on success. */ -#ifdef IA64_USE_NEW_STUB +#if IA64_USE_NEW_STUB # define INTERNAL_SYSCALL_NCS(name, nr, args...) \ ({ \ @@ -277,7 +282,7 @@ #define ASM_OUTARGS_5 ASM_OUTARGS_4, "=r" (_out4) #define ASM_OUTARGS_6 ASM_OUTARGS_5, "=r" (_out5) -#ifdef IA64_USE_NEW_STUB +#if IA64_USE_NEW_STUB #define ASM_ARGS_0 #define ASM_ARGS_1 ASM_ARGS_0, "4" (_out0) #define ASM_ARGS_2 ASM_ARGS_1, "5" (_out1) @@ -313,7 +318,7 @@ /* Branch registers. */ \ "b6" -#ifdef IA64_USE_NEW_STUB +#if IA64_USE_NEW_STUB # define ASM_CLOBBERS_6 ASM_CLOBBERS_6_COMMON #else # define ASM_CLOBBERS_6 ASM_CLOBBERS_6_COMMON , "b7" From patchwork Wed May 4 16:48:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 53470 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6A3D6385734B for ; Wed, 4 May 2022 16:49:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6A3D6385734B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1651682956; bh=2TegBWK/gupEspWoxzNT/yMCi/sRRJx/opa3WNwoAX0=; h=To:Subject:In-Reply-To:References:Date:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=pWUiCY/g3TwvW9PrDPOli1988JyqXXVs7ROUIZ7QXESaW6m49R1EYIbwwVRYetYti NkSpAuRYMxTx0udG7tBmfkX8F6Wpy+Mv0hpmykScEp0T4wS90zFaqzEcEvg+Tt5Wgu /oCrRVVIwayvn8lWQy7Xt0XEsksimHuoJbC2R3Cs= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 1EACD3858C53 for ; Wed, 4 May 2022 16:48:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1EACD3858C53 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-655-WSiFA_SeM_OMJRra0y0KKQ-1; Wed, 04 May 2022 12:48:50 -0400 X-MC-Unique: WSiFA_SeM_OMJRra0y0KKQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 961D238149A3; Wed, 4 May 2022 16:48:50 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.40]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5B1FD15674F3; Wed, 4 May 2022 16:48:49 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH v2 2/3] Linux: Implement a useful version of _startup_fatal In-Reply-To: References: X-From-Line: 63235b8cfce808ff0c6fd07d5710faaf2e692f88 Mon Sep 17 00:00:00 2001 Message-Id: <63235b8cfce808ff0c6fd07d5710faaf2e692f88.1651682800.git.fweimer@redhat.com> Date: Wed, 04 May 2022 18:48:47 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" On i386 and ia64, the TCB is not available at this point. --- v2: Add ia64 override. On i386, use non-TCB version for non-PIE static, too. sysdeps/unix/sysv/linux/i386/startup.h | 21 ++------------ sysdeps/unix/sysv/linux/ia64/startup.h | 22 +++++++++++++++ sysdeps/unix/sysv/linux/startup.h | 38 ++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/ia64/startup.h create mode 100644 sysdeps/unix/sysv/linux/startup.h diff --git a/sysdeps/unix/sysv/linux/i386/startup.h b/sysdeps/unix/sysv/linux/i386/startup.h index 67c9310f3a..85534d09f1 100644 --- a/sysdeps/unix/sysv/linux/i386/startup.h +++ b/sysdeps/unix/sysv/linux/i386/startup.h @@ -16,22 +16,7 @@ License along with the GNU C Library; if not, see . */ -#if BUILD_PIE_DEFAULT -/* Can't use "call *%gs:SYSINFO_OFFSET" during statup in static PIE. */ -# define I386_USE_SYSENTER 0 +/* Can't use "call *%gs:SYSINFO_OFFSET" during statup. */ +#define I386_USE_SYSENTER 0 -# include -# include - -__attribute__ ((__noreturn__)) -static inline void -_startup_fatal (const char *message __attribute__ ((unused))) -{ - /* This is only called very early during startup in static PIE. - FIXME: How can it be improved? */ - ABORT_INSTRUCTION; - __builtin_unreachable (); -} -#else -# include_next -#endif +#include_next diff --git a/sysdeps/unix/sysv/linux/ia64/startup.h b/sysdeps/unix/sysv/linux/ia64/startup.h new file mode 100644 index 0000000000..68fcd9fea0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/startup.h @@ -0,0 +1,22 @@ +/* Linux/ia64 definitions of functions used by static libc main startup. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This code is used before the TCB is set up. */ +#define IA64_USE_NEW_STUB 0 + +#include_next diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h new file mode 100644 index 0000000000..a5de941759 --- /dev/null +++ b/sysdeps/unix/sysv/linux/startup.h @@ -0,0 +1,38 @@ +/* Linux definitions of functions used by static libc main startup. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifdef SHARED +# include_next +#else +# include + +/* Avoid a run-time invocation of strlen. */ +#define _startup_fatal(message) \ + do \ + { \ + size_t message_length = __builtin_strlen (message); \ + if (! __builtin_constant_p (message_length)) \ + { \ + extern void _startup_fatal_not_constant (void); \ + _startup_fatal_not_constant (); \ + } \ + INTERNAL_SYSCALL_CALL (write, STDERR_FILENO, message, message_length); \ + INTERNAL_SYSCALL_CALL (exit_group, 127); \ + } \ + while (0) +#endif /* !SHARED */ From patchwork Wed May 4 16:49:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 53471 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 567333857375 for ; Wed, 4 May 2022 16:49:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 567333857375 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1651682999; bh=5Gmfs9PKUJK9XsNdpVezMwS97PCMg8Vh2qUpbb+Kch8=; h=To:Subject:In-Reply-To:References:Date:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=dLaJ0dWz5p+yu9WhtHfO8jGo9Jb8kYoS6lkJvTb0Fpl7jCZF3Zmu13djxzzUJlTu+ GOkhLjIT9Tly/+2hdEBnFQj7HERJSOF/4xUXVEP1//+Ao1VXVYeE65m0HQCHmY26lZ NmuYqjfsHR87fD1xOx4rkeA8LFzJWxWg0+H8ivKM= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 64DDD3857351 for ; Wed, 4 May 2022 16:49:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 64DDD3857351 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-530-TlwkXQ5CPUizZal5649kRA-1; Wed, 04 May 2022 12:49:29 -0400 X-MC-Unique: TlwkXQ5CPUizZal5649kRA-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 50F1D802803 for ; Wed, 4 May 2022 16:49:29 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.40]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 46687455921 for ; Wed, 4 May 2022 16:49:28 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH v2 3/3] csu: Implement and use _dl_early_allocate during static startup In-Reply-To: References: X-From-Line: efedd33164138409c6c345180e0a04a7d99d5915 Mon Sep 17 00:00:00 2001 Message-Id: Date: Wed, 04 May 2022 18:49:26 +0200 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" This implements mmap fallback for a brk failure during TLS allocation. scripts/tls-elf-edit.py is updated to support the new patching method. The script no longer requires that in the input object is of ET_DYN type. --- v2: Unchanged. csu/libc-tls.c | 12 ++- elf/Makefile | 19 +++++ elf/dl-early_allocate.c | 30 ++++++++ elf/tst-tls-allocation-failure-static.c | 31 ++++++++ scripts/tst-elf-edit.py | 34 +++++++-- sysdeps/generic/ldsodefs.h | 5 ++ sysdeps/unix/sysv/linux/dl-early_allocate.c | 81 +++++++++++++++++++++ 7 files changed, 202 insertions(+), 10 deletions(-) create mode 100644 elf/dl-early_allocate.c create mode 100644 elf/tst-tls-allocation-failure-static.c create mode 100644 sysdeps/unix/sysv/linux/dl-early_allocate.c diff --git a/csu/libc-tls.c b/csu/libc-tls.c index bef92a7568..7d311056bc 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -145,11 +145,16 @@ __libc_setup_tls (void) _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign and dl_tls_static_align. */ tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align); - tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align); + tlsblock = _dl_early_allocate (tcb_offset + TLS_INIT_TCB_SIZE + max_align); + if (tlsblock == NULL) + _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n"); #elif TLS_DTV_AT_TP tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1); - tlsblock = __sbrk (tcb_offset + memsz + max_align - + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus)); + tlsblock = _dl_early_allocate (tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + + GLRO(dl_tls_static_surplus)); + if (tlsblock == NULL) + _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n"); tlsblock += TLS_PRE_TCB_SIZE; #else /* In case a model with a different layout for the TCB and DTV @@ -157,6 +162,7 @@ __libc_setup_tls (void) # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" #endif + /* Align the TLS block. */ tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) & ~(max_align - 1)); diff --git a/elf/Makefile b/elf/Makefile index fc9860edee..ce3345ed92 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -33,6 +33,7 @@ routines = \ $(all-dl-routines) \ dl-addr \ dl-addr-obj \ + dl-early_allocate \ dl-error \ dl-iteratephdr \ dl-libc \ @@ -108,6 +109,7 @@ all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. elide-routines.os = \ $(all-dl-routines) \ + dl-early_allocate \ dl-exception \ dl-origin \ dl-reloc-static-pie \ @@ -276,6 +278,7 @@ tests-static-normal := \ tst-linkall-static \ tst-single_threaded-pthread-static \ tst-single_threaded-static \ + tst-tls-allocation-failure-static \ tst-tlsalign-extern-static \ tst-tlsalign-static \ # tests-static-normal @@ -1213,6 +1216,10 @@ $(objpfx)tst-glibcelf.out: tst-glibcelf.py elf.h $(..)/scripts/glibcelf.py \ --cc="$(CC) $(patsubst -DMODULE_NAME=%,-DMODULE_NAME=testsuite,$(CPPFLAGS))" \ < /dev/null > $@ 2>&1; $(evaluate-test) +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-tls-allocation-failure-static-patched.out +endif + # The test requires shared _and_ PIE because the executable # unit test driver must be able to link with the shared object # that is going to eventually go into an installed DSO. @@ -2937,3 +2944,15 @@ $(eval $(call tst-trace-skeleton,4,\ $(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4)) $(eval $(call tst-trace-skeleton,5,\ $(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4:$(objpfx)libtracemod5)) + +$(objpfx)tst-tls-allocation-failure-static-patched: \ + $(objpfx)tst-tls-allocation-failure-static $(..)scripts/tst-elf-edit.py + cp $< $@ + $(PYTHON) $(..)scripts/tst-elf-edit.py --maximize-tls-size $@ + +$(objpfx)tst-tls-allocation-failure-static-patched.out: \ + $(objpfx)tst-tls-allocation-failure-static-patched + $< > $@ 2>&1; echo "status: $$?" >> $@ + grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \ + && grep -q '^status: 127$$' $@; \ + $(evaluate-test) diff --git a/elf/dl-early_allocate.c b/elf/dl-early_allocate.c new file mode 100644 index 0000000000..d7f59d41e5 --- /dev/null +++ b/elf/dl-early_allocate.c @@ -0,0 +1,30 @@ +/* Early memory allocation for the dynamic loader. Generic version. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +void * +_dl_early_allocate (size_t size) +{ + void *result = __sbrk (size); + if (result == (void *) -1) + _dl_fatal_printf ("Fatal glibc error: Early memory allocation failed\n"); + return result; +} diff --git a/elf/tst-tls-allocation-failure-static.c b/elf/tst-tls-allocation-failure-static.c new file mode 100644 index 0000000000..8de831b246 --- /dev/null +++ b/elf/tst-tls-allocation-failure-static.c @@ -0,0 +1,31 @@ +/* Base for test program with impossiblyh large PT_TLS segment. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* The test actual binary is patched using scripts/tst-elf-edit.py + --maximize-tls-size, and this introduces the expected test + allocation failure due to an excessive PT_LS p_memsz value. + + Patching the binary is required because on some 64-bit targets, TLS + relocations can only cover a 32-bit range, and glibc-internal TLS + variables such as errno end up outside that range. */ + +int +main (void) +{ + return 0; +} diff --git a/scripts/tst-elf-edit.py b/scripts/tst-elf-edit.py index a514179bbf..0e19ce1e73 100644 --- a/scripts/tst-elf-edit.py +++ b/scripts/tst-elf-edit.py @@ -43,9 +43,11 @@ EI_DATA=5 ELFDATA2LSB=b'\x01' ELFDATA2MSB=b'\x02' +ET_EXEC=2 ET_DYN=3 PT_LOAD=1 +PT_TLS=7 def elf_types_fmts(e_ident): endian = '<' if e_ident[EI_DATA] == ELFDATA2LSB else '>' @@ -146,8 +148,15 @@ def elf_edit_align(phdr, align): else: phdr.p_align = int(align) +def elf_edit_maximize_tls_size(phdr, elfclass): + if elfclass == ELFCLASS32: + # It is possible that the kernel can allocate half of the + # address space, so use something larger. + phdr.p_memsz = 0xfff00000 + else: + phdr.p_memsz = 1 << 63 -def elf_edit(f, align): +def elf_edit(f, opts): ei_nident_fmt = 'c' * EI_NIDENT ei_nident_len = struct.calcsize(ei_nident_fmt) @@ -172,24 +181,35 @@ def elf_edit(f, align): ehdr = Elf_Ehdr(e_ident) ehdr.read(f) - if ehdr.e_type != ET_DYN: - error('{}: not a shared library'.format(f.name)) + if ehdr.e_type not in (ET_EXEC, ET_DYN): + error('{}: not an executable or shared library'.format(f.name)) phdr = Elf_Phdr(e_ident) + maximize_tls_size_done = False for i in range(0, ehdr.e_phnum): f.seek(ehdr.e_phoff + i * phdr.len) phdr.read(f) - if phdr.p_type == PT_LOAD: - elf_edit_align(phdr, align) + if phdr.p_type == PT_LOAD and opts.align is not None: + elf_edit_align(phdr, opts.align) + f.seek(ehdr.e_phoff + i * phdr.len) + phdr.write(f) + break + if phdr.p_type == PT_TLS and opts.maximize_tls_size: + elf_edit_maximize_tls_size(phdr, e_ident[EI_CLASS]) f.seek(ehdr.e_phoff + i * phdr.len) phdr.write(f) + maximize_tls_size_done = True break + if opts.maximize_tls_size and not maximize_tls_size_done: + error('{}: TLS maximum size was not updated'.format(f.name)) def get_parser(): parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('-a', dest='align', required=True, + parser.add_argument('-a', dest='align', help='How to set the LOAD alignment') + parser.add_argument('--maximize-tls-size', action='store_true', + help='Set maximum PT_TLS size') parser.add_argument('output', help='ELF file to edit') return parser @@ -199,7 +219,7 @@ def main(argv): parser = get_parser() opts = parser.parse_args(argv) with open(opts.output, 'r+b') as fout: - elf_edit(fout, opts.align) + elf_edit(fout, opts) if __name__ == '__main__': diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 4a5e698db2..5d0369358d 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1211,6 +1211,11 @@ extern struct link_map * _dl_get_dl_main_map (void) # endif #endif +/* Perform early memory allocation, avoding a TCB dependency. + Terminate the process if allocation fails. May attempt to use + brk. */ +void *_dl_early_allocate (size_t size) attribute_hidden; + /* Initialize the DSO sort algorithm to use. */ #if !HAVE_TUNABLES static inline void diff --git a/sysdeps/unix/sysv/linux/dl-early_allocate.c b/sysdeps/unix/sysv/linux/dl-early_allocate.c new file mode 100644 index 0000000000..2c77b6e3ff --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-early_allocate.c @@ -0,0 +1,81 @@ +/* Early memory allocation for the dynamic loader. Generic version. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Mark symbols hidden in static PIE for early self relocation to work. */ +#if BUILD_PIE_DEFAULT +# pragma GCC visibility push(hidden) +#endif +#include + +#include +#include +#include +#include +#include + +#include + +/* Defined in brk.c. */ +extern void *__curbrk; + +void * +_dl_early_allocate (size_t size) +{ + void *result; + + if (__curbrk != NULL) + /* If the break has been initialized, brk must have run before, + so just call it once more. */ + { + result = __sbrk (size); + if (result == (void *) -1) + result = NULL; + } + else + { + /* If brk has not been invoked, there is no need to update + __curbrk. The first call to brk will take care of that. */ + void *previous = (void *) INTERNAL_SYSCALL_CALL (brk, 0); + result = (void *) INTERNAL_SYSCALL_CALL (brk, previous + size); + if (result == previous) + result = NULL; + else + result = previous; + } + + /* If brk fails, fall back to mmap. This can happen due to + unfortunate ASLR layout decisions and kernel bugs, particularly + for static PIE. */ + if (result == NULL) + { + long int ret; + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; +#ifdef __NR_mmap2 + ret = MMAP_CALL_INTERNAL (mmap2, 0, size, prot, flags, -1, 0); +#else + ret = MMAP_CALL_INTERNAL (mmap, 0, size, prot, flags, -1, 0); +#endif + if (INTERNAL_SYSCALL_ERROR_P (ret)) + result = NULL; + else + result = (void *) ret; + } + + return result; +}