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