| From de7a7c04a92dbc5d35cb37e47c471e12784cc95e Mon Sep 17 00:00:00 2001 |
| From: Khem Raj <raj.khem@gmail.com> |
| Date: Wed, 18 Mar 2015 00:20:09 +0000 |
| Subject: [PATCH 11/29] 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 <andrei.adrianx.dinu@intel.com> |
| Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| --- |
| 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 90856779b1..a29bb86c56 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: |
| -- |
| 2.27.0 |
| |