From patchwork Fri Oct 2 14:05:58 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?=C5=81ukasz_Stelmach?= X-Patchwork-Id: 145156 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id ADD684BB1C20 for ; Fri, 2 Oct 2026 14:07:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org ADD684BB1C20 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=samsung.com header.i=@samsung.com header.a=rsa-sha256 header.s=mail20170921 header.b=Bi7RN/sQ X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mailout1.w1.samsung.com (mailout1.w1.samsung.com [210.118.77.11]) by sourceware.org (Postfix) with ESMTPS id A67564BA79B8 for ; Fri, 2 Oct 2026 14:07:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A67564BA79B8 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=samsung.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A67564BA79B8 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=210.118.77.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1790950022; cv=none; b=CX1JXUZzl4AKO3MwnYm0YJEOT/UDySdEGItJvTOW8NWmUqa3yPc5k0R9o6ss89mN/B2OtvMe+23oFqs/MdakHFT+UXiff5I/IoKzuddP07/7Z0koxIBBFPNg+9rHzflAzuzs/I0LxqquVTNsK84zWrUqKoZboeXJZhABdRXBvZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1790950022; c=relaxed/simple; bh=Fp5bm9GuSuCLDZzZVgJNMqvSYvyb0AIzyjrrIZhymKY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=SHRgvQAtJdNwBefiJgO++I/HcuBsiWypPjx5uCHAtsbCnu75bGpOx5NdRVnCtTJeknxJ0WUnc05FGpF11+BG2Q03Az2XDY0pSKwMAy84NWnFDcV3IigiPTHB2ARHl0iHJM9lv2wQNQ7qeKngx1o0GchU4jg2W/RG6nWs7TokQMI= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=samsung.com header.i=@samsung.com header.a=rsa-sha256 header.s=mail20170921 header.b=Bi7RN/sQ DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A67564BA79B8 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20261002140659euoutp0121e63b0d7799383c744a40317f54d50d~au43H81RD0145901459euoutp01s for ; Fri, 2 Oct 2026 14:06:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20261002140659euoutp0121e63b0d7799383c744a40317f54d50d~au43H81RD0145901459euoutp01s DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1790950019; bh=1PXvlNvDSG2ELxEDRw36k5QkhRhv9LDG5q7wBW0dgiM=; h=From:To:Cc:Subject:Date:References:From; b=Bi7RN/sQfwXwJKqiX543maD4EdLYb+iyUT+xrQl7JMzT29qhBrhEN6kSrfOUpwJ93 OJrnhUdNhq6waXnkJDRk5p+DBIin8jK7V8M4DgRCZvWuMYvQTKNQJ+y8+ZJ2oicNzn 6hlBFnYRAVYi6g5oSJiTZHAvWNYOcHdsTz68wuRY= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p2.samsung.com (KnoxPortal) with ESMTPA id 20261002140659eucas1p23a7bc42fd314f4a1ce4022c38b1e42ab~au422Ik-M2695226952eucas1p2b; Fri, 2 Oct 2026 14:06:59 +0000 (GMT) Received: from localhost (unknown [106.120.51.111]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20261002140659eusmtip264dc185a77e60bb7f959452784f649a6~au42ySeiw2242422424eusmtip2x; Fri, 2 Oct 2026 14:06:59 +0000 (GMT) From: =?utf-8?q?=C5=81ukasz_Stelmach?= To: libc-alpha@sourceware.org Cc: gabravier@gmail.com, fweimer@redhat.com, carlos@redhat.com, k.lewandowsk@samsung.com, m.szyprowski@samsung.com, m.moscicki2@samsung.com, =?utf-8?q?=C5=81ukasz_Stelmach?= Subject: [PATCH v2] elf: Load files from /etc/ld.so.preload.d Date: Fri, 2 Oct 2026 16:05:58 +0200 Message-ID: <20261002140558.130572-1-l.stelmach@samsung.com> X-Mailer: git-send-email 2.54.0 MIME-Version: 1.0 Organization: Samsung R&D Institute Poland X-CMS-MailID: 20261002140659eucas1p23a7bc42fd314f4a1ce4022c38b1e42ab X-Msg-Generator: CA X-RootMTR: 20261002140659eucas1p23a7bc42fd314f4a1ce4022c38b1e42ab X-EPHeader: CA X-CMS-RootMailID: 20261002140659eucas1p23a7bc42fd314f4a1ce4022c38b1e42ab References: 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, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RCVD_IN_PBL, SPF_HELO_PASS, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Enable reading a list of libraries to preload from files in /etc/ld.so.preload.d directory. The files are read in alphabetical order and must end in `.conf` to be read. Fixes: https://sourceware.org/bugzilla/show_bug.cgi?id=24913 Signed-off-by: Ɓukasz Stelmach --- Changelog: v2 - use scandir(3) to sort files from /etc/ld.so.preload.d alphabetically elf/rtld.c | 185 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 114 insertions(+), 71 deletions(-) diff --git a/elf/rtld.c b/elf/rtld.c index 324393d606..6b26620759 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include @@ -872,6 +874,89 @@ handle_preload_list (const char *preloadlist, struct link_map *main_map, return npreloads; } +unsigned int +handle_preload_file (const char *preload_file, struct link_map *main_map) +{ + size_t file_size; + char *file; + unsigned int npreloads = 0; + + /* Read the contents of the file. */ + file = _dl_sysdep_read_whole_file (preload_file, &file_size, + PROT_READ | PROT_WRITE); + if (__glibc_unlikely (file != MAP_FAILED)) + { + /* Parse the file. It contains names of libraries to be loaded, + separated by white spaces or `:'. It may also contain + comments introduced by `#'. */ + char *problem; + char *runp; + size_t rest; + + /* Eliminate comments. */ + runp = file; + rest = file_size; + while (rest > 0) + { + char *comment = memchr (runp, '#', rest); + if (comment == NULL) + break; + + rest -= comment - runp; + do + *comment = ' '; + while (--rest > 0 && *++comment != '\n'); + } + + /* We have one problematic case: if we have a name at the end of + the file without a trailing terminating characters, we cannot + place the \0. Handle the case separately. */ + if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t' + && file[file_size - 1] != '\n' && file[file_size - 1] != ':') + { + problem = &file[file_size]; + while (problem > file && problem[-1] != ' ' + && problem[-1] != '\t' + && problem[-1] != '\n' && problem[-1] != ':') + --problem; + + if (problem > file) + problem[-1] = '\0'; + } + else + { + problem = NULL; + file[file_size - 1] = '\0'; + } + + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); + + if (file != problem) + { + char *p; + runp = file; + while ((p = strsep (&runp, ": \t\n")) != NULL) + if (p[0] != '\0') + npreloads += do_preload (p, main_map, preload_file); + } + + if (problem != NULL) + { + char *p = strndupa (problem, file_size - (problem - file)); + + npreloads += do_preload (p, main_map, preload_file); + } + + rtld_timer_accum (&load_time, start); + + /* We don't need the file anymore. */ + __munmap (file, file_size); + } + + return npreloads; +} + /* Called if the audit DSO cannot be used: if it does not have the appropriate interfaces, or it expects a more recent version library version than what the dynamic linker provides. */ @@ -1338,6 +1423,20 @@ _dl_start_args_adjust (int skip_args, int skip_env) #endif } +static int +conf_filter(const struct dirent *d) +{ + int len; + if (d == NULL) + return 0; + len = strlen(d->d_name); + if (len < (sizeof(".conf"))) + return 0; + if (strncmp(".conf", &d->d_name[len - 5], 5) != 0) + return 0; + return 1; +} + static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum, @@ -1345,8 +1444,6 @@ dl_main (const ElfW(Phdr) *phdr, ElfW(auxv_t) *auxv) { struct link_map *main_map; - size_t file_size; - char *file; unsigned int i; bool rtld_is_main = false; void *tcbp = NULL; @@ -1841,80 +1938,26 @@ dl_main (const ElfW(Phdr) *phdr, the work but this does not matter, since it is not for production use. */ static const char preload_file[] = "/etc/ld.so.preload"; - if (__glibc_unlikely (__access (preload_file, R_OK) == 0)) - { - /* Read the contents of the file. */ - file = _dl_sysdep_read_whole_file (preload_file, &file_size, - PROT_READ | PROT_WRITE); - if (__glibc_unlikely (file != MAP_FAILED)) - { - /* Parse the file. It contains names of libraries to be loaded, - separated by white spaces or `:'. It may also contain - comments introduced by `#'. */ - char *problem; - char *runp; - size_t rest; - - /* Eliminate comments. */ - runp = file; - rest = file_size; - while (rest > 0) - { - char *comment = memchr (runp, '#', rest); - if (comment == NULL) - break; - - rest -= comment - runp; - do - *comment = ' '; - while (--rest > 0 && *++comment != '\n'); - } + static const char preload_dir[] = "/etc/ld.so.preload.d"; - /* We have one problematic case: if we have a name at the end of - the file without a trailing terminating characters, we cannot - place the \0. Handle the case separately. */ - if (file[file_size - 1] != ' ' && file[file_size - 1] != '\t' - && file[file_size - 1] != '\n' && file[file_size - 1] != ':') - { - problem = &file[file_size]; - while (problem > file && problem[-1] != ' ' - && problem[-1] != '\t' - && problem[-1] != '\n' && problem[-1] != ':') - --problem; - - if (problem > file) - problem[-1] = '\0'; - } - else - { - problem = NULL; - file[file_size - 1] = '\0'; - } - - RTLD_TIMING_VAR (start); - rtld_timer_start (&start); - - if (file != problem) - { - char *p; - runp = file; - while ((p = strsep (&runp, ": \t\n")) != NULL) - if (p[0] != '\0') - npreloads += do_preload (p, main_map, preload_file); - } + if (__glibc_unlikely (__access (preload_file, R_OK) == 0)) + npreloads += handle_preload_file (preload_file, main_map); - if (problem != NULL) - { - char *p = strndupa (problem, file_size - (problem - file)); + if (__glibc_unlikely (__access (preload_dir, R_OK | X_OK) == 0)) + { + struct dirent **conffiles = NULL; + int i, n = 0; - npreloads += do_preload (p, main_map, preload_file); - } + n = scandir (preload_dir, &conffiles, conf_filter, alphasort); + if (n < 0) + n = 0; - rtld_timer_accum (&load_time, start); + for (i = 0; i < n; i++) { + npreloads += handle_preload_file (conffiles[i]->d_name, main_map); + free(conffiles[i]); + } - /* We don't need the file anymore. */ - __munmap (file, file_size); - } + free(conffiles); } if (__glibc_unlikely (*first_preload != NULL))