summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2008-10-10 00:16:32 +0000
committerkan <kan@FreeBSD.org>2008-10-10 00:16:32 +0000
commitd53cb6ffcf6fddc63c399fb2ea4620e682597b38 (patch)
tree96fb448f8fe2d62582809928c6e81ebd28b02202 /libexec
parentb4da579f7f8907132cf9121a6ed3f46e54c2d528 (diff)
downloadFreeBSD-src-d53cb6ffcf6fddc63c399fb2ea4620e682597b38.zip
FreeBSD-src-d53cb6ffcf6fddc63c399fb2ea4620e682597b38.tar.gz
Allow strong symbols to override weak ones for lookups done through
dlsym with RTLD_NEXT/RTLD_SELF handles. Allow symbols from ld-elf.so to be located this way too. Based on report and original patch from sobomax@.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/rtld.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 7e0f8b1..144ea6c 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1925,7 +1925,7 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve,
{
DoneList donelist;
const Obj_Entry *obj, *defobj;
- const Elf_Sym *def;
+ const Elf_Sym *def, *symp;
unsigned long hash;
int lockstate;
@@ -1951,9 +1951,26 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve,
if (handle == RTLD_NEXT)
obj = obj->next;
for (; obj != NULL; obj = obj->next) {
- if ((def = symlook_obj(name, hash, obj, ve, flags)) != NULL) {
- defobj = obj;
- break;
+ if ((symp = symlook_obj(name, hash, obj, ve, flags)) != NULL) {
+ if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) {
+ def = symp;
+ defobj = obj;
+ if (ELF_ST_BIND(def->st_info) != STB_WEAK)
+ break;
+ }
+ }
+ }
+ /*
+ * Search the dynamic linker itself, and possibly resolve the
+ * symbol from there. This is how the application links to
+ * dynamic linker services such as dlopen. Only the values listed
+ * in the "exports" array can be resolved from the dynamic linker.
+ */
+ if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
+ symp = symlook_obj(name, hash, &obj_rtld, ve, flags);
+ if (symp != NULL && is_exported(symp)) {
+ def = symp;
+ defobj = &obj_rtld;
}
}
} else {
OpenPOWER on IntegriCloud