Date: Thu, 16 Mar 2017 15:13:28 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r315416 - stable/11/libexec/rtld-elf Message-ID: <201703161513.v2GFDS39097457@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Thu Mar 16 15:13:28 2017 New Revision: 315416 URL: https://svnweb.freebsd.org/changeset/base/315416 Log: MFC r314973: Avoid bind lock recursion. Modified: stable/11/libexec/rtld-elf/rtld.c Directory Properties: stable/11/ (props changed) Modified: stable/11/libexec/rtld-elf/rtld.c ============================================================================== --- stable/11/libexec/rtld-elf/rtld.c Thu Mar 16 15:10:04 2017 (r315415) +++ stable/11/libexec/rtld-elf/rtld.c Thu Mar 16 15:13:28 2017 (r315416) @@ -77,6 +77,7 @@ static void digest_dynamic2(Obj_Entry *, static void digest_dynamic(Obj_Entry *, int); static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); +static int dlclose_locked(void *, RtldLockState *); static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, int mode, RtldLockState *lockstate); static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); @@ -98,7 +99,7 @@ static void initlist_add_objects(Obj_Ent static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); static void load_filtees(Obj_Entry *, int flags, RtldLockState *); -static void unload_filtees(Obj_Entry *); +static void unload_filtees(Obj_Entry *, RtldLockState *); static int load_needed_objects(Obj_Entry *, int); static int load_preload_objects(void); static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int); @@ -142,7 +143,7 @@ static int symlook_obj1_sysv(SymLook *, static int symlook_obj1_gnu(SymLook *, const Obj_Entry *); static void trace_loaded_objects(Obj_Entry *); static void unlink_object(Obj_Entry *); -static void unload_object(Obj_Entry *); +static void unload_object(Obj_Entry *, RtldLockState *lockstate); static void unref_dag(Obj_Entry *); static void ref_dag(Obj_Entry *); static char *origin_subst_one(Obj_Entry *, char *, const char *, @@ -2099,13 +2100,13 @@ initlist_add_objects(Obj_Entry *obj, Obj #endif static void -free_needed_filtees(Needed_Entry *n) +free_needed_filtees(Needed_Entry *n, RtldLockState *lockstate) { Needed_Entry *needed, *needed1; for (needed = n; needed != NULL; needed = needed->next) { if (needed->obj != NULL) { - dlclose(needed->obj); + dlclose_locked(needed->obj, lockstate); needed->obj = NULL; } } @@ -2116,14 +2117,14 @@ free_needed_filtees(Needed_Entry *n) } static void -unload_filtees(Obj_Entry *obj) +unload_filtees(Obj_Entry *obj, RtldLockState *lockstate) { - free_needed_filtees(obj->needed_filtees); - obj->needed_filtees = NULL; - free_needed_filtees(obj->needed_aux_filtees); - obj->needed_aux_filtees = NULL; - obj->filtees_loaded = false; + free_needed_filtees(obj->needed_filtees, lockstate); + obj->needed_filtees = NULL; + free_needed_filtees(obj->needed_aux_filtees, lockstate); + obj->needed_aux_filtees = NULL; + obj->filtees_loaded = false; } static void @@ -3010,15 +3011,23 @@ search_library_pathfds(const char *name, int dlclose(void *handle) { + RtldLockState lockstate; + int error; + + wlock_acquire(rtld_bind_lock, &lockstate); + error = dlclose_locked(handle, &lockstate); + lock_release(rtld_bind_lock, &lockstate); + return (error); +} + +static int +dlclose_locked(void *handle, RtldLockState *lockstate) +{ Obj_Entry *root; - RtldLockState lockstate; - wlock_acquire(rtld_bind_lock, &lockstate); root = dlcheck(handle); - if (root == NULL) { - lock_release(rtld_bind_lock, &lockstate); + if (root == NULL) return -1; - } LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, root->path); @@ -3030,19 +3039,18 @@ dlclose(void *handle) * The object will be no longer referenced, so we must unload it. * First, call the fini functions. */ - objlist_call_fini(&list_fini, root, &lockstate); + objlist_call_fini(&list_fini, root, lockstate); unref_dag(root); /* Finish cleaning up the newly-unreferenced objects. */ GDB_STATE(RT_DELETE,&root->linkmap); - unload_object(root); + unload_object(root, lockstate); GDB_STATE(RT_CONSISTENT,NULL); } else unref_dag(root); LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); - lock_release(rtld_bind_lock, &lockstate); return 0; } @@ -3118,13 +3126,13 @@ rtld_dlopen(const char *name, int fd, in } static void -dlopen_cleanup(Obj_Entry *obj) +dlopen_cleanup(Obj_Entry *obj, RtldLockState *lockstate) { obj->dl_refcount--; unref_dag(obj); if (obj->refcount == 0) - unload_object(obj); + unload_object(obj, lockstate); } static Obj_Entry * @@ -3173,7 +3181,7 @@ dlopen_object(const char *name, int fd, (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, lockstate) == -1) { - dlopen_cleanup(obj); + dlopen_cleanup(obj, lockstate); obj = NULL; } else if (lo_flags & RTLD_LO_EARLY) { /* @@ -3230,7 +3238,7 @@ dlopen_object(const char *name, int fd, (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, lockstate) == -1) { objlist_clear(&initlist); - dlopen_cleanup(obj); + dlopen_cleanup(obj, lockstate); if (lockstate == &mlockstate) lock_release(rtld_bind_lock, lockstate); return (NULL); @@ -4424,7 +4432,7 @@ trace_loaded_objects(Obj_Entry *obj) * reference count of 0. */ static void -unload_object(Obj_Entry *root) +unload_object(Obj_Entry *root, RtldLockState *lockstate) { Obj_Entry marker, *obj, *next; @@ -4456,11 +4464,11 @@ unload_object(Obj_Entry *root) if (next != NULL) { init_marker(&marker); TAILQ_INSERT_BEFORE(next, &marker, next); - unload_filtees(obj); + unload_filtees(obj, lockstate); next = TAILQ_NEXT(&marker, next); TAILQ_REMOVE(&obj_list, &marker, next); } else - unload_filtees(obj); + unload_filtees(obj, lockstate); } release_object(obj); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703161513.v2GFDS39097457>