elf: rtld_multiple_ref is always true

For a long time, libc.so.6 has dependend on ld.so, which
means that there is a reference to ld.so in all processes,
and rtld_multiple_ref is always true.  In fact, if
rtld_multiple_ref were false, some of the ld.so setup code
would not run.

Reviewed-by: DJ Delorie <dj@redhat.com>
This commit is contained in:
Florian Weimer 2024-11-06 10:33:44 +01:00
parent 273694cd78
commit 8f8dd904c4

View File

@ -1963,43 +1963,37 @@ dl_main (const ElfW(Phdr) *phdr,
if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map)) if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map))
break; break;
bool rtld_multiple_ref = false; /* Insert the link map for the dynamic loader into the chain in
if (__glibc_likely (i < main_map->l_searchlist.r_nlist)) symbol search order because gdb uses the chain's order as its
symbol search order. */
GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
if (__glibc_likely (state.mode == rtld_mode_normal))
{ {
/* Some DT_NEEDED entry referred to the interpreter object itself, so GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist
put it back in the list of visible objects. We insert it into the ? main_map->l_searchlist.r_list[i + 1]
chain in symbol search order because gdb uses the chain's order as : NULL);
its symbol search order. */
rtld_multiple_ref = true;
GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1];
if (__glibc_likely (state.mode == rtld_mode_normal))
{
GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist
? main_map->l_searchlist.r_list[i + 1]
: NULL);
#ifdef NEED_DL_SYSINFO_DSO #ifdef NEED_DL_SYSINFO_DSO
if (GLRO(dl_sysinfo_map) != NULL if (GLRO(dl_sysinfo_map) != NULL
&& GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map) && GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map)
&& GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map)) && GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map))
GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map); GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map);
#endif #endif
} }
else else
/* In trace mode there might be an invisible object (which we /* In trace mode there might be an invisible object (which we
could not find) after the previous one in the search list. could not find) after the previous one in the search list.
In this case it doesn't matter much where we put the In this case it doesn't matter much where we put the
interpreter object, so we just initialize the list pointer so interpreter object, so we just initialize the list pointer so
that the assertion below holds. */ that the assertion below holds. */
GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next; GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next;
assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next); assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next);
GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map); GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map);
if (GL(dl_rtld_map).l_next != NULL) if (GL(dl_rtld_map).l_next != NULL)
{ {
assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev); assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev);
GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map); GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map);
}
} }
/* Now let us see whether all libraries are available in the /* Now let us see whether all libraries are available in the
@ -2327,35 +2321,33 @@ dl_main (const ElfW(Phdr) *phdr,
/* Make sure no new search directories have been added. */ /* Make sure no new search directories have been added. */
assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs)); assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs));
if (rtld_multiple_ref) /* Re-relocate ourselves with user-controlled symbol definitions.
{
/* There was an explicit ref to the dynamic linker as a shared lib.
Re-relocate ourselves with user-controlled symbol definitions.
We must do this after TLS initialization in case after this We must do this after TLS initialization in case after this
re-relocation, we might call a user-supplied function re-relocation, we might call a user-supplied function
(e.g. calloc from _dl_relocate_object) that uses TLS data. */ (e.g. calloc from _dl_relocate_object) that uses TLS data. */
/* Set up the object lookup structures. */ /* Set up the object lookup structures. */
_dl_find_object_init (); _dl_find_object_init ();
/* The malloc implementation has been relocated, so resolving /* The malloc implementation has been relocated, so resolving
its symbols (and potentially calling IFUNC resolvers) is safe its symbols (and potentially calling IFUNC resolvers) is safe
at this point. */ at this point. */
__rtld_malloc_init_real (main_map); __rtld_malloc_init_real (main_map);
/* Likewise for the locking implementation. */ /* Likewise for the locking implementation. */
__rtld_mutex_init (); __rtld_mutex_init ();
RTLD_TIMING_VAR (start); {
rtld_timer_start (&start); RTLD_TIMING_VAR (start);
rtld_timer_start (&start);
/* Mark the link map as not yet relocated again. */ /* Mark the link map as not yet relocated again. */
GL(dl_rtld_map).l_relocated = 0; GL(dl_rtld_map).l_relocated = 0;
_dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
rtld_timer_accum (&relocate_time, start); rtld_timer_accum (&relocate_time, start);
} }
/* Relocation is complete. Perform early libc initialization. This /* Relocation is complete. Perform early libc initialization. This
is the initial libc, even if audit modules have been loaded with is the initial libc, even if audit modules have been loaded with