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