git: e10cca68cf34 - stable/13 - rtld/arm: fix initial-exec (IE) thread-local storage relocation
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 22 Nov 2024 15:42:14 UTC
The branch stable/13 has been updated by rcm: URL: https://cgit.FreeBSD.org/src/commit/?id=e10cca68cf349d11bc5c6474b792529bffc789cf commit e10cca68cf349d11bc5c6474b792529bffc789cf Author: R. Christian McDonald <rcm@rcm.sh> AuthorDate: 2023-11-03 12:56:58 +0000 Commit: R. Christian McDonald <rcm@FreeBSD.org> CommitDate: 2024-11-22 15:41:10 +0000 rtld/arm: fix initial-exec (IE) thread-local storage relocation net/frr[89] revealed an interesting edge-case on arm when dynamically linking a shared library that declares more than one static TLS variable with at least one using the "initial-exec" TLS model. In the case of frr[89], this library was libfrr.so which essentially does the following: #include <stdio.h> #include "lib.h" static __thread int *a __attribute__((tls_model("initial-exec"))); void lib_test() { static __thread int b = -1; printf("&a = %p\n", &a); printf(" a = %p\n", a); printf("\n"); printf("&b = %p\n", &b); printf(" b = %d\n", b); } Allocates a file scoped `static __thread` pointer with tls_model("initial-exec") and later a block scoped TLS int. Notice in the above minimal reproducer, `b == -1`. The relocation process does the wrong thing and ends up pointing both `a` and `b` at the same place in memory. The output of the above in the broken state is: &a = 0x4009c018 a = 0xffffffff &b = 0x4009c018 b = -1 With the patch applied, the output becomes: &a = 0x4009c01c a = 0x0 &b = 0x4009c018 b = -1 Reviewed by: kib Approved by: kp (mentor) Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D42415/ (cherry picked from commit 98fd69f0090da73d9d0451bd769d7752468284c6) --- libexec/rtld-elf/arm/reloc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index e2dc7f8c9eb9..b62a62c5b116 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -322,10 +322,13 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache, return -1; tmp = (Elf_Addr)def->st_value + defobj->tlsoffset; - if (__predict_true(RELOC_ALIGNED_P(where))) + if (__predict_true(RELOC_ALIGNED_P(where))) { + tmp += *where; *where = tmp; - else + } else { + tmp += load_ptr(where); store_ptr(where, tmp); + } dbg("TLS_TPOFF32 %s in %s --> %p", obj->strtab + obj->symtab[symnum].st_name, obj->path, (void *)tmp);