Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 Dec 2025 18:18:53 +0000
Message-ID:  <6940510d.24ebc.5fa078df@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/13 has been updated by jrtc27:

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

commit 6216ed808d1b0ec1921f49b5bba454f38d152a0c
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2025-05-06 22:14:51 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2025-12-15 17:56:36 +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
    
    (cherry picked from commit a08d92def20a41243d4afc97cf4a2124be5386b9)
---
 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 eaf96fb80925..830974d22f9e 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;
@@ -314,8 +314,12 @@ map_object(int fd, const char *path, const struct stat *sb)
     if (phinterp != NULL)
 	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 980f5c89edb7..9725dcdd805f 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -777,7 +777,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();
@@ -2891,7 +2891,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 306c460f286d..54015b5122f7 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -368,7 +368,7 @@ typedef struct Struct_SymLook {
 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 *);


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6940510d.24ebc.5fa078df>