From fe8d9b76e7c881cc0a0b728ea2bd637fafca0978 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Wed, 18 Mar 2015 00:20:09 +0000 Subject: [PATCH] Quote from bug 1443 which explains what the patch does : We build some random program and link it with -lust. When we run it, it dies with a SIGSEGV before reaching main(). Libust.so depends on liburcu-bp.so from the usermode-rcu package. Although libust.so is not prelinked, liburcu-bp.so IS prelinked; this is critical. Libust.so uses a TLS / __thread variable that is defined in liburcu- bp.so. There are special ARM-specific relocation types that allow two shared libraries to share thread-specific data. This is critical too. One more critical issue: although liburcu-bp.so is prelinked, we can't load it at its prelinked address, because we also link against librt.so, and librt.so uses that address. The dynamic linker is forced to relink liburcu-bp.so at a different address. In the course of relinking, it processes the special ARM relocation record mentioned above. The prelinker has already filled in the information, which is a short offset into a table of thread- specific data that is allocated per-thread for each library that uses TLS. Because the normal behavior of a relocation is to add the symbol value to an addend stored at the address being relocated, we end up adding the short offset to itself, doubling it. Now we have an awkward situation. The libust.so library doesn't know about the addend, so its TLS data for this element is correct. The liburcu-bp.so library has a different offset for the element. When we go to initialize the element for the first time in liburcu-bp.so, we write the address of the result at the doubled (broken) offset. Later, when we refer to the address from libust.so, we check the value at the correct offset, but it's NULL, so we eat hot SIGSEGV. Upstream-Status: Pending Signed-off-by: Andrei Dinu Signed-off-by: Khem Raj --- sysdeps/arm/dl-machine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index 1a4fd3f17b..a02c47571a 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -510,7 +510,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, case R_ARM_TLS_DTPOFF32: if (sym != NULL) - *reloc_addr += sym->st_value; + *reloc_addr = sym->st_value; break; case R_ARM_TLS_TPOFF32: