git: ef758b59a44e - main - rtld: release rtld_bind_lock around calls to .preinit_array initializers

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 10 Oct 2026 17:03:36 UTC
The branch main has been updated by kib:

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

commit ef758b59a44e6b5b2d2dc178b97c01cde1b34570
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-10-10 15:05:55 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-10-10 17:03:01 +0000

    rtld: release rtld_bind_lock around calls to .preinit_array initializers
    
    We unlock the bind lock around .init calls anyway.  Also, the main
    object cannot be unloaded.
    
    Reported and reviewed by:       dim
    PR:     298943
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D60588
---
 libexec/rtld-elf/rtld.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index c64fb689276d..b637a3032218 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -187,7 +187,7 @@ static char *origin_subst_one(Obj_Entry *, char *, const char *, const char *,
     bool);
 static char *origin_subst(Obj_Entry *, const char *);
 static bool obj_resolve_origin(Obj_Entry *obj);
-static void preinit_main(void);
+static void preinit_main(RtldLockState *lockstate);
 static void rtld_recalc_bind_not(const char *);
 static void rtld_recalc_dangerous_ld_env(void);
 static void rtld_recalc_debug(const char *);
@@ -1005,7 +1005,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
 
 	rtld_exit_ptr = rtld_exit;
 	if (obj_main->crt_no_init)
-		preinit_main();
+		preinit_main(&lockstate);
 	objlist_call_init(&initlist, &lockstate);
 	_r_debug_postinit(&obj_main->linkmap);
 	objlist_clear(&initlist);
@@ -3122,7 +3122,7 @@ obj_from_addr(const void *addr)
 }
 
 static void
-preinit_main(void)
+preinit_main(RtldLockState *lockstate)
 {
 	uintptr_t *preinit_addr;
 	int index;
@@ -3131,6 +3131,7 @@ preinit_main(void)
 	if (preinit_addr == NULL)
 		return;
 
+	lock_release(rtld_bind_lock, lockstate);
 	for (index = 0; index < obj_main->preinit_array_num; index++) {
 		if (preinit_addr[index] != 0 && preinit_addr[index] != 1) {
 			dbg("calling preinit function for %s at %p",
@@ -3140,6 +3141,7 @@ preinit_main(void)
 			call_init_pointer(obj_main, preinit_addr[index]);
 		}
 	}
+	wlock_acquire(rtld_bind_lock, lockstate);
 }
 
 /*