git: 91880e07f605 - main - rtld: do not allow both dynamic DTV index and static TLS offset

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 05 Jun 2023 19:33:52 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=91880e07f605edb90339685bc934699a4344de3b

commit 91880e07f605edb90339685bc934699a4344de3b
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-06-05 00:54:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-06-05 19:33:18 +0000

    rtld: do not allow both dynamic DTV index and static TLS offset
    
    If we are allocating static offset for an object with dynamic index,
    return failure.  In the opposite case, if dynamic index is requested for
    statically allocated TLS area, directly use the offset instead of
    setting the index.
    
    Taken from NetBSD Joerg Sonnenberger change for src/libexec/ld.elf_so/tls.c
    rev. 1.18.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
---
 libexec/rtld-elf/rtld.c | 14 ++++++++++++++
 libexec/rtld-elf/rtld.h |  1 +
 2 files changed, 15 insertions(+)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 9ed9a4aed4bb..72a128ccbb81 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -5463,6 +5463,17 @@ allocate_module_tls(int index)
 		rtld_die();
 	}
 
+	if (obj->tls_static) {
+#ifdef TLS_VARIANT_I
+		p = (char *)_tcb_get() + obj->tlsoffset;
+#else
+		p = (char *)_tcb_get() - obj->tlsoffset;
+#endif
+		return (p);
+	}
+
+	obj->tls_dynamic = true;
+
 	p = malloc_aligned(obj->tlssize, obj->tlsalign, obj->tlspoffset);
 	memcpy(p, obj->tlsinit, obj->tlsinitsize);
 	memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
@@ -5474,6 +5485,9 @@ allocate_tls_offset(Obj_Entry *obj)
 {
     size_t off;
 
+    if (obj->tls_dynamic)
+	return (false);
+
     if (obj->tls_static)
 	return (true);
 
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index 025bf4ff0670..b8b0d67bd05d 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -246,6 +246,7 @@ typedef struct Struct_Obj_Entry {
     bool jmpslots_done : 1;	/* Already have relocated the jump slots */
     bool init_done : 1;		/* Already have added object to init list */
     bool tls_static : 1;	/* Already allocated offset for static TLS */
+    bool tls_dynamic : 1;	/* A non-static DTV entry has been allocated */
     bool phdr_alloc : 1;	/* Phdr is allocated and needs to be freed. */
     bool z_origin : 1;		/* Process rpath and soname tokens */
     bool z_nodelete : 1;	/* Do not unload the object and dependencies */