]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
x86_64: Avoid lazy relocation of tlsdesc [BZ #27137]
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Thu, 11 Feb 2021 11:29:23 +0000 (11:29 +0000)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Mon, 15 Feb 2021 12:05:21 +0000 (12:05 +0000)
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.

sysdeps/x86_64/dl-machine.h

index 103eee6c3ff6e1ac88a6415d2f74ee1800483ded..9a876a371e157916bb7731a0241537a99ea1e644 100644 (file)
@@ -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))
     {