svn commit: r214777 - head/libexec/rtld-elf

Konstantin Belousov kib at FreeBSD.org
Thu Nov 4 09:29:00 UTC 2010


Author: kib
Date: Thu Nov  4 09:29:00 2010
New Revision: 214777
URL: http://svn.freebsd.org/changeset/base/214777

Log:
  In r214728, if dlopen() is called for the object that has been already
  loaded as a dependency and marked -z nodlopen, object' DAG is already
  initialized by load_needed_objects(). Due to this, the init_dag() call
  from dlopen() does not increment refcount for the object [1].
  
  Change init_dag() to not increment DAG refcount. Require explicit calls
  to ref_dag() to increment, and assert that ref_dag() and unref_dag()
  are called for root that has dag initialized. To fix the noted issue,
  unconditionally call both init_dag() and ref_dag() in dlopen() for the
  case when the object was already loaded, making it similar to the case
  of newly loaded object.
  
  Noted by:	jh [1]
  Reviewed by:	jh, kan
  MFC after:	6 days

Modified:
  head/libexec/rtld-elf/rtld.c

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Thu Nov  4 09:19:14 2010	(r214776)
+++ head/libexec/rtld-elf/rtld.c	Thu Nov  4 09:29:00 2010	(r214777)
@@ -1290,7 +1290,6 @@ init_dag1(Obj_Entry *root, Obj_Entry *ob
     if (donelist_check(dlp, obj))
 	return;
 
-    obj->refcount++;
     objlist_push_tail(&obj->dldags, root);
     objlist_push_tail(&root->dagmembers, obj);
     for (needed = obj->needed;  needed != NULL;  needed = needed->next)
@@ -2031,6 +2030,7 @@ dlopen(const char *name, int mode)
 	    assert(*old_obj_tail == obj);
 	    result = load_needed_objects(obj, RTLD_LO_DLOPEN);
 	    init_dag(obj);
+	    ref_dag(obj);
 	    if (result != -1)
 		result = rtld_verify_versions(&obj->dagmembers);
 	    if (result != -1 && ld_tracing)
@@ -2054,10 +2054,8 @@ dlopen(const char *name, int mode)
 	     * already loaded as a dependency, initialize the dag
 	     * starting at it.
 	     */
-	    if (obj->dl_refcount == 1)
-		init_dag(obj);
-	    else
-		ref_dag(obj);
+	    init_dag(obj);
+	    ref_dag(obj);
 
 	    if (ld_tracing)
 		goto trace;
@@ -3085,6 +3083,7 @@ ref_dag(Obj_Entry *root)
 {
     Objlist_Entry *elm;
 
+    assert(root->dag_inited);
     STAILQ_FOREACH(elm, &root->dagmembers, link)
 	elm->obj->refcount++;
 }
@@ -3094,6 +3093,7 @@ unref_dag(Obj_Entry *root)
 {
     Objlist_Entry *elm;
 
+    assert(root->dag_inited);
     STAILQ_FOREACH(elm, &root->dagmembers, link)
 	elm->obj->refcount--;
 }


More information about the svn-src-head mailing list