diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 2 | ||||
-rw-r--r-- | elf/Versions | 4 | ||||
-rw-r--r-- | elf/dl-call-libc-early-init.c (renamed from elf/dl-lookup_libc_early_init.c) | 23 | ||||
-rw-r--r-- | elf/dl-load.c | 9 | ||||
-rw-r--r-- | elf/dl-open.c | 4 | ||||
-rw-r--r-- | elf/dl-version.c | 18 | ||||
-rw-r--r-- | elf/libc-early-init.h | 21 | ||||
-rw-r--r-- | elf/rtld.c | 12 |
8 files changed, 44 insertions, 49 deletions
diff --git a/elf/Makefile b/elf/Makefile index bc68150a37..3928a08787 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -52,6 +52,7 @@ routines = \ # The core dynamic linking functions are in libc for the static and # profiled libraries. dl-routines = \ + dl-call-libc-early-init \ dl-close \ dl-debug \ dl-debug-symbols \ @@ -64,7 +65,6 @@ dl-routines = \ dl-load \ dl-lookup \ dl-lookup-direct \ - dl-lookup_libc_early_init \ dl-minimal-malloc \ dl-misc \ dl-object \ diff --git a/elf/Versions b/elf/Versions index 6260c0fe03..a9ff278de7 100644 --- a/elf/Versions +++ b/elf/Versions @@ -29,8 +29,8 @@ libc { __placeholder_only_for_empty_version_map; } GLIBC_PRIVATE { - # A pattern is needed here because the suffix is dynamically generated. - __libc_early_init_*; + # functions used in other libraries + __libc_early_init; # Internal error handling support. Interposes the functions in ld.so. _dl_signal_exception; _dl_catch_exception; diff --git a/elf/dl-lookup_libc_early_init.c b/elf/dl-call-libc-early-init.c index 64bc287a05..ee9860e3ab 100644 --- a/elf/dl-lookup_libc_early_init.c +++ b/elf/dl-call-libc-early-init.c @@ -1,4 +1,4 @@ -/* Find the address of the __libc_early_init function. +/* Invoke the early initialization function in libc.so. Copyright (C) 2020-2022 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -16,21 +16,26 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ +#include <assert.h> #include <ldsodefs.h> #include <libc-early-init.h> #include <link.h> #include <stddef.h> -__typeof (__libc_early_init) * -_dl_lookup_libc_early_init (struct link_map *libc_map) +void +_dl_call_libc_early_init (struct link_map *libc_map, _Bool initial) { + /* There is nothing to do if we did not actually load libc.so. */ + if (libc_map == NULL) + return; + const ElfW(Sym) *sym - = _dl_lookup_direct (libc_map, LIBC_EARLY_INIT_NAME_STRING, - LIBC_EARLY_INIT_GNU_HASH, + = _dl_lookup_direct (libc_map, "__libc_early_init", + 0x069682ac, /* dl_new_hash output. */ "GLIBC_PRIVATE", 0x0963cf85); /* _dl_elf_hash output. */ - if (sym == NULL) - _dl_signal_error (0, libc_map->l_name, NULL, "\ -ld.so/libc.so mismatch detected (upgrade in progress?)"); - return DL_SYMBOL_ADDRESS (libc_map, sym); + assert (sym != NULL); + __typeof (__libc_early_init) *early_init + = DL_SYMBOL_ADDRESS (libc_map, sym); + early_init (initial); } diff --git a/elf/dl-load.c b/elf/dl-load.c index 00e08b5500..1ad0868dad 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -31,6 +31,7 @@ #include <sys/param.h> #include <sys/stat.h> #include <sys/types.h> +#include <gnu/lib-names.h> /* Type for the buffer we put the ELF header and hopefully the program header. This buffer does not really have to be too large. In most @@ -1465,6 +1466,14 @@ cannot enable executable stack as shared object requires"); add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB]) + l->l_info[DT_SONAME]->d_un.d_val)); + /* If we have newly loaded libc.so, update the namespace + description. */ + if (GL(dl_ns)[nsid].libc_map == NULL + && l->l_info[DT_SONAME] != NULL + && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB]) + + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0) + GL(dl_ns)[nsid].libc_map = l; + /* _dl_close can only eventually undo the module ID assignment (via remove_slotinfo) if this function returns a pointer to a link map. Therefore, delay this step until all possibilities for diff --git a/elf/dl-open.c b/elf/dl-open.c index dcc24130fe..a23e65926b 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -760,8 +760,8 @@ dl_open_worker_begin (void *a) if (!args->libc_already_loaded) { /* dlopen cannot be used to load an initial libc by design. */ - if (GL(dl_ns)[args->nsid].libc_map != NULL) - GL(dl_ns)[args->nsid].libc_map_early_init (false); + struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map; + _dl_call_libc_early_init (libc_map, false); } args->worker_continue = true; diff --git a/elf/dl-version.c b/elf/dl-version.c index d9ec44eed6..cda0889209 100644 --- a/elf/dl-version.c +++ b/elf/dl-version.c @@ -23,8 +23,6 @@ #include <string.h> #include <ldsodefs.h> #include <_itoa.h> -#include <gnu/lib-names.h> -#include <libc-early-init.h> #include <assert.h> @@ -361,22 +359,6 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) } } - /* Detect a libc.so loaded into this namespace. The - __libc_early_init lookup below means that we have to do this - after parsing the version data. */ - if (GL(dl_ns)[map->l_ns].libc_map == NULL - && map->l_info[DT_SONAME] != NULL - && strcmp (((const char *) D_PTR (map, l_info[DT_STRTAB]) - + map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0) - { - /* Look up this symbol early to trigger a mismatch error before - relocation (which may call IFUNC resolvers, and those can - have an internal ABI dependency). */ - GL(dl_ns)[map->l_ns].libc_map_early_init - = _dl_lookup_libc_early_init (map); - GL(dl_ns)[map->l_ns].libc_map = map; - } - /* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue an error if there is a DT_RELR entry without GLIBC_ABI_DT_RELR dependency. */ diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h index ac8c204bc7..a8edfadfb0 100644 --- a/elf/libc-early-init.h +++ b/elf/libc-early-init.h @@ -19,10 +19,13 @@ #ifndef _LIBC_EARLY_INIT_H #define _LIBC_EARLY_INIT_H -#include <libc_early_init_name.h> - struct link_map; +/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it + and call this function, with INITIAL as the argument. */ +void _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial) + attribute_hidden; + /* In the shared case, this function is defined in libc.so and invoked from ld.so (or on the fist static dlopen) after complete relocation of a new loaded libc.so, but before user-defined ELF constructors @@ -30,18 +33,6 @@ struct link_map; startup code. If INITIAL is true, the libc being initialized is the libc for the main program. INITIAL is false for libcs loaded for audit modules, dlmopen, and static dlopen. */ -void __libc_early_init (_Bool initial) -#ifdef SHARED -/* Redirect to the actual implementation name. */ - __asm__ (LIBC_EARLY_INIT_NAME_STRING) -#endif - ; - -/* Attempts to find the appropriately named __libc_early_init function - in LIBC_MAP. On lookup failure, an exception is signaled, - indicating an ld.so/libc.so mismatch. */ -__typeof (__libc_early_init) *_dl_lookup_libc_early_init (struct link_map * - libc_map) - attribute_hidden; +void __libc_early_init (_Bool initial); #endif /* _LIBC_EARLY_INIT_H */ diff --git a/elf/rtld.c b/elf/rtld.c index 910075c37f..cbbaf4a331 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1707,6 +1707,15 @@ dl_main (const ElfW(Phdr) *phdr, /* Extract the contents of the dynamic section for easy access. */ elf_get_dynamic_info (main_map, false, false); + /* If the main map is libc.so, update the base namespace to + refer to this map. If libc.so is loaded later, this happens + in _dl_map_object_from_fd. */ + if (main_map->l_info[DT_SONAME] != NULL + && (strcmp (((const char *) D_PTR (main_map, l_info[DT_STRTAB]) + + main_map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) + == 0)) + GL(dl_ns)[LM_ID_BASE].libc_map = main_map; + /* Set up our cache of pointers into the hash table. */ _dl_setup_hash (main_map); } @@ -2377,8 +2386,7 @@ dl_main (const ElfW(Phdr) *phdr, /* Relocation is complete. Perform early libc initialization. This is the initial libc, even if audit modules have been loaded with other libcs. */ - if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL) - GL(dl_ns)[LM_ID_BASE].libc_map_early_init (true); + _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map, true); /* Do any necessary cleanups for the startup OS interface code. We do these now so that no calls are made after rtld re-relocation |