aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2021-02-11 11:29:23 +0000
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2021-02-15 12:05:21 +0000
commit9fc1e41f6ed4bc1d98d6a357ac4fce2377d01ed3 (patch)
tree4d11b52c492bb7f5614f0352f0aabbf56ad7dd30
parentc6208126680a7351145a1c7fe37ae88337ed2b2c (diff)
downloadglibc-9fc1e41f6ed4bc1d98d6a357ac4fce2377d01ed3.tar
glibc-9fc1e41f6ed4bc1d98d6a357ac4fce2377d01ed3.tar.gz
glibc-9fc1e41f6ed4bc1d98d6a357ac4fce2377d01ed3.tar.bz2
glibc-9fc1e41f6ed4bc1d98d6a357ac4fce2377d01ed3.zip
x86_64: Avoid lazy relocation of tlsdesc [BZ #27137]
Lazy tlsdesc relocation is racy because the static tls optimization and tlsdesc management operations are done without holding the dlopen lock. This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 for aarch64, but it fixes a different race: bug 27137.
-rw-r--r--sysdeps/x86_64/dl-machine.h19
1 files changed, 14 insertions, 5 deletions
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 103eee6c3f..9a876a371e 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -570,12 +570,21 @@ elf_machine_lazy_rel (struct link_map *map,
}
else if (__glibc_likely (r_type == R_X86_64_TLSDESC))
{
- struct tlsdesc volatile * __attribute__((__unused__)) td =
- (struct tlsdesc volatile *)reloc_addr;
+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
+ const ElfW (Sym) *sym = &symtab[symndx];
+ const struct r_found_version *version = NULL;
- td->arg = (void*)reloc;
- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
- + map->l_addr);
+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ {
+ const ElfW (Half) *vernum =
+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
+ version = &map->l_versions[vernum[symndx] & 0x7fff];
+ }
+
+ /* Always initialize TLS descriptors completely at load time, in
+ case static TLS is allocated for it that requires locking. */
+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
}
else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE))
{