Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 1 | From 48262b6dda935278a40374ddf0080ab6cc999582 Mon Sep 17 00:00:00 2001 |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 2 | From: Khem Raj <raj.khem@gmail.com> |
| 3 | Date: Wed, 18 Mar 2015 00:20:09 +0000 |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 4 | Subject: [PATCH 09/27] Quote from bug 1443 which explains what the patch does |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 5 | : |
| 6 | |
| 7 | We build some random program and link it with -lust. When we run it, |
| 8 | it dies with a SIGSEGV before reaching main(). |
| 9 | |
| 10 | Libust.so depends on liburcu-bp.so from the usermode-rcu package. |
| 11 | Although libust.so is not prelinked, liburcu-bp.so IS prelinked; this |
| 12 | is critical. |
| 13 | |
| 14 | Libust.so uses a TLS / __thread variable that is defined in liburcu- |
| 15 | bp.so. There are special ARM-specific relocation types that allow two |
| 16 | shared libraries to share thread-specific data. This is critical too. |
| 17 | |
| 18 | One more critical issue: although liburcu-bp.so is prelinked, we can't |
| 19 | load it at its prelinked address, because we also link against |
| 20 | librt.so, and librt.so uses that address. |
| 21 | |
| 22 | The dynamic linker is forced to relink liburcu-bp.so at a different |
| 23 | address. In the course of relinking, it processes the special ARM |
| 24 | relocation record mentioned above. The prelinker has already filled |
| 25 | in the information, which is a short offset into a table of thread- |
| 26 | specific data that is allocated per-thread for each library that uses |
| 27 | TLS. Because the normal behavior of a relocation is to add the symbol |
| 28 | value to an addend stored at the address being relocated, we end up |
| 29 | adding the short offset to itself, doubling it. |
| 30 | |
| 31 | Now we have an awkward situation. The libust.so library doesn't know |
| 32 | about the addend, so its TLS data for this element is correct. The |
| 33 | liburcu-bp.so library has a different offset for the element. When we |
| 34 | go to initialize the element for the first time in liburcu-bp.so, we |
| 35 | write the address of the result at the doubled (broken) offset. |
| 36 | Later, when we refer to the address from libust.so, we check the value |
| 37 | at the correct offset, but it's NULL, so we eat hot SIGSEGV. |
| 38 | |
| 39 | Upstream-Status: Pending |
| 40 | |
| 41 | Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> |
| 42 | Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| 43 | --- |
| 44 | sysdeps/arm/dl-machine.h | 2 +- |
| 45 | 1 file changed, 1 insertion(+), 1 deletion(-) |
| 46 | |
| 47 | diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 48 | index 8a00eab5e3..623edcb1bd 100644 |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 49 | --- a/sysdeps/arm/dl-machine.h |
| 50 | +++ b/sysdeps/arm/dl-machine.h |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 51 | @@ -510,7 +510,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 52 | |
| 53 | case R_ARM_TLS_DTPOFF32: |
| 54 | if (sym != NULL) |
| 55 | - *reloc_addr += sym->st_value; |
| 56 | + *reloc_addr = sym->st_value; |
| 57 | break; |
| 58 | |
| 59 | case R_ARM_TLS_TPOFF32: |
| 60 | -- |
Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 61 | 2.16.1 |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 62 | |