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