From d4b23912214ecc61ebbf635bc40bfa3393731f92 Mon Sep 17 00:00:00 2001 From: oddcoder Date: Sat, 18 Jul 2020 20:32:03 +0200 Subject: [PATCH] Fix wrong TLS resolving I attempted fixing this issue before at 43fbaf99. Although it did work, it worked wrong, and it was just consistently working (but in wrong way) until it didn't. Since this is (hopefully) the real fix, I will try to explain exactly what is going on. This is explaination by example: our TLS is memory of size 0x1000 starting at 0x7ffff6c50000, but the real size is 0x000068 so we have padding stored at master.offset = 0xf98 Now our symbol looks as follows Offset Type Sym. Value Name 000000432b20 R_X86_64_DTPOFF64 0000000000000058 errno The old code did 0x7ffff6c50000 + 0xf98 + 000000432b20 which is obviosly overflowing the memory and wrong. The right way 0x7ffff6c50000 + 0xf98 + 0000000000000058. THe Tls base part and offset are added at __tls_get_addr function. What is left is storing the 0x58 at the relocation address. The problem is that we don't have 0x58, but we have (binary base + 0x58) in global symbol table and binary base so what we store is the (binarybase + 0x58 - binary base). I hope this does turn out to be wrong. --- src/ld_so/linker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 00ef617293..6b54a35a66 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -694,7 +694,7 @@ impl Linker { set_u64(tm as u64); } reloc::R_X86_64_DTPOFF64 => { - set_u64(rel.r_offset as u64); + set_u64((s - b) as u64); } reloc::R_X86_64_GLOB_DAT | reloc::R_X86_64_JUMP_SLOT => { set_u64(s as u64);