the global variable, dl_loaded, must be accessed on the exclusive conditions

Shunichi Sagawa s-sagawa at jp.fujitsu.com
Fri Feb 20 11:56:29 UTC 2004


Hi,

In glibc-2.3.2, I think that _dl_addr() function should
access the global variable, dl_loaded, with a lock.
(File name elf/dl-addr.c)

_dl_addr() accesses the global variable dl_loaded.
This variable is also accessed by dlopen() and dlclose().
dlopen() and dlclose() have a lock GL(dl_loaded) to protect it
for multithreaded programs, but _dl_addr() has none.

3 functions shown below have the same problem.

  __dlvsym() : File name dlfcn/dlvsym.c
  dlsym()    : File name dlfcn/dlsym.c
  _dl_fini() : FIle name elf/dl-fini.c



----start----
diff -Nur glibc-2.3.2.org/dlfcn/dlsym.c glibc-2.3.2/dlfcn/dlsym.c
--- glibc-2.3.2.org/dlfcn/dlsym.c	2001-07-08 04:20:52.000000000 +0900
+++ glibc-2.3.2/dlfcn/dlsym.c	2004-02-20 15:41:38.000000000 +0900
@@ -44,9 +44,13 @@
 dlsym (void *handle, const char *name)
 {
   struct dlsym_args args;
+  void *funchandle;
   args.who = RETURN_ADDRESS (0);
   args.handle = handle;
   args.name = name;
 
-  return (_dlerror_run (dlsym_doit, &args) ? NULL : args.sym);
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  funchandle = (_dlerror_run (dlsym_doit, &args) ? NULL : args.sym);
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+  return funchandle;
 }
diff -Nur glibc-2.3.2.org/dlfcn/dlvsym.c glibc-2.3.2/dlfcn/dlvsym.c
--- glibc-2.3.2.org/dlfcn/dlvsym.c	2001-07-08 04:20:52.000000000 +0900
+++ glibc-2.3.2/dlfcn/dlvsym.c	2004-02-20 15:42:55.000000000 +0900
@@ -45,12 +45,16 @@
 __dlvsym (void *handle, const char *name, const char *version_str)
 {
   struct dlvsym_args args;
+  void *funchandle;
 
   args.handle = handle;
   args.name = name;
   args.who = RETURN_ADDRESS (0);
   args.version = version_str;
 
-  return (_dlerror_run (dlvsym_doit, &args) ? NULL : args.sym);
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  funchandle = (_dlerror_run (dlvsym_doit, &args) ? NULL : args.sym);
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+  return funchandle;
 }
 weak_alias (__dlvsym, dlvsym)
diff -Nur glibc-2.3.2.org/elf/dl-addr.c glibc-2.3.2/elf/dl-addr.c
--- glibc-2.3.2.org/elf/dl-addr.c	2002-09-28 12:35:22.000000000 +0900
+++ glibc-2.3.2/elf/dl-addr.c	2004-02-20 15:44:30.000000000 +0900
@@ -32,6 +32,7 @@
   const char *strtab;
   ElfW(Word) strtabsize;
 
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
   /* Find the highest-addressed object that ADDRESS is not below.  */
   match = NULL;
   for (l = GL(dl_loaded); l; l = l->l_next)
@@ -55,8 +56,10 @@
 	break;
       }
 
-  if (match == NULL)
+  if (match == NULL) {
+    __rtld_lock_unlock_recursive (GL(dl_load_lock));
     return 0;
+  }
 
   /* Now we know what object the address lies in.  */
   info->dli_fname = match->l_name;
@@ -106,6 +109,7 @@
       info->dli_saddr = NULL;
     }
 
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
   return 1;
 }
 libc_hidden_def (_dl_addr)
diff -Nur glibc-2.3.2.org/elf/dl-fini.c glibc-2.3.2/elf/dl-fini.c
--- glibc-2.3.2.org/elf/dl-fini.c	2002-11-09 04:35:00.000000000 +0900
+++ glibc-2.3.2/elf/dl-fini.c	2004-02-20 15:45:27.000000000 +0900
@@ -49,6 +49,7 @@
   /* XXX Could it be (in static binaries) that there is no object loaded?  */
   assert (GL(dl_nloaded) > 0);
 
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
   /* Now we can allocate an array to hold all the pointers and copy
      the pointers in.  */
   maps = (struct link_map **) alloca (GL(dl_nloaded)
@@ -182,4 +183,5 @@
 final number of relocations from cache: %lu\n",
 				GL(dl_num_cache_relocations));
     }
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 }
----end----


Best Regards,
Shunichi Sagawa





More information about the Phil-list mailing list