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