diff --git a/elf/Makefile b/elf/Makefile index fda796f6d5..3a1cb72955 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -453,6 +453,9 @@ tests += \ tst-recursive-tls \ tst-relsort1 \ tst-ro-dynamic \ + tst-rtld-no-malloc \ + tst-rtld-no-malloc-audit \ + tst-rtld-no-malloc-preload \ tst-rtld-run-static \ tst-single_threaded \ tst-single_threaded-pthread \ @@ -3160,3 +3163,9 @@ tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so $(objpfx)tst-dlopen-auditdup.out: \ $(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so + +# Reuse an audit module which provides ample debug logging. +tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + +# Any shared object should do. +tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so diff --git a/elf/dl-support.c b/elf/dl-support.c index 451932dd03..ee590edf93 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -338,8 +338,7 @@ _dl_non_dynamic_init (void) call_function_static_weak (_dl_find_object_init); /* Setup relro on the binary itself. */ - if (_dl_main_map.l_relro_size != 0) - _dl_protect_relro (&_dl_main_map); + _dl_protect_relro (&_dl_main_map); } #ifdef DL_SYSINFO_IMPLEMENTATION diff --git a/elf/rtld.c b/elf/rtld.c index dcd0f4cdc6..b8cc3f605f 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -2321,30 +2321,27 @@ dl_main (const ElfW(Phdr) *phdr, /* Make sure no new search directories have been added. */ assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs)); - /* Re-relocate ourselves with user-controlled symbol definitions. - - We must do this after TLS initialization in case after this - re-relocation, we might call a user-supplied function - (e.g. calloc from _dl_relocate_object) that uses TLS data. */ - /* Set up the object lookup structures. */ _dl_find_object_init (); - /* The malloc implementation has been relocated, so resolving - its symbols (and potentially calling IFUNC resolvers) is safe - at this point. */ - __rtld_malloc_init_real (main_map); - /* Likewise for the locking implementation. */ __rtld_mutex_init (); + /* Re-relocate ourselves with user-controlled symbol definitions. */ + { RTLD_TIMING_VAR (start); rtld_timer_start (&start); - /* Mark the link map as not yet relocated again. */ - GL(dl_rtld_map).l_relocated = 0; - _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); + _dl_relocate_object_no_relro (&GL(dl_rtld_map), main_map->l_scope, 0, 0); + + /* The malloc implementation has been relocated, so resolving + its symbols (and potentially calling IFUNC resolvers) is safe + at this point. */ + __rtld_malloc_init_real (main_map); + + if (GL(dl_rtld_map).l_relro_size != 0) + _dl_protect_relro (&GL(dl_rtld_map)); rtld_timer_accum (&relocate_time, start); } diff --git a/elf/tst-rtld-no-malloc-audit.c b/elf/tst-rtld-no-malloc-audit.c new file mode 100644 index 0000000000..a028377ad1 --- /dev/null +++ b/elf/tst-rtld-no-malloc-audit.c @@ -0,0 +1 @@ +#include "tst-rtld-no-malloc.c" diff --git a/elf/tst-rtld-no-malloc-preload.c b/elf/tst-rtld-no-malloc-preload.c new file mode 100644 index 0000000000..a028377ad1 --- /dev/null +++ b/elf/tst-rtld-no-malloc-preload.c @@ -0,0 +1 @@ +#include "tst-rtld-no-malloc.c" diff --git a/elf/tst-rtld-no-malloc.c b/elf/tst-rtld-no-malloc.c new file mode 100644 index 0000000000..5f24d4bd72 --- /dev/null +++ b/elf/tst-rtld-no-malloc.c @@ -0,0 +1,76 @@ +/* Test that program loading does not call malloc. + Copyright (C) 2024 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 + +static void +print (const char *s) +{ + const char *end = s + strlen (s); + while (s < end) + { + ssize_t ret = write (STDOUT_FILENO, s, end - s); + if (ret <= 0) + _exit (2); + s += ret; + } +} + +static void __attribute__ ((noreturn)) +unexpected_call (const char *function) +{ + print ("error: unexpected call to "); + print (function); + print ("\n"); + _exit (1); +} + +/* These are the malloc functions implement in elf/dl-minimal.c. */ + +void +free (void *ignored) +{ + unexpected_call ("free"); +} + +void * +calloc (size_t ignored1, size_t ignored2) +{ + unexpected_call ("calloc"); +} + +void * +malloc (size_t ignored) +{ + unexpected_call ("malloc"); +} + +void * +realloc (void *ignored1, size_t ignored2) +{ + unexpected_call ("realloc"); +} + +int +main (void) +{ + /* Do not use the test wrapper, to avoid spurious malloc calls from it. */ + return 0; +}