aboutsummaryrefslogtreecommitdiff
path: root/libexec/rtld-elf/rtld.c
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2016-12-22 17:41:32 +0000
committerMark Johnston <markj@FreeBSD.org>2016-12-22 17:41:32 +0000
commit510fe58c824384e0a8c1bad8d8866c92f83b2d25 (patch)
treec7c90b554d35b4c83d7ce5737b40c36f3a830000 /libexec/rtld-elf/rtld.c
parentc02741759fcfef1ad6a52ff515d33a7a8374b5c0 (diff)
downloadsrc-510fe58c824384e0a8c1bad8d8866c92f83b2d25.tar.gz
src-510fe58c824384e0a8c1bad8d8866c92f83b2d25.zip
rtld: Ensure that dlopen() cannot obtain a reference on a doomed object.
rtld drops the bind lock to call fini functions in an object prior to unmapping it. The new "doomed" state flag prevents the acquisition of new references for an object while the lock is dropped. Reviewed by: kib MFC after: 2 weeks Sponsored by: Dell EMC Isilon
Notes
Notes: svn path=/head/; revision=310421
Diffstat (limited to 'libexec/rtld-elf/rtld.c')
-rw-r--r--libexec/rtld-elf/rtld.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index cde79be9b6bd..10711da25bb1 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -2229,7 +2229,7 @@ load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags)
fd = -1;
if (name != NULL) {
TAILQ_FOREACH(obj, &obj_list, next) {
- if (obj->marker)
+ if (obj->marker || obj->doomed)
continue;
if (object_match_name(obj, name))
return (obj);
@@ -2276,7 +2276,7 @@ load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags)
return NULL;
}
TAILQ_FOREACH(obj, &obj_list, next) {
- if (obj->marker)
+ if (obj->marker || obj->doomed)
continue;
if (obj->ino == sb.st_ino && obj->dev == sb.st_dev)
break;
@@ -2418,6 +2418,9 @@ objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
assert(root == NULL || root->refcount == 1);
+ if (root != NULL)
+ root->doomed = true;
+
/*
* Preserve the current error message since a fini function might
* call into the dynamic linker and overwrite it.
@@ -2430,16 +2433,11 @@ objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
continue;
/* Remove object from fini list to prevent recursive invocation. */
STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
- /*
- * XXX: If a dlopen() call references an object while the
- * fini function is in progress, we might end up trying to
- * unload the referenced object in dlclose() or the object
- * won't be unloaded although its fini function has been
- * called.
- */
+ /* Ensure that new references cannot be acquired. */
+ elm->obj->doomed = true;
+
hold_object(elm->obj);
lock_release(rtld_bind_lock, lockstate);
-
/*
* It is legal to have both DT_FINI and DT_FINI_ARRAY defined.
* When this happens, DT_FINI_ARRAY is processed first.