Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 May 2025 22:15:34 GMT
From:      Jessica Clarke <jrtc27@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: a08d92def20a - main - rtld-elf: Fix executable's TLS module index for direct exec
Message-ID:  <202505062215.546MFYfa063077@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by jrtc27:

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

commit a08d92def20a41243d4afc97cf4a2124be5386b9
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2025-05-06 22:14:51 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2025-05-06 22:14:51 +0000

    rtld-elf: Fix executable's TLS module index for direct exec
    
    For direct exec mode we reuse map_object, but tls_max_index is
    initialised to 1. As a result, the executable ends up being assigned
    module 2 (and the generation is pointlessly incremented, unlike in
    digest_phdr for the normal case). For most architectures this is
    harmless, since TLS linker relaxation will optimise General Dynamic
    accesses to Initial Exec or Local Exec for executables, but on RISC-V
    this relaxation does not exist, yet the linker will initialise the
    tls_index in the GOT with module 1, and at run time the call to
    __tls_get_addr will fail with:
    
        ld-elf.so.1: Can't find module with TLS index 1
    
    Fix this by making map_object use 1 for obj->tlsindex when it's loading
    the main executable, and don't bother to increment tls_dtv_generation
    either, matching digest_phdr (though that one is harmless).
    
    (Note this also applies to MIPS on stable/13)
    
    Reviewed by:    kib
    Fixes:          0fc65b0ab82c ("Make ld-elf.so.1 directly executable.")
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D50186
---
 libexec/rtld-elf/map_object.c | 10 +++++++---
 libexec/rtld-elf/rtld.c       |  4 ++--
 libexec/rtld-elf/rtld.h       |  2 +-
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index 148b6dc4ca6e..04d17072af77 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -60,7 +60,7 @@ phdr_in_zero_page(const Elf_Ehdr *hdr)
  * for the shared object.  Returns NULL on failure.
  */
 Obj_Entry *
-map_object(int fd, const char *path, const struct stat *sb)
+map_object(int fd, const char *path, const struct stat *sb, bool ismain)
 {
 	Obj_Entry *obj;
 	Elf_Ehdr *hdr;
@@ -327,8 +327,12 @@ map_object(int fd, const char *path, const struct stat *sb)
 		obj->interp = (const char *)(obj->relocbase +
 		    phinterp->p_vaddr);
 	if (phtls != NULL) {
-		tls_dtv_generation++;
-		obj->tlsindex = ++tls_max_index;
+		if (ismain)
+			obj->tlsindex = 1;
+		else {
+			tls_dtv_generation++;
+			obj->tlsindex = ++tls_max_index;
+		}
 		obj->tlssize = phtls->p_memsz;
 		obj->tlsalign = phtls->p_align;
 		obj->tlspoffset = phtls->p_offset;
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index d7ac1e36d70f..eb04a2f17603 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -784,7 +784,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 	 */
 	if (fd != -1) { /* Load the main program. */
 		dbg("loading main program");
-		obj_main = map_object(fd, argv0, NULL);
+		obj_main = map_object(fd, argv0, NULL, true);
 		close(fd);
 		if (obj_main == NULL)
 			rtld_die();
@@ -2920,7 +2920,7 @@ do_load_object(int fd, const char *name, char *path, struct stat *sbp,
 	}
 
 	dbg("loading \"%s\"", printable_path(path));
-	obj = map_object(fd, printable_path(path), sbp);
+	obj = map_object(fd, printable_path(path), sbp, false);
 	if (obj == NULL)
 		return (NULL);
 
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index d1ea00b96627..a15c1d6d159f 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -380,7 +380,7 @@ enum {
 void _rtld_error(const char *, ...) __printflike(1, 2) __exported;
 void rtld_die(void) __dead2;
 const char *rtld_strerror(int);
-Obj_Entry *map_object(int, const char *, const struct stat *);
+Obj_Entry *map_object(int, const char *, const struct stat *, bool);
 void *xcalloc(size_t, size_t);
 void *xmalloc(size_t);
 char *xstrdup(const char *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202505062215.546MFYfa063077>