From patchwork Thu May 18 08:28:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: stsp X-Patchwork-Id: 1783063 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=yandex.ru header.i=@yandex.ru header.a=rsa-sha256 header.s=mail header.b=VTVD5EVH; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QMNXP1bmLz20dn for ; Thu, 18 May 2023 18:33:09 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 46B2E3839067 for ; Thu, 18 May 2023 08:33:07 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from forward102c.mail.yandex.net (forward102c.mail.yandex.net [178.154.239.213]) by sourceware.org (Postfix) with ESMTPS id F147A3856DF4 for ; Thu, 18 May 2023 08:29:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F147A3856DF4 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=yandex.ru Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=yandex.ru Received: from mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net (mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:1186:0:640:38cb:0]) by forward102c.mail.yandex.net (Yandex) with ESMTP id E129360031 for ; Thu, 18 May 2023 11:29:42 +0300 (MSK) Received: by mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net (smtp/Yandex) with ESMTPSA id XTYe39MDZ0U0-vSYJP4k3; Thu, 18 May 2023 11:29:42 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1684398582; bh=ruq76yRdNZz4P0RtmrsIHFoJB+6LMR303Cmg+gcIE4w=; h=Message-Id:Date:In-Reply-To:Cc:Subject:References:To:From; b=VTVD5EVHsz5laRHJEzGVbnEqVX0cxwGI5lPJAGC1a4jl7HJ2JE4B889jsTzlW5jj3 7L1eBATKGzxRLROhrQsJg3EIXlkBczcCPPoUTGyLf5SdTUv0qAHQ/t5MPWpHT5jcei hU9tBHvWFFL9QEPyyFLg8Drz6dpFaEiKAEe8mP0M= Authentication-Results: mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net; dkim=pass header.i=@yandex.ru From: Stas Sergeev To: libc-alpha@sourceware.org Cc: Stas Sergeev Subject: [PATCH 08/14] finalize elf segments on a relocation step Date: Thu, 18 May 2023 13:28:48 +0500 Message-Id: <20230518082854.3903342-9-stsp2@yandex.ru> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230518082854.3903342-1-stsp2@yandex.ru> References: <20230518082854.3903342-1-stsp2@yandex.ru> MIME-Version: 1.0 X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org Sender: "Libc-alpha" This is needed so that the segment finalization can be delayed, together with the relocation process. The test-suite was run on x86_64/64 and showed no regressions. Signed-off-by: Stas Sergeev --- elf/dl-close.c | 1 + elf/dl-load.c | 33 ++++++++++++++++++++++----------- elf/dl-load.h | 2 +- elf/dl-map-segments.h | 7 ++++++- elf/dl-open.c | 10 +++++++++- include/link.h | 5 ++++- 6 files changed, 43 insertions(+), 15 deletions(-) diff --git a/elf/dl-close.c b/elf/dl-close.c index 48ac3663ec..0640fc0bec 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -691,6 +691,7 @@ _dl_close_worker (struct link_map *map, bool force) GL(dl_initfirst) = NULL; free (imap->l_dlopen_args); + free (imap->l_loadcmds); free (imap); } diff --git a/elf/dl-load.c b/elf/dl-load.c index 28e582fbdf..31514fca84 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -950,6 +950,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, int type; /* Initialize to keep the compiler happy. */ const char *errstring = NULL; + struct loadcmd *loadcmds = NULL; int errval = 0; /* Get file information. To match the kernel behavior, do not fill @@ -969,6 +970,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, lose_errno: errval = errno; lose: + if (loadcmds) + free (loadcmds); /* The file might already be closed. */ if (fd != -1) __close_nocancel (fd); @@ -1080,18 +1083,23 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, } } - /* On most platforms presume that PT_GNU_STACK is absent and the stack is - * executable. Other platforms default to a nonexecutable stack and don't - * need PT_GNU_STACK to do so. */ - unsigned int stack_flags = DEFAULT_STACK_PERMS; + /* On most platforms presume that PT_GNU_STACK is absent and the stack is + * executable. Other platforms default to a nonexecutable stack and don't + * need PT_GNU_STACK to do so. */ + unsigned int stack_flags = DEFAULT_STACK_PERMS; { /* Scan the program header table, collecting its load commands. */ - struct loadcmd loadcmds[l->l_phnum]; - size_t nloadcmds = 0; + #define nloadcmds l->l_nloadcmds bool empty_dynamic = false; ElfW(Addr) p_align_max = 0; + loadcmds = (struct loadcmd *) malloc (sizeof (struct loadcmd) * l->l_phnum); + if (loadcmds == NULL) + goto lose; + l->l_loadcmds = loadcmds; + nloadcmds = 0; + /* The struct is initialized to zero so this is not necessary: l->l_ld = 0; l->l_phdr = 0; @@ -1225,8 +1233,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, } /* Align all PT_LOAD segments to the maximum p_align. */ - for (size_t i = 0; i < nloadcmds; i++) - loadcmds[i].mapalign = p_align_max; + l->l_map_align = p_align_max; /* dlopen of an executable is not valid because it is not possible to perform proper relocations, handle static TLS, or run the @@ -1263,9 +1270,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, l->l_map_start = l->l_map_end = 0; goto lose; } - errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds); - if (__glibc_unlikely (errstring != NULL)) - goto lose; + /* dlopen()ed solibs are finalized on a relocation step. */ + if (!(mode & __RTLD_DLOPEN)) + { + errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds); + if (__glibc_unlikely (errstring != NULL)) + goto lose; + } } if (l->l_ld != 0) diff --git a/elf/dl-load.h b/elf/dl-load.h index 61f5c4fadf..555eed176d 100644 --- a/elf/dl-load.h +++ b/elf/dl-load.h @@ -75,7 +75,7 @@ ELF_PREFERRED_ADDRESS_DATA; Its details have been expanded out and converted. */ struct loadcmd { - ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign, maphole; + ElfW(Addr) mapstart, mapend, dataend, allocend, maphole; ElfW(Off) mapoff; int prot; /* PROT_* bits. */ }; diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h index da6b762bca..a0078a77c8 100644 --- a/elf/dl-map-segments.h +++ b/elf/dl-map-segments.h @@ -100,7 +100,7 @@ _dl_map_segments (struct link_map *l, int fd, - MAP_BASE_ADDR (l)); /* Remember which part of the address space this object uses. */ - l->l_map_start = _dl_map_segment (mappref, maplength, c->mapalign); + l->l_map_start = _dl_map_segment (mappref, maplength, l->l_map_align); if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED)) return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; @@ -150,6 +150,9 @@ _dl_finalize_segments (struct link_map *l, int type, { const struct loadcmd *c = loadcmds; + if (l->l_map_completed) + return NULL; + while (c < &loadcmds[nloadcmds]) { ElfW(Addr) hole_start, hole_size; @@ -234,5 +237,7 @@ _dl_finalize_segments (struct link_map *l, int type, ++c; } + l->l_map_completed = 1; + return NULL; } diff --git a/elf/dl-open.c b/elf/dl-open.c index e553403e8b..f1f2e8d3a4 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -40,7 +40,8 @@ #include #include - +#include "dl-load.h" +#include "dl-map-segments.h" /* We must be careful not to leave us in an inconsistent state. Thus we catch any error and re-raise it after cleaning up. */ @@ -543,6 +544,8 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors) for (unsigned int i = last; i-- > first; ) { + const char *errstring; + l = new->l_initfini[i]; if (l->l_real->l_relocated) @@ -555,6 +558,11 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors) relocation_in_progress = 1; } + errstring = _dl_finalize_segments (l, ET_DYN, l->l_loadcmds, + l->l_nloadcmds); + if (__glibc_unlikely (errstring != NULL)) + _dl_signal_error (EINVAL, l->l_libname->name, NULL, errstring); + #ifdef SHARED if (__glibc_unlikely (GLRO(dl_profile) != NULL)) { diff --git a/include/link.h b/include/link.h index 03b9f82715..fa16dfa337 100644 --- a/include/link.h +++ b/include/link.h @@ -179,6 +179,7 @@ struct link_map } l_type:2; unsigned int l_dt_relr_ref:1; /* Nonzero if GLIBC_ABI_DT_RELR is referenced. */ + unsigned int l_map_completed:1; /* Nonzero if object fully mapped. */ unsigned int l_relocated:1; /* Nonzero if object's relocations done. */ unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */ @@ -252,7 +253,7 @@ struct link_map /* Start and finish of memory map for this object. l_map_start need not be the same as l_addr. */ - ElfW(Addr) l_map_start, l_map_end; + ElfW(Addr) l_map_start, l_map_end, l_map_align; /* End of the executable part of the mapping. */ ElfW(Addr) l_text_end; @@ -349,6 +350,8 @@ struct link_map unsigned long long int l_serial; void *l_dlopen_args; + void *l_loadcmds; + size_t l_nloadcmds; }; #include