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