On 19/04/2025 13:38, Konstantin Belousov wrote:
And there is the version with the recursive marking by deepbind:

I think that this patch would help with my case (haven't tested yet).
But I am not sure if it would be "correct".

First, as you have rightfully asked, it's not clear that deepbind should be recursive.

But even if it should be, there could be some edge case where the same library is a dependency of more than one dlopen-ed object where one dlopen uses RTLD_DEEPBIND and another doesn't. I am not sure how that case should be hadled.

BTW, I've been wondering how illumos avoids the problem even though they do not use any special dlopen flags. It turns out that they link almost all system shared libraries with -Bdirect option (which is Solaris/illumos specific).
It's somewhat similar to, but different from, -Bsymbolic.
https://docs.oracle.com/cd/E23824_01/html/819-0690/aehzq.html#scrolltoc
https://docs.oracle.com/cd/E36784_01/html/E36857/gejfe.html

I think that on FreeBSD we should use symbol visibility attributes or a symbol map to hide (make local) symbols that are not expected to be interposed or have a high chance to be interposed by accident.

IMO, yyparse should definitely get that treatment.

I think that approach would be better than magic rtld tricks.
Especially because the tricks do not work with the current rtld.
I'd rather make a change to libdtrace.so than to rtld.


diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 2346c6eae9f6..9767c8e7016c 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -3824,27 +3824,26 @@ dlopen_object(const char *name, int fd, Obj_Entry 
*refobj, int lo_flags,
                        if ((lo_flags & (RTLD_LO_EARLY | RTLD_LO_IGNSTLS)) ==
                                0 &&
                            obj->static_tls && !allocate_tls_offset(obj)) {
-                               _rtld_error("%s: No space available "
-                                           "for static Thread Local Storage",
+                               _rtld_error(
+                   "%s: No space available for static Thread Local Storage",
                                    obj->path);
                                result = -1;
                        }
                        if (result != -1)
                                result = load_needed_objects(obj,
-                                   lo_flags &
-                                       (RTLD_LO_DLOPEN | RTLD_LO_EARLY |
-                                           RTLD_LO_IGNSTLS | RTLD_LO_TRACE));
+                                   lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY |
+                                   RTLD_LO_IGNSTLS | RTLD_LO_TRACE |
+                                   RTLD_LO_DEEPBIND));
                        init_dag(obj);
                        ref_dag(obj);
                        if (result != -1)
                                result = rtld_verify_versions(&obj->dagmembers);
                        if (result != -1 && ld_tracing)
                                goto trace;
-                       if (result == -1 ||
-                           relocate_object_dag(obj,
-                               (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld,
-                               (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0,
-                               lockstate) == -1) {
+                       if (result == -1 || relocate_object_dag(obj,
+                           (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld,
+                           (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0,
+                           lockstate) == -1) {
                                dlopen_cleanup(obj, lockstate);
                                obj = NULL;
                        } else if (lo_flags & RTLD_LO_EARLY) {
@@ -4679,12 +4678,13 @@ symlook_default(SymLook *req, const Obj_Entry *refobj)
         */
        res = symlook_obj(&req1, refobj);
        if (res == 0 && (refobj->symbolic ||
-           ELF_ST_VISIBILITY(req1.sym_out->st_other) == STV_PROTECTED)) {
+           ELF_ST_VISIBILITY(req1.sym_out->st_other) == STV_PROTECTED ||
+           refobj->deepbind)) {
                req->sym_out = req1.sym_out;
                req->defobj_out = req1.defobj_out;
                assert(req->defobj_out != NULL);
        }
-       if (refobj->symbolic || req->defobj_out != NULL)
+       if (refobj->symbolic || req->defobj_out != NULL || refobj->deepbind)
                donelist_check(&donelist, refobj);
if (!refobj->deepbind)


--
Andriy Gapon

Reply via email to