summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-10-04 21:22:54 +0200
committerFlorian Weimer <fweimer@redhat.com>2019-10-04 21:22:54 +0200
commit2b26b084e4e4ba58a2ff9f8f8f14c9bca506bd59 (patch)
tree4e22bfbb8197ffdbf3fb5d86b3613dee441d8491 /elf
parenteaad14b56aa0d18b3b6bbb1618de2ab5b242d434 (diff)
downloadglibc-2b26b084e4e4ba58a2ff9f8f8f14c9bca506bd59.tar.gz
glibc-2b26b084e4e4ba58a2ff9f8f8f14c9bca506bd59.tar.xz
glibc-2b26b084e4e4ba58a2ff9f8f8f14c9bca506bd59.zip
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 23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6
("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>
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-load.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 21a91b9484..8f192036a5 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