7c0489
Partial backport without the new tst-dlopen-aout-pie test.  The test
7c0489
fails because the a self-dlopen of a PIE binary succeeds, as commit
7c0489
23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6 ("elf: Self-dlopen failure
7c0489
with explict loader invocation [BZ #24900]") has not been backported.
7c0489
7c0489
commit 77523d5e43cb5721c23855eb6045b0607a3b30a0
7c0489
Author: Florian Weimer <fweimer@redhat.com>
7c0489
Date:   Fri Oct 4 21:23:51 2019 +0200
7c0489
7c0489
    elf: Assign TLS modid later during dlopen [BZ #24930]
7c0489
    
7c0489
    Commit a42faf59d6d9f82e5293a9ebcc26d9c9e562b12b ("Fix BZ #16634.")
7c0489
    attempted to fix a TLS modid consistency issue by adding additional
7c0489
    checks to the open_verify function.  However, this is fragile
7c0489
    because open_verify cannot reliably predict whether
7c0489
    _dl_map_object_from_fd will later fail in the more complex cases
7c0489
    (such as memory allocation failures).  Therefore, this commit
7c0489
    assigns the TLS modid as late as possible.  At that point, the link
7c0489
    map pointer will eventually be passed to _dl_close, which will undo
7c0489
    the TLS modid assignment.
7c0489
    
7c0489
    Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
7c0489
7c0489
diff --git a/elf/dl-load.c b/elf/dl-load.c
7c0489
index bb839ef70ff46f37..b190b28e32e47391 100644
7c0489
--- a/elf/dl-load.c
7c0489
+++ b/elf/dl-load.c
7c0489
@@ -1134,27 +1134,21 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
7c0489
 	     offset.  We will adjust it later.  */
7c0489
 	  l->l_tls_initimage = (void *) ph->p_vaddr;
7c0489
 
7c0489
-	  /* If not loading the initial set of shared libraries,
7c0489
-	     check whether we should permit loading a TLS segment.  */
7c0489
-	  if (__glibc_likely (l->l_type == lt_library)
7c0489
-	      /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did
7c0489
-		 not set up TLS data structures, so don't use them now.  */
7c0489
-	      || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))
7c0489
-	    {
7c0489
-	      /* Assign the next available module ID.  */
7c0489
-	      l->l_tls_modid = _dl_next_tls_modid ();
7c0489
-	      break;
7c0489
-	    }
7c0489
+	  /* l->l_tls_modid is assigned below, once there is no
7c0489
+	     possibility for failure.  */
7c0489
 
7c0489
+	  if (l->l_type != lt_library
7c0489
+	      && GL(dl_tls_dtv_slotinfo_list) == NULL)
7c0489
+	    {
7c0489
 #ifdef SHARED
7c0489
-	  /* We are loading the executable itself when the dynamic
7c0489
-	     linker was executed directly.  The setup will happen
7c0489
-	     later.  Otherwise, the TLS data structures are already
7c0489
-	     initialized, and we assigned a TLS modid above.  */
7c0489
-	  assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0);
7c0489
+	      /* We are loading the executable itself when the dynamic
7c0489
+		 linker was executed directly.  The setup will happen
7c0489
+		 later.  */
7c0489
+	      assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0);
7c0489
 #else
7c0489
-	  assert (false && "TLS not initialized in static application");
7c0489
+	      assert (false && "TLS not initialized in static application");
7c0489
 #endif
7c0489
+	    }
7c0489
 	  break;
7c0489
 
7c0489
 	case PT_GNU_STACK:
7c0489
@@ -1395,6 +1389,18 @@ cannot enable executable stack as shared object requires");
7c0489
     add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
7c0489
 			    + l->l_info[DT_SONAME]->d_un.d_val));
7c0489
 
7c0489
+  /* _dl_close can only eventually undo the module ID assignment (via
7c0489
+     remove_slotinfo) if this function returns a pointer to a link
7c0489
+     map.  Therefore, delay this step until all possibilities for
7c0489
+     failure have been excluded.  */
7c0489
+  if (l->l_tls_blocksize > 0
7c0489
+      && (__glibc_likely (l->l_type == lt_library)
7c0489
+	  /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did
7c0489
+	     not set up TLS data structures, so don't use them now.  */
7c0489
+	  || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL)))
7c0489
+    /* Assign the next available module ID.  */
7c0489
+    l->l_tls_modid = _dl_next_tls_modid ();
7c0489
+
7c0489
 #ifdef DL_AFTER_LOAD
7c0489
   DL_AFTER_LOAD (l);
7c0489
 #endif
7c0489
@@ -1662,17 +1668,6 @@ open_verify (const char *name, int fd,
7c0489
 	  errstring = N_("only ET_DYN and ET_EXEC can be loaded");
7c0489
 	  goto call_lose;
7c0489
 	}
7c0489
-      else if (__glibc_unlikely (ehdr->e_type == ET_EXEC
7c0489
-				 && (mode & __RTLD_OPENEXEC) == 0))
7c0489
-	{
7c0489
-	  /* BZ #16634. It is an error to dlopen ET_EXEC (unless
7c0489
-	     __RTLD_OPENEXEC is explicitly set).  We return error here
7c0489
-	     so that code in _dl_map_object_from_fd does not try to set
7c0489
-	     l_tls_modid for this module.  */
7c0489
-
7c0489
-	  errstring = N_("cannot dynamically load executable");
7c0489
-	  goto call_lose;
7c0489
-	}
7c0489
       else if (__glibc_unlikely (ehdr->e_phentsize != sizeof (ElfW(Phdr))))
7c0489
 	{
7c0489
 	  errstring = N_("ELF file's phentsize not the expected size");