From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.9 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,T_SCC_BODY_TEXT_LINE,URIBL_BLACK autolearn=no autolearn_force=no version=3.4.4 Received: (qmail 25434 invoked from network); 8 May 2023 18:14:42 -0000 Received: from second.openwall.net (193.110.157.125) by inbox.vuxu.org with ESMTPUTF8; 8 May 2023 18:14:42 -0000 Received: (qmail 15541 invoked by uid 550); 8 May 2023 18:14:32 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 15451 invoked from network); 8 May 2023 18:14:31 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683569659; x=1686161659; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DFI8jtYCSs542zsuiJKa3Nm163wEY81p383pAYJskOM=; b=nxcJOXfJp8Xjn8QO56TG/ZCo3PbwShSYCOWsiaF+7xw7s/1LireiifT3rddihGfsup 9TeWOxg8LENtj/auZgjh/xKIbuMDfnrKjRKBjaU3Rpafn5dJqUfPx3/QOBHGU+RfHNli D/DAB4vSWBZdSt8uHKQIP2krD33juq2IWxvm+LahJeBdNfxoh7izYsyOCY2GZmXW5vJe r92BK0gwEvGiP5pAKLsYiY8cKrOQh8SqfXMj89yVvSS4miKH/Gvv5f0nzSt4jp7FdlnF +jQPCSMSwz47KTruFJFV+YD+OhvPvf9efEglIQPyDd7q364FfGquRLm80Jqy7+3czd9k Szkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683569659; x=1686161659; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DFI8jtYCSs542zsuiJKa3Nm163wEY81p383pAYJskOM=; b=dTOIjo61ItH9m9a3R1W5PrZCFrfYGn0+uo7cDrxROHWoQ/zvvtok0skdnibhZ9zFJY PMdSwvVLKNyCOB8CrHmC5lwlkKp9fUvjNg5VbI2kW2kVXCpHR+0irHYnkrwCK+litD+S 6UJNCfbd8nFT5P7junVkAoy9mKZyNC68gP0XGNGoXlAv+An765L8pMjTKRMsieQkBkJE XXf6cba9HBZnYOih52wGfc3q/rF4Z4rDW3dBVIPmzyn7BHxbuoXYBwGIhyaTEVPbP23C VcFsyCcvx0nF+uTjdLYXERCbOAbl9hnNQ8NRNhqxIyu1xDiojOIcwteGEf6oU4CR8yAb oabQ== X-Gm-Message-State: AC+VfDwyY2mBmVXw3qrFIrUJmRXGx5X8WWyx1ArzEFHw296HuJ0LWYj5 0D4Sv6kUczXRsywqERvdT08EUdcThqRJxg== X-Google-Smtp-Source: ACHHUZ73bGLBmbPVlew4O1gMAsZh3a1imUQf/M+1X63t2TxE/sYdGEyp9VsBmMEj3ObhFdhsWvWc0A== X-Received: by 2002:a1c:7415:0:b0:3f1:9a5a:b44c with SMTP id p21-20020a1c7415000000b003f19a5ab44cmr7966861wmc.26.1683569659566; Mon, 08 May 2023 11:14:19 -0700 (PDT) From: Pedro Falcato To: musl@lists.openwall.com Cc: Pedro Falcato Date: Mon, 8 May 2023 19:14:12 +0100 Message-Id: <20230508181413.194379-2-pedro.falcato@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230508181413.194379-1-pedro.falcato@gmail.com> References: <20230508181413.194379-1-pedro.falcato@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [musl] [RFC PATCH 1/2] dynlink: Reorganize library loading Separate the core of library loading from load_library, in a way that can be reused by codepaths that do not need path -> library resolution. Signed-off-by: Pedro Falcato --- ldso/dynlink.c | 202 ++++++++++++++++++++++++++----------------------- 1 file changed, 107 insertions(+), 95 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 2b8c382b..2272b768 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -988,16 +988,118 @@ static void makefuncdescs(struct dso *p) } } +static struct dso *load_library(const char *name, struct dso *needed_by); + +static struct dso *load_library_core(int fd, struct dso *needed_by, const char *pathname, const char *name) +{ + struct dso *p; + struct stat st; + size_t alloc_size; + int n_th = 0; + unsigned char *map; + struct dso temp_dso = {0}; + + if (fd < 0) return 0; + if (fstat(fd, &st) < 0) { + close(fd); + return 0; + } + for (p=head->next; p; p=p->next) { + if (p->dev == st.st_dev && p->ino == st.st_ino) { + /* If this library was previously loaded with a + * pathname but a search found the same inode, + * setup its shortname so it can be found by name. */ + if (!p->shortname && pathname != name) + p->shortname = strrchr(p->name, '/')+1; + close(fd); + return p; + } + } + map = noload ? 0 : map_library(fd, &temp_dso); + close(fd); + if (!map) return 0; + + /* Avoid the danger of getting two versions of libc mapped into the + * same process when an absolute pathname was used. The symbols + * checked are chosen to catch both musl and glibc, and to avoid + * false positives from interposition-hack libraries. */ + decode_dyn(&temp_dso); + if (find_sym(&temp_dso, "__libc_start_main", 1).sym && + find_sym(&temp_dso, "stdin", 1).sym) { + unmap_library(&temp_dso); + return load_library("libc.so", needed_by); + } + /* Past this point, if we haven't reached runtime yet, ldso has + * committed either to use the mapped library or to abort execution. + * Unmapping is not possible, so we can safely reclaim gaps. */ + if (!runtime) reclaim_gaps(&temp_dso); + + /* Allocate storage for the new DSO. When there is TLS, this + * storage must include a reservation for all pre-existing + * threads to obtain copies of both the new TLS, and an + * extended DTV capable of storing an additional slot for + * the newly-loaded DSO. */ + alloc_size = sizeof *p + strlen(pathname) + 1; + if (runtime && temp_dso.tls.image) { + size_t per_th = temp_dso.tls.size + temp_dso.tls.align + + sizeof(void *) * (tls_cnt+3); + n_th = libc.threads_minus_1 + 1; + if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX; + else alloc_size += n_th * per_th; + } + p = calloc(1, alloc_size); + if (!p) { + unmap_library(&temp_dso); + return 0; + } + memcpy(p, &temp_dso, sizeof temp_dso); + p->dev = st.st_dev; + p->ino = st.st_ino; + p->needed_by = needed_by; + p->name = p->buf; + p->runtime_loaded = runtime; + strcpy(p->name, pathname); + /* Add a shortname only if name arg was not an explicit pathname. */ + if (pathname != name) p->shortname = strrchr(p->name, '/')+1; + if (p->tls.image) { + p->tls_id = ++tls_cnt; + tls_align = MAXP2(tls_align, p->tls.align); +#ifdef TLS_ABOVE_TP + p->tls.offset = tls_offset + ( (p->tls.align-1) & + (-tls_offset + (uintptr_t)p->tls.image) ); + tls_offset = p->tls.offset + p->tls.size; +#else + tls_offset += p->tls.size + p->tls.align - 1; + tls_offset -= (tls_offset + (uintptr_t)p->tls.image) + & (p->tls.align-1); + p->tls.offset = tls_offset; +#endif + p->new_dtv = (void *)(-sizeof(size_t) & + (uintptr_t)(p->name+strlen(p->name)+sizeof(size_t))); + p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1)); + if (tls_tail) tls_tail->next = &p->tls; + else libc.tls_head = &p->tls; + tls_tail = &p->tls; + } + + tail->next = p; + p->prev = tail; + tail = p; + + if (DL_FDPIC) makefuncdescs(p); + + if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base); + + return p; +} + static struct dso *load_library(const char *name, struct dso *needed_by) { char buf[2*NAME_MAX+2]; const char *pathname; - unsigned char *map; - struct dso *p, temp_dso = {0}; + struct dso *p; int fd; struct stat st; - size_t alloc_size; - int n_th = 0; int is_self = 0; if (!*name) { @@ -1100,98 +1202,8 @@ static struct dso *load_library(const char *name, struct dso *needed_by) } pathname = buf; } - if (fd < 0) return 0; - if (fstat(fd, &st) < 0) { - close(fd); - return 0; - } - for (p=head->next; p; p=p->next) { - if (p->dev == st.st_dev && p->ino == st.st_ino) { - /* If this library was previously loaded with a - * pathname but a search found the same inode, - * setup its shortname so it can be found by name. */ - if (!p->shortname && pathname != name) - p->shortname = strrchr(p->name, '/')+1; - close(fd); - return p; - } - } - map = noload ? 0 : map_library(fd, &temp_dso); - close(fd); - if (!map) return 0; - - /* Avoid the danger of getting two versions of libc mapped into the - * same process when an absolute pathname was used. The symbols - * checked are chosen to catch both musl and glibc, and to avoid - * false positives from interposition-hack libraries. */ - decode_dyn(&temp_dso); - if (find_sym(&temp_dso, "__libc_start_main", 1).sym && - find_sym(&temp_dso, "stdin", 1).sym) { - unmap_library(&temp_dso); - return load_library("libc.so", needed_by); - } - /* Past this point, if we haven't reached runtime yet, ldso has - * committed either to use the mapped library or to abort execution. - * Unmapping is not possible, so we can safely reclaim gaps. */ - if (!runtime) reclaim_gaps(&temp_dso); - - /* Allocate storage for the new DSO. When there is TLS, this - * storage must include a reservation for all pre-existing - * threads to obtain copies of both the new TLS, and an - * extended DTV capable of storing an additional slot for - * the newly-loaded DSO. */ - alloc_size = sizeof *p + strlen(pathname) + 1; - if (runtime && temp_dso.tls.image) { - size_t per_th = temp_dso.tls.size + temp_dso.tls.align - + sizeof(void *) * (tls_cnt+3); - n_th = libc.threads_minus_1 + 1; - if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX; - else alloc_size += n_th * per_th; - } - p = calloc(1, alloc_size); - if (!p) { - unmap_library(&temp_dso); - return 0; - } - memcpy(p, &temp_dso, sizeof temp_dso); - p->dev = st.st_dev; - p->ino = st.st_ino; - p->needed_by = needed_by; - p->name = p->buf; - p->runtime_loaded = runtime; - strcpy(p->name, pathname); - /* Add a shortname only if name arg was not an explicit pathname. */ - if (pathname != name) p->shortname = strrchr(p->name, '/')+1; - if (p->tls.image) { - p->tls_id = ++tls_cnt; - tls_align = MAXP2(tls_align, p->tls.align); -#ifdef TLS_ABOVE_TP - p->tls.offset = tls_offset + ( (p->tls.align-1) & - (-tls_offset + (uintptr_t)p->tls.image) ); - tls_offset = p->tls.offset + p->tls.size; -#else - tls_offset += p->tls.size + p->tls.align - 1; - tls_offset -= (tls_offset + (uintptr_t)p->tls.image) - & (p->tls.align-1); - p->tls.offset = tls_offset; -#endif - p->new_dtv = (void *)(-sizeof(size_t) & - (uintptr_t)(p->name+strlen(p->name)+sizeof(size_t))); - p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1)); - if (tls_tail) tls_tail->next = &p->tls; - else libc.tls_head = &p->tls; - tls_tail = &p->tls; - } - - tail->next = p; - p->prev = tail; - tail = p; - - if (DL_FDPIC) makefuncdescs(p); - if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base); - - return p; + return load_library_core(fd, needed_by, pathname, name); } static void load_direct_deps(struct dso *p) -- 2.40.1