summaryrefslogtreecommitdiff
path: root/ldso/libdl
diff options
context:
space:
mode:
authorLeonid Lisovskiy <lly.dev@gmail.com>2016-01-13 21:00:05 +0300
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2016-01-31 17:39:37 +0100
commit27f1b2c66c67e601dd619a1def70a8fd7ca5eeba (patch)
tree90a57981936937d51fa6dab56026f5f7c8bfcc80 /ldso/libdl
parent12a85731dc5fda3bc01ab19c82678b3bf122d794 (diff)
libdl: dlopen() mustn't forget RTLD_NODELETE flag
If RTLD_NODELETE is passed to dlopen() rather than set on shared library itself, flag propagation to rtld_flags is missed. Test-case taken from glibc. Signed-off-by: Leonid Lisovskiy <lly.dev@gmail.com> Signed-off-by: Waldemar Brodkorb <wbx@uclibc-ng.org>
Diffstat (limited to 'ldso/libdl')
-rw-r--r--ldso/libdl/libdl.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 2c4b06411..08619bc37 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -394,7 +394,7 @@ static void *do_dlopen(const char *libname, int flag, ElfW(Addr) from)
dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
memset(dyn_chain, 0, sizeof(struct dyn_elf));
dyn_chain->dyn = tpnt;
- tpnt->rtld_flags |= (flag & RTLD_GLOBAL);
+ tpnt->rtld_flags |= (flag & (RTLD_GLOBAL|RTLD_NODELETE));
dyn_chain->next_handle = _dl_handles;
_dl_handles = dyn_ptr = dyn_chain;
@@ -407,7 +407,7 @@ static void *do_dlopen(const char *libname, int flag, ElfW(Addr) from)
dyn_chain->init_fini.init_fini = handle->init_fini.init_fini;
dyn_chain->init_fini.nlist = handle->init_fini.nlist;
for (i = 0; i < dyn_chain->init_fini.nlist; i++)
- dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL);
+ dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & (RTLD_GLOBAL|RTLD_NODELETE));
dyn_chain->next = handle->next;
break;
}
@@ -439,7 +439,7 @@ static void *do_dlopen(const char *libname, int flag, ElfW(Addr) from)
if (!tpnt1)
goto oops;
- tpnt1->rtld_flags |= (flag & RTLD_GLOBAL);
+ tpnt1->rtld_flags |= (flag & (RTLD_GLOBAL|RTLD_NODELETE));
/* This list is for dlsym() and relocation */
dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));