From owner-freebsd-bugs@FreeBSD.ORG Wed Nov 3 09:30:12 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7A3CC10656BF for ; Wed, 3 Nov 2010 09:30:12 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 4E0FC8FC16 for ; Wed, 3 Nov 2010 09:30:12 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id oA39UCCB069780 for ; Wed, 3 Nov 2010 09:30:12 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oA39UCr2069777; Wed, 3 Nov 2010 09:30:12 GMT (envelope-from gnats) Date: Wed, 3 Nov 2010 09:30:12 GMT Message-Id: <201011030930.oA39UCr2069777@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: dfilter@FreeBSD.ORG (dfilter service) Cc: Subject: Re: misc/151861: commit references a PR X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: dfilter service List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Nov 2010 09:30:12 -0000 The following reply was made to PR misc/151861; it has been noted by GNATS. From: dfilter@FreeBSD.ORG (dfilter service) To: bug-followup@FreeBSD.org Cc: Subject: Re: misc/151861: commit references a PR Date: Wed, 3 Nov 2010 09:23:17 +0000 (UTC) Author: kib Date: Wed Nov 3 09:23:08 2010 New Revision: 214728 URL: http://svn.freebsd.org/changeset/base/214728 Log: If dlopen() is called for the dso that has been already loaded as a dependency, then the dso never has its DAG initialized. Empty DAG makes ref_dag() call in dlopen() a nop, and the dso refcount is off by one. Initialize the DAG on the first dlopen() call, using a boolean flag to prevent double initialization. From the PR (edited): Assume we have a library liba.so, containing a function a(), and a library libb.so, containing function b(). liba.so needs functionality from libb.so, so liba.so links in libb.so. An application doesn't know about the relation between these libraries, but needs to call a() and b(). It dlopen()s liba.so and obtains a pointer to a(), then it dlopen()s libb.so and obtains a pointer to b(). As soon as the application doesn't need a() anymore, it dlclose()s liba.so. Expected result: the pointer to b() is still valid and can be called Actual result: the pointer to b() has become invalid, even though the application did not dlclose() the handle to libb.so. On calling b(), the application crashes with a segmentation fault. PR: misc/151861 Based on patch by: jh Reviewed by: kan Tested by: Arjan van Leeuwen MFC after: 1 week 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 Wed Nov 3 08:34:00 2010 (r214727) +++ head/libexec/rtld-elf/rtld.c Wed Nov 3 09:23:08 2010 (r214728) @@ -1275,8 +1275,11 @@ init_dag(Obj_Entry *root) { DoneList donelist; + if (root->dag_inited) + return; donelist_init(&donelist); init_dag1(root, root, &donelist); + root->dag_inited = true; } static void @@ -2045,8 +2048,16 @@ dlopen(const char *name, int mode) } } else { - /* Bump the reference counts for objects on this DAG. */ - ref_dag(obj); + /* + * Bump the reference counts for objects on this DAG. If + * this is the first dlopen() call for the object that was + * already loaded as a dependency, initialize the dag + * starting at it. + */ + if (obj->dl_refcount == 1) + init_dag(obj); + else + ref_dag(obj); if (ld_tracing) goto trace; Modified: head/libexec/rtld-elf/rtld.h ============================================================================== --- head/libexec/rtld-elf/rtld.h Wed Nov 3 08:34:00 2010 (r214727) +++ head/libexec/rtld-elf/rtld.h Wed Nov 3 09:23:08 2010 (r214728) @@ -222,6 +222,7 @@ typedef struct Struct_Obj_Entry { bool ref_nodel : 1; /* Refcount increased to prevent dlclose */ bool init_scanned: 1; /* Object is already on init list. */ bool on_fini_list: 1; /* Object is already on fini list. */ + bool dag_inited : 1; /* Object has its DAG initialized. */ struct link_map linkmap; /* For GDB and dlinfo() */ Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"