diff options
author | Florian Weimer <fweimer@redhat.com> | 2021-05-17 09:59:14 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2021-05-17 10:06:57 +0200 |
commit | 78b31cc8341ab8268c468cd0f4f988d1d7862a55 (patch) | |
tree | 52a91d569feb58d40449e34028ffb35b95f6e541 /elf/dl-open.c | |
parent | 23ce1cf35a59a4fdb3dabe073e3d1fe2b76fb0ca (diff) | |
download | glibc-78b31cc8341ab8268c468cd0f4f988d1d7862a55.tar.gz glibc-78b31cc8341ab8268c468cd0f4f988d1d7862a55.tar.xz glibc-78b31cc8341ab8268c468cd0f4f988d1d7862a55.zip |
elf: Partially initialize ld.so after static dlopen (bug 20802)
After static dlopen, a copy of ld.so is loaded into the inner namespace, but that copy is not initialized at all. Some architectures run into serious problems as result, which is why the _dl_var_init mechanism was invented. With libpthread moving into libc and parts into ld.so, more architectures impacted, so it makes sense to switch to a generic mechanism which performs the partial initialization. As a result, getauxval now works after static dlopen (bug 20802). Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'elf/dl-open.c')
-rw-r--r-- | elf/dl-open.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/elf/dl-open.c b/elf/dl-open.c index 0887fc5cc5..c2ac5ee94f 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -35,6 +35,7 @@ #include <libc-internal.h> #include <array_length.h> #include <libc-early-init.h> +#include <gnu/lib-names.h> #include <dl-dst.h> #include <dl-prop.h> @@ -590,8 +591,20 @@ dl_open_worker (void *a) /* So far, so good. Now check the versions. */ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL) - (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real, - 0, 0); + { + struct link_map *map = new->l_searchlist.r_list[i]->l_real; + _dl_check_map_versions (map, 0, 0); +#ifndef SHARED + /* During static dlopen, check if ld.so has been loaded. + Perform partial initialization in this case. This must + come after the symbol versioning initialization in + _dl_check_map_versions. */ + if (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), LD_SO) == 0) + __rtld_static_init (map); +#endif + } #ifdef SHARED /* Auditing checkpoint: we have added all objects. */ |