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

login
register
mail settings
Submitter Florian Weimer
Date Aug. 22, 2019, 4:54 p.m.
Message ID <87pnkxw36k.fsf@oldenburg2.str.redhat.com>
Download mbox | patch
Permalink /patch/34246/
State New
Headers show

Comments

Florian Weimer - Aug. 22, 2019, 4:54 p.m.
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 23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6
("elf: Self-dlopen failure with explict loader invocation
[BZ #24900]").

2019-08-22  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.

Patch

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 5abeb867f1..7bf0ca563e 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -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);
   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;
-  if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
+  if (mode & __RTLD_OPENEXEC)
     {
-      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);
+      assert (nsid == LM_ID_BASE);
+      memset (&id, 0, sizeof (id));
     }
+  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.  */
-  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))
-      {
-	/* The object is already loaded.
-	   Just bump its reference count and return it.  */
-	__close_nocancel (fd);
+      /* 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)
+	if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
+	  {
+	    /* The object is already loaded.
+	       Just bump its reference count and return it.  */
+	    __close_nocancel (fd);
 
-	/* If the name is not in the list of names for this object add
-	   it.  */
-	free (realname);
-	add_name_to_object (l, name);
+	    /* If the name is not in the list of names for this object add
+	       it.  */
+	    free (realname);
+	    add_name_to_object (l, name);
 
-	return l;
-      }
+	    return l;
+	  }
+    }
 
 #ifdef SHARED
   /* When loading into a namespace other than the base one we must