summaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-10-27 21:39:59 +0000
committerJakub Jelinek <jakub@redhat.com>2004-10-27 21:39:59 +0000
commit0b5cfa4e0b7c9dc2cd81635307613c86c0f5e200 (patch)
treed9bf37b1a193cb3a52c598349d33c61c00a6aeca /elf
parentaa85b49673c934c0eeeec9e6e302f94fa1b165ab (diff)
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile5
-rw-r--r--elf/dl-fini.c127
-rw-r--r--elf/dl-open.c6
-rw-r--r--elf/tst-dlmopen1mod.c21
-rw-r--r--elf/tst-dlmopen3.c23
5 files changed, 115 insertions, 67 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 0bec4abbb7..028be25b2d 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -154,7 +154,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \
$(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
- tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2
+ tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@@ -770,3 +770,6 @@ $(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so
$(objpfx)tst-dlmopen2: $(libdl)
$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so
+
+$(objpfx)tst-dlmopen3: $(libdl)
+$(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 33036b5cbd..f43f4a00ed 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -42,23 +42,18 @@ _dl_fini (void)
using `dlopen' there are possibly several other modules with its
dependencies to be taken into account. Therefore we have to start
determining the order of the modules once again from the beginning. */
- unsigned int i;
- unsigned int nloaded;
- struct link_map *l;
struct link_map **maps = NULL;
size_t maps_size = 0;
- /* We First run the destructors of the main namespaces, then the
- other ones. The order should not matter since the namespace
- content is supposed to be independent. But we can have auditing
- code in a auxiliaty namespace and we want it to monitor the
- destructors. */
- for (Lmid_t cnt = 0; cnt < DL_NNS; ++cnt)
+ /* We run the destructors of the main namespaces last. As for the
+ other namespaces, we pick run the destructors in them in reverse
+ order of the namespace ID. */
+ for (Lmid_t cnt = DL_NNS - 1; cnt >= 0; --cnt)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
- nloaded = GL(dl_ns)[cnt]._ns_nloaded;
+ unsigned int nloaded = GL(dl_ns)[cnt]._ns_nloaded;
/* XXX Could it be (in static binaries) that there is no object
loaded? */
@@ -79,20 +74,20 @@ _dl_fini (void)
nloaded * sizeof (struct link_map *));
}
+ unsigned int i;
+ struct link_map *l;
for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next)
- {
- assert (i < nloaded);
+ /* Do not handle ld.so in secondary namespaces. */
+ if (l == l->l_real)
+ {
+ assert (i < nloaded);
- /* Do not handle ld.so in secondary namespaces. */
- if (l == l->l_real)
- {
- maps[i++] = l;
+ maps[i++] = l;
- /* Bump l_opencount of all objects so that they are not
- dlclose()ed from underneath us. */
- ++l->l_opencount;
- }
- }
+ /* Bump l_opencount of all objects so that they are not
+ dlclose()ed from underneath us. */
+ ++l->l_opencount;
+ }
assert (cnt != LM_ID_BASE || i == nloaded);
assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1);
unsigned int nmaps = i;
@@ -105,46 +100,23 @@ _dl_fini (void)
/* The main executable always comes first. */
l = l->l_next;
for (; l != NULL; l = l->l_next)
- {
- unsigned int j;
- unsigned int k;
-
- /* Find the place in the 'maps' array. */
- for (j = 1; maps[j] != l; ++j)
- ;
-
- /* Find all object for which the current one is a dependency and
- move the found object (if necessary) in front. */
- for (k = j + 1; k < nmaps; ++k)
- {
- struct link_map **runp = maps[k]->l_initfini;
- if (runp != NULL)
- {
- while (*runp != NULL)
- if (*runp == l)
- {
- struct link_map *here = maps[k];
-
- /* Move it now. */
- memmove (&maps[j] + 1,
- &maps[j],
- (k - j) * sizeof (struct link_map *));
- maps[j++] = here;
-
- break;
- }
- else
- ++runp;
- }
-
- if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
- {
- unsigned int m = maps[k]->l_reldepsact;
- struct link_map **relmaps = maps[k]->l_reldeps;
-
- while (m-- > 0)
- {
- if (relmaps[m] == l)
+ /* Do not handle ld.so in secondary namespaces. */
+ if (l == l->l_real)
+ {
+ /* Find the place in the 'maps' array. */
+ unsigned int j;
+ for (j = cnt == LM_ID_BASE ? 1 : 0; maps[j] != l; ++j)
+ assert (j < nmaps);
+
+ /* Find all object for which the current one is a dependency
+ and move the found object (if necessary) in front. */
+ for (unsigned int k = j + 1; k < nmaps; ++k)
+ {
+ struct link_map **runp = maps[k]->l_initfini;
+ if (runp != NULL)
+ {
+ while (*runp != NULL)
+ if (*runp == l)
{
struct link_map *here = maps[k];
@@ -152,14 +124,37 @@ _dl_fini (void)
memmove (&maps[j] + 1,
&maps[j],
(k - j) * sizeof (struct link_map *));
- maps[j] = here;
+ maps[j++] = here;
break;
}
- }
- }
- }
- }
+ else
+ ++runp;
+ }
+
+ if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
+ {
+ unsigned int m = maps[k]->l_reldepsact;
+ struct link_map **relmaps = maps[k]->l_reldeps;
+
+ while (m-- > 0)
+ {
+ if (relmaps[m] == l)
+ {
+ struct link_map *here = maps[k];
+
+ /* Move it now. */
+ memmove (&maps[j] + 1,
+ &maps[j],
+ (k - j) * sizeof (struct link_map *));
+ maps[j] = here;
+
+ break;
+ }
+ }
+ }
+ }
+ }
}
/* We do not rely on the linked list of loaded object anymore from
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 2ab1e307a4..294a523aac 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -570,6 +570,12 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid)
no more namespaces available for dlmopen()"));
}
}
+ /* Never allow loading a DSO in a namespace which is empty. Such
+ direct placements is only causing problems. */
+ else if (nsid != LM_ID_BASE && nsid != __LM_ID_CALLER
+ && GL(dl_ns)[nsid]._ns_nloaded == 0)
+ GLRO(dl_signal_error) (EINVAL, file, NULL,
+ N_("invalid target namespace in dlmopen()"));
args.file = file;
args.mode = mode;
diff --git a/elf/tst-dlmopen1mod.c b/elf/tst-dlmopen1mod.c
index 40a4c8fa44..142488098a 100644
--- a/elf/tst-dlmopen1mod.c
+++ b/elf/tst-dlmopen1mod.c
@@ -3,6 +3,16 @@
#include <gnu/lib-names.h>
+static int cnt;
+
+static void
+__attribute ((constructor))
+constr (void)
+{
+ ++cnt;
+}
+
+
int
foo (Lmid_t ns2)
{
@@ -34,5 +44,16 @@ foo (Lmid_t ns2)
return 1;
}
+ if (cnt == 0)
+ {
+ puts ("constructor did not run");
+ return 1;
+ }
+ else if (cnt != 1)
+ {
+ puts ("constructor did not run exactly once");
+ return 1;
+ }
+
return 0;
}
diff --git a/elf/tst-dlmopen3.c b/elf/tst-dlmopen3.c
new file mode 100644
index 0000000000..da951ca806
--- /dev/null
+++ b/elf/tst-dlmopen3.c
@@ -0,0 +1,23 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <gnu/lib-names.h>
+
+
+static int
+do_test (void)
+{
+ void *h = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ printf ("cannot get handle for %s: %s\n",
+ "tst-dlmopen1mod.so", dlerror ());
+ return 1;
+ }
+
+ /* Do not unload. */
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"