git: dc56749b2074 - stable/13 - rtld: do not allow both dynamic DTV index and static TLS offset

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sun, 11 Jun 2023 23:40:21 UTC
The branch stable/13 has been updated by kib:

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

commit dc56749b2074b4f3e95e7295ac60f04e611949e3
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-06-05 00:54:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-06-11 23:39:43 +0000

    rtld: do not allow both dynamic DTV index and static TLS offset
    
    (cherry picked from commit 91880e07f605edb90339685bc934699a4344de3b)
---
 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 8aa717021c97..017833164a18 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -5509,6 +5509,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);
@@ -5520,6 +5531,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 7db3f00e0dc5..9bc75dc97546 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -252,6 +252,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 */