git: 02cb2f8094ba - stable/14 - Revert "rtld: fix allocate_module_tls() variant I fallback to static allocation"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 15 Dec 2025 17:00:29 UTC
The branch stable/14 has been updated by jrtc27:
URL: https://cgit.FreeBSD.org/src/commit/?id=02cb2f8094baab0b4299e5fcd1694d9193be14b3
commit 02cb2f8094baab0b4299e5fcd1694d9193be14b3
Author: Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2025-05-28 20:24:52 +0000
Commit: Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2025-12-15 16:58:45 +0000
Revert "rtld: fix allocate_module_tls() variant I fallback to static allocation"
This was applying a NetBSD fix to FreeBSD. However, the original code
was correct for FreeBSD. NetBSD's obj->tlsoffset is relative to the end
of the TCB, not the TCB itself, whilst ours is relative to the TCB[1]
itself. For example, our allocate_tls uses (char *)tcb + obj->tlsoffset
for the memcpy and memset calls.
Without this reverted, for dynamically loaded shared objects, Initial
Exec accesses to TLS variables on variant I architectures (non-x86) use
the correct address, whilst General Dynamic and dlsym(3) use the
incorrect address (TLS_TCB_SIZE past the start). Note that, on arm64,
LLVM only supports TLSDESC (including LLD) and TLSDESC will use the
static resolver if the variable ends up allocated to the static TLS
block, even in the presence of dlopen(3), so only dlsym(3) shows the
discrepancy there.
Whilst here, add a comment to explain this difference to try and avoid
the same mistake being made in future.
[1] In the case of variant II, it's the amount to subtract, so still
positive
This reverts commit e9a38ed2fa61fd264a80f24ceb35f39b0ac6463d.
Reviewed by: kib (prior version)
Fixes: e9a38ed2fa61 ("rtld: fix allocate_module_tls() variant I fallback to static allocation")
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D50565
(cherry picked from commit ccfb1c50e45dbb7fcadf7e1932f63cf1702ef13a)
---
libexec/rtld-elf/rtld.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index a7fdc153eca8..5117448a0d28 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -5378,6 +5378,9 @@ get_tls_block_ptr(void *tcb, size_t tcbsize)
* it is based on tls_last_offset, and TLS offsets here are really TCB
* offsets, whereas libc's tls_static_space is just the executable's static
* TLS segment.
+ *
+ * NB: This differs from NetBSD's ld.elf_so, where TLS offsets are relative to
+ * the end of the TCB.
*/
void *
allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign)
@@ -5612,7 +5615,7 @@ allocate_module_tls(int index)
if (obj->tls_static) {
#ifdef TLS_VARIANT_I
- p = (char *)_tcb_get() + obj->tlsoffset + TLS_TCB_SIZE;
+ p = (char *)_tcb_get() + obj->tlsoffset;
#else
p = (char *)_tcb_get() - obj->tlsoffset;
#endif