| commit 8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86 |
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> |
| Date: Thu Feb 11 11:29:23 2021 +0000 |
| |
| 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. |
| |
| Another issue is that ld auditing ignores DT_BIND_NOW and thus tries to |
| relocate tlsdesc lazily, but that does not work in a BIND_NOW module |
| due to missing DT_TLSDESC_PLT. Unconditionally relocating tlsdesc at |
| load time fixes this bug 27721 too. |
| |
| diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h |
| index e308b662d245cc63..ef5740ba281c7282 100644 |
| |
| |
| @@ -563,12 +563,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)) |
| { |