[PATCH] elf: Load files from /etc/ld.so.preload.d
Gabriel Ravier
gabravier@gmail.com
Tue Sep 29 22:53:53 GMT 2026
On 9/29/26 1:50 PM, Łukasz Stelmach wrote:
> From: Łukasz Stelmach <l.stelmach@samsung.com>
>
> Enable reading a list of libraries to preload from files in
> /etc/ld.so.preload.d directory. The files must end in `.conf` to be read.
>
> Fixes: https://sourceware.org/bugzilla/show_bug.cgi?id=24913
> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
> ---
> elf/rtld.c | 161 ++++++++++++++++++++++++++++++++---------------------
> 1 file changed, 97 insertions(+), 64 deletions(-)
>
> diff --git a/elf/rtld.c b/elf/rtld.c
> index 324393d606..74387c2663 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -54,6 +54,8 @@
> #include <dl-audit-check.h>
> #include <dl-call_tls_init_tp.h>
> #include <dl-exec-post.h>
> +#include <sys/types.h>
> +#include <dirent.h>
>
> #include <assert.h>
>
> @@ -1841,80 +1843,111 @@ 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";
> + const size_t preload_dir_len = sizeof("/etc/ld.so.preload.d") - 1;
> + char preload_dir[sizeof("/etc/ld.so.preload.d") + 1 + sizeof(((struct dirent*)0)->d_name)] = "/etc/ld.so.preload.d";
> + const char *p_file = NULL;
> + DIR *p_dir = NULL;
> +
> if (__glibc_unlikely (__access (preload_file, R_OK) == 0))
> + p_file = preload_file;
> +
> + if (__glibc_unlikely (__access (preload_dir, R_OK | X_OK) == 0))
> + p_dir = opendir(preload_dir);
> +
> + if (__glibc_unlikely (p_file != NULL || p_dir != NULL))
> {
> - /* 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;
> + struct dirent* de = NULL;
> + do {
> + if (de != NULL)
> + {
> + int l = strlen(de->d_name);
> + if (__glibc_unlikely ((l < sizeof(".conf") - 1)
> + || (strncmp(".conf", &de->d_name[l - 5], 5) != 0)))
> + continue;
> + preload_dir[preload_dir_len] = '/';
> + strncpy(&preload_dir[preload_dir_len + 1], de->d_name, sizeof(preload_dir) - preload_dir_len - 1);
> + preload_dir[preload_dir_len + 1 + l] = '\0';
> + p_file = preload_dir;
> + }
>
> - rest -= comment - runp;
> - do
> - *comment = ' ';
> - while (--rest > 0 && *++comment != '\n');
> - }
> + if (p_file == NULL)
> + continue;
>
> - /* 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';
> - }
> + /* Read the contents of the file. */
> + file = _dl_sysdep_read_whole_file (p_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');
> + }
>
> - RTLD_TIMING_VAR (start);
> - rtld_timer_start (&start);
> + /* 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';
> + }
>
> - 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);
> - }
> + RTLD_TIMING_VAR (start);
> + rtld_timer_start (&start);
>
> - if (problem != NULL)
> - {
> - char *p = strndupa (problem, file_size - (problem - file));
> + if (file != problem)
> + {
> + char *p;
> + runp = file;
> + while ((p = strsep (&runp, ": \t\n")) != NULL)
> + if (p[0] != '\0')
> + npreloads += do_preload (p, main_map, p_file);
> + }
>
> - npreloads += do_preload (p, main_map, preload_file);
> - }
> + if (problem != NULL)
> + {
> + char *p = strndupa (problem, file_size - (problem - file));
>
> - rtld_timer_accum (&load_time, start);
> + npreloads += do_preload (p, main_map, p_file);
> + }
>
> - /* We don't need the file anymore. */
> - __munmap (file, file_size);
> - }
> + rtld_timer_accum (&load_time, start);
> +
> + /* We don't need the file anymore. */
> + __munmap (file, file_size);
> + }
> + } while (p_dir && (de = readdir(p_dir)));
> + if (p_dir != NULL)
> + closedir(p_dir);
> }
>
> if (__glibc_unlikely (*first_preload != NULL))
...How does the ordering work? If it's just readdir, isn't that
effectively unspecified? AIUI all the other .d directory conventions in
most tools sort entries, which would matter here for e.g. symbol
interposition order, I'd think...
More information about the Libc-alpha
mailing list