From owner-svn-src-all@freebsd.org Thu Dec 22 17:41:33 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 82A00C8B2DF; Thu, 22 Dec 2016 17:41:33 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 45098D5C; Thu, 22 Dec 2016 17:41:33 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uBMHfWrh058580; Thu, 22 Dec 2016 17:41:32 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uBMHfWjt058578; Thu, 22 Dec 2016 17:41:32 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201612221741.uBMHfWjt058578@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Thu, 22 Dec 2016 17:41:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r310421 - head/libexec/rtld-elf X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Dec 2016 17:41:33 -0000 Author: markj Date: Thu Dec 22 17:41:32 2016 New Revision: 310421 URL: https://svnweb.freebsd.org/changeset/base/310421 Log: 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 Modified: head/libexec/rtld-elf/rtld.c head/libexec/rtld-elf/rtld.h Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Thu Dec 22 17:37:39 2016 (r310420) +++ head/libexec/rtld-elf/rtld.c Thu Dec 22 17:41:32 2016 (r310421) @@ -2229,7 +2229,7 @@ load_object(const char *name, int fd_u, 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, 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_Ent 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_Ent 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. Modified: head/libexec/rtld-elf/rtld.h ============================================================================== --- head/libexec/rtld-elf/rtld.h Thu Dec 22 17:37:39 2016 (r310420) +++ head/libexec/rtld-elf/rtld.h Thu Dec 22 17:41:32 2016 (r310421) @@ -267,6 +267,7 @@ typedef struct Struct_Obj_Entry { bool dlopened : 1; /* dlopen()-ed (vs. load statically) */ bool marker : 1; /* marker on the global obj list */ bool unholdfree : 1; /* unmap upon last unhold */ + bool doomed : 1; /* Object cannot be referenced */ struct link_map linkmap; /* For GDB and dlinfo() */ Objlist dldags; /* Object belongs to these dlopened DAGs (%) */