elf: Never use the file ID of the main executable [BZ #24900]

If the loader is invoked explicitly and loads the main executable,
it stores the file ID of the main executable in l_file_id.  This
information is not available if the main excutable is loaded by the
kernel, so this is another case where the two cases differ.

This enhances commit 23d2e5faf0
("elf: Self-dlopen failure with explict loader invocation
[BZ #24900]").

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
This commit is contained in:
Florian Weimer 2019-10-04 21:22:54 +02:00
parent eaad14b56a
commit 2b26b084e4
2 changed files with 38 additions and 21 deletions

View File

@ -1,3 +1,10 @@
2019-10-04 Florian Weimer <fweimer@redhat.com>
[BZ #24900]
* elf/dl-load.c (_dl_map_object_from_fd): Do not use the file ID
when loading the executable as part of an explicit loader
invocation.
2019-10-04 Florian Weimer <fweimer@redhat.com> 2019-10-04 Florian Weimer <fweimer@redhat.com>
nptl: Move pthread_attr_setinheritsched implementation into libc. nptl: Move pthread_attr_setinheritsched implementation into libc.

View File

@ -876,33 +876,43 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
struct r_debug *r = _dl_debug_initialize (0, nsid); struct r_debug *r = _dl_debug_initialize (0, nsid);
bool make_consistent = false; bool make_consistent = false;
/* Get file information. */ /* Get file information. To match the kernel behavior, do not fill
in this information for the executable in case of an explicit
loader invocation. */
struct r_file_id id; struct r_file_id id;
if (__glibc_unlikely (!_dl_get_file_id (fd, &id))) if (mode & __RTLD_OPENEXEC)
{ {
errstring = N_("cannot stat shared object"); assert (nsid == LM_ID_BASE);
call_lose_errno: memset (&id, 0, sizeof (id));
errval = errno;
call_lose:
lose (errval, fd, name, realname, l, errstring,
make_consistent ? r : NULL, nsid);
} }
else
{
if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
{
errstring = N_("cannot stat shared object");
call_lose_errno:
errval = errno;
call_lose:
lose (errval, fd, name, realname, l, errstring,
make_consistent ? r : NULL, nsid);
}
/* Look again to see if the real name matched another already loaded. */ /* Look again to see if the real name matched another already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next) for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id)) if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
{ {
/* The object is already loaded. /* The object is already loaded.
Just bump its reference count and return it. */ Just bump its reference count and return it. */
__close_nocancel (fd); __close_nocancel (fd);
/* If the name is not in the list of names for this object add /* If the name is not in the list of names for this object add
it. */ it. */
free (realname); free (realname);
add_name_to_object (l, name); add_name_to_object (l, name);
return l; return l;
} }
}
#ifdef SHARED #ifdef SHARED
/* When loading into a namespace other than the base one we must /* When loading into a namespace other than the base one we must