git: 9daf6cd0f464 - main - RTLD_DEEPBIND: make lookup not just symbolic, but walk all refobj' DAGs

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 30 Nov 2023 19:35:07 UTC
The branch main has been updated by kib:

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

commit 9daf6cd0f46416d9c6eb0411ea6042cd42b8a9bc
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-11-29 18:30:59 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-11-30 19:34:36 +0000

    RTLD_DEEPBIND: make lookup not just symbolic, but walk all refobj' DAGs
    
    before starting the walk over the global list.  Effectively we visit
    needed objects first as well, instead of just the object itself.
    This seems to better match the semantic offered by the glibc flag.
    
    Reported by:    kevans
    PR:     275393
    Reviewed by:    kevans
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D42841
---
 libexec/rtld-elf/rtld.c | 8 ++++++--
 libexec/rtld-elf/rtld.h | 1 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 49de41f81583..2c4111cc457a 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -3755,7 +3755,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
 	if (!obj->init_done) {
 	    /* We loaded something new and have to init something. */
 	    if ((lo_flags & RTLD_LO_DEEPBIND) != 0)
-		obj->symbolic = true;
+		obj->deepbind = true;
 	    result = 0;
 	    if ((lo_flags & (RTLD_LO_EARLY | RTLD_LO_IGNSTLS)) == 0 &&
 	      obj->static_tls && !allocate_tls_offset(obj)) {
@@ -4581,7 +4581,8 @@ symlook_default(SymLook *req, const Obj_Entry *refobj)
     if (refobj->symbolic || req->defobj_out != NULL)
 	donelist_check(&donelist, refobj);
 
-    symlook_global(req, &donelist);
+    if (!refobj->deepbind)
+        symlook_global(req, &donelist);
 
     /* Search all dlopened DAGs containing the referencing object. */
     STAILQ_FOREACH(elm, &refobj->dldags, link) {
@@ -4597,6 +4598,9 @@ symlook_default(SymLook *req, const Obj_Entry *refobj)
 	}
     }
 
+    if (refobj->deepbind)
+        symlook_global(req, &donelist);
+
     /*
      * Search the dynamic linker itself, and possibly resolve the
      * symbol from there.  This is how the application links to
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index c7c17426b38a..e8b15095812b 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -240,6 +240,7 @@ typedef struct Struct_Obj_Entry {
     bool ver_checked : 1;	/* True if processed by rtld_verify_object_versions */
     bool textrel : 1;		/* True if there are relocations to text seg */
     bool symbolic : 1;		/* True if generated with "-Bsymbolic" */
+    bool deepbind : 1;		/* True if loaded with RTLD_DEEPBIND" */
     bool bind_now : 1;		/* True if all relocations should be made first */
     bool traced : 1;		/* Already printed in ldd trace output */
     bool jmpslots_done : 1;	/* Already have relocated the jump slots */