Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 May 2025 18:08:18 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: c66c0a8479e6 - main - rtld: do not call into ifunc resolvers with the bind lock write-locked
Message-ID:  <202505021808.542I8I3s061845@gitrepo.freebsd.org>

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

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

commit c66c0a8479e62f3e3e085252839cddace4d4bbf5
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-05-01 15:44:12 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-05-02 18:08:09 +0000

    rtld: do not call into ifunc resolvers with the bind lock write-locked
    
    If filter needs to be loader, we restart after the lock upgrade.  But
    possible binds in the resolver itself would try to recurse on the lock,
    which can be only done for the read locks.
    
    PR:     286502
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
---
 libexec/rtld-elf/rtld.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 3a9a3e800831..59d29888d93d 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1040,6 +1040,7 @@ _rtld_bind(Obj_Entry *obj, Elf_Size reloff)
 	Elf_Addr target;
 	RtldLockState lockstate;
 
+relock:
 	rlock_acquire(rtld_bind_lock, &lockstate);
 	if (sigsetjmp(lockstate.env, 0) != 0)
 		lock_upgrade(rtld_bind_lock, &lockstate);
@@ -1053,10 +1054,15 @@ _rtld_bind(Obj_Entry *obj, Elf_Size reloff)
 	    NULL, &lockstate);
 	if (def == NULL)
 		rtld_die();
-	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC)
+	if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+		if (lockstate_wlocked(&lockstate)) {
+			lock_release(rtld_bind_lock, &lockstate);
+			goto relock;
+		}
 		target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
-	else
+	} else {
 		target = (Elf_Addr)(defobj->relocbase + def->st_value);
+	}
 
 	dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", defobj->strtab + def->st_name,
 	    obj->path == NULL ? NULL : basename(obj->path), (void *)target,



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