diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -263,6 +263,7 @@ bool on_fini_list: 1; /* Object is already on fini list. */ bool dag_inited : 1; /* Object has its DAG initialized. */ bool filtees_loaded : 1; /* Filtees loaded */ + bool filtees_loading : 1; /* In process of filtees loading */ bool irelative : 1; /* Object has R_MACHDEP_IRELATIVE relocs */ bool irelative_nonplt : 1; /* Object has R_MACHDEP_IRELATIVE non-plt relocs */ bool gnu_ifunc : 1; /* Object has references to STT_GNU_IFUNC */ diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -2582,13 +2582,14 @@ static void load_filtees(Obj_Entry *obj, int flags, RtldLockState *lockstate) { - - if (!obj->filtees_loaded) { + if (obj->filtees_loaded || obj->filtees_loading) + return; lock_restart_for_upgrade(lockstate); + obj->filtees_loading = true; load_filtee1(obj, obj->needed_filtees, flags, lockstate); load_filtee1(obj, obj->needed_aux_filtees, flags, lockstate); obj->filtees_loaded = true; - } + obj->filtees_loading = false; } static int @@ -4690,6 +4691,21 @@ return (ESRCH); } +static int +symlook_obj_load_filtees(SymLook *req, SymLook *req1, const Obj_Entry *obj, + Needed_Entry *needed) +{ + DoneList donelist; + int flags, res; + + flags = (req->flags & SYMLOOK_EARLY) != 0 ? RTLD_LO_EARLY : 0; + load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); + donelist_init(&donelist); + symlook_init_from_req(req1, req); + res = symlook_needed(req1, needed, &donelist); + return (res); +} + /* * Search the symbol table of a single shared object for a symbol of * the given name and version, if requested. Returns a pointer to the @@ -4702,9 +4718,8 @@ int symlook_obj(SymLook *req, const Obj_Entry *obj) { - DoneList donelist; SymLook req1; - int flags, res, mres; + int res, mres; /* * If there is at least one valid hash at this point, we prefer to @@ -4719,11 +4734,8 @@ if (mres == 0) { if (obj->needed_filtees != NULL) { - flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; - load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); - donelist_init(&donelist); - symlook_init_from_req(&req1, req); - res = symlook_needed(&req1, obj->needed_filtees, &donelist); + res = symlook_obj_load_filtees(req, &req1, obj, + obj->needed_filtees); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; @@ -4731,11 +4743,8 @@ return (res); } if (obj->needed_aux_filtees != NULL) { - flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; - load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); - donelist_init(&donelist); - symlook_init_from_req(&req1, req); - res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist); + res = symlook_obj_load_filtees(req, &req1, obj, + obj->needed_aux_filtees); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out;