b1dca6
commit 23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6
b1dca6
Author: Florian Weimer <fweimer@redhat.com>
b1dca6
Date:   Thu Aug 15 14:37:50 2019 +0200
b1dca6
b1dca6
    elf: Self-dlopen failure with explict loader invocation [BZ #24900]
b1dca6
    
b1dca6
    In case of an explicit loader invocation, ld.so essentially performs
b1dca6
    a dlopen call to load the main executable.  Since the pathname of
b1dca6
    the executable is known at this point, it gets stored in the link
b1dca6
    map.  In regular mode, the pathname is not known and "" is used
b1dca6
    instead.
b1dca6
    
b1dca6
    As a result, if a program calls dlopen on the pathname of the main
b1dca6
    program, the dlopen call succeeds and returns a handle for the main
b1dca6
    map.  This results in an unnecessary difference between glibc
b1dca6
    testing (without --enable-hardcoded-path-in-tests) and production
b1dca6
    usage.
b1dca6
    
b1dca6
    This commit discards the names when building the link map in
b1dca6
    _dl_new_object for the main executable, but it still determines
b1dca6
    the origin at this point in case of an explict loader invocation.
b1dca6
    The reason is that the specified pathname has to be used; the kernel
b1dca6
    has a different notion of the main executable.
b1dca6
b1dca6
Conflicts:
b1dca6
	elf/Makefile
b1dca6
	elf/tst-dlopen-aout.c
b1dca6
	  (Differences due to the complicated history of the test.
b1dca6
	  The new test elf/tst-dlopen-aout-container is not backported
b1dca6
	  here.)
b1dca6
b1dca6
diff --git a/elf/dl-object.c b/elf/dl-object.c
b1dca6
index b37bcc1295f475f6..f6544a8fec45bdce 100644
b1dca6
--- a/elf/dl-object.c
b1dca6
+++ b/elf/dl-object.c
b1dca6
@@ -57,14 +57,30 @@ struct link_map *
b1dca6
 _dl_new_object (char *realname, const char *libname, int type,
b1dca6
 		struct link_map *loader, int mode, Lmid_t nsid)
b1dca6
 {
b1dca6
+#ifdef SHARED
b1dca6
+  unsigned int naudit;
b1dca6
+  if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
b1dca6
+    {
b1dca6
+      assert (type == lt_executable);
b1dca6
+      assert (nsid == LM_ID_BASE);
b1dca6
+
b1dca6
+      /* Ignore the specified libname for the main executable.  It is
b1dca6
+	 only known with an explicit loader invocation.  */
b1dca6
+      libname = "";
b1dca6
+
b1dca6
+      /* We create the map for the executable before we know whether
b1dca6
+	 we have auditing libraries and if yes, how many.  Assume the
b1dca6
+	 worst.  */
b1dca6
+      naudit = DL_NNS;
b1dca6
+    }
b1dca6
+  else
b1dca6
+    naudit = GLRO (dl_naudit);
b1dca6
+#endif
b1dca6
+
b1dca6
   size_t libname_len = strlen (libname) + 1;
b1dca6
   struct link_map *new;
b1dca6
   struct libname_list *newname;
b1dca6
 #ifdef SHARED
b1dca6
-  /* We create the map for the executable before we know whether we have
b1dca6
-     auditing libraries and if yes, how many.  Assume the worst.  */
b1dca6
-  unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC)
b1dca6
-					    ? DL_NNS : 0);
b1dca6
   size_t audit_space = naudit * sizeof (new->l_audit[0]);
b1dca6
 #else
b1dca6
 # define audit_space 0
b1dca6
@@ -91,8 +107,20 @@ _dl_new_object (char *realname, const char *libname, int type,
b1dca6
      and won't get dumped during core file generation. Therefore to assist
b1dca6
      gdb and to create more self-contained core files we adjust l_name to
b1dca6
      point at the newly allocated copy (which will get dumped) instead of
b1dca6
-     the ld.so rodata copy.  */
b1dca6
-  new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
b1dca6
+     the ld.so rodata copy.
b1dca6
+
b1dca6
+     Furthermore, in case of explicit loader invocation, discard the
b1dca6
+     name of the main executable, to match the regular behavior, where
b1dca6
+     name of the executable is not known.  */
b1dca6
+#ifdef SHARED
b1dca6
+  if (*realname != '\0' && (mode & __RTLD_OPENEXEC) == 0)
b1dca6
+#else
b1dca6
+  if (*realname != '\0')
b1dca6
+#endif
b1dca6
+    new->l_name = realname;
b1dca6
+  else
b1dca6
+    new->l_name = (char *) newname->name + libname_len - 1;
b1dca6
+
b1dca6
   new->l_type = type;
b1dca6
   /* If we set the bit now since we know it is never used we avoid
b1dca6
      dirtying the cache line later.  */
b1dca6
@@ -149,7 +177,14 @@ _dl_new_object (char *realname, const char *libname, int type,
b1dca6
 
b1dca6
   new->l_local_scope[0] = &new->l_searchlist;
b1dca6
 
b1dca6
-  /* Don't try to find the origin for the main map which has the name "".  */
b1dca6
+  /* Determine the origin.  If allocating the link map for the main
b1dca6
+     executable, the realname is not known and "".  In this case, the
b1dca6
+     origin needs to be determined by other means.  However, in case
b1dca6
+     of an explicit loader invocation, the pathname of the main
b1dca6
+     executable is known and needs to be processed here: From the
b1dca6
+     point of view of the kernel, the main executable is the
b1dca6
+     dynamic loader, and this would lead to a computation of the wrong
b1dca6
+     origin.  */
b1dca6
   if (realname[0] != '\0')
b1dca6
     {
b1dca6
       size_t realname_len = strlen (realname) + 1;