aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@codesourcery.com>2013-06-28 16:20:26 +0100
committerMaciej W. Rozycki <macro@codesourcery.com>2013-06-28 16:22:20 +0100
commitf91f1c0fb89056995f1c9c6a06c361efdf5139e7 (patch)
tree67db98c499e8dbd72bc5b49e654706d375384c0f
parented0257f7d3378ec4a72e297f0dcba5159f2dd138 (diff)
downloadglibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.tar
glibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.tar.gz
glibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.tar.bz2
glibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.zip
[BZ #15022] Correct global-scope dlopen issues in static executables.
This change creates a link map in static executables to serve as the global search list for dlopen. It fixes a problem with the inability to access the global symbol object and a crash on an attempt to map a DSO into the global scope. Some code that has become dead after the addition of this link map is removed too and test cases are provided.
-rw-r--r--ChangeLog23
-rw-r--r--NEWS16
-rw-r--r--dlfcn/Makefile14
-rw-r--r--dlfcn/modstatic3.c31
-rw-r--r--dlfcn/tststatic3.c128
-rw-r--r--dlfcn/tststatic4.c363
-rw-r--r--elf/dl-load.c8
-rw-r--r--elf/dl-open.c18
-rw-r--r--elf/dl-support.c51
9 files changed, 610 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index 1012b2c2db..174b184c37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2013-06-28 Maciej W. Rozycki <macro@codesourcery.com>
+
+ [BZ #15022]
+ * elf/dl-support.c (_dl_main_map): New variable.
+ (_dl_ns): Use it to initialize [LM_ID_BASE] element.
+ (_dl_nns, _dl_load_adds): Set to 1.
+ (_dl_initial_searchlist): Refer to _dl_main_map.
+ (_dl_non_dynamic_init): Initialize _dl_main_map.l_origin.
+ * elf/dl-load.c (_dl_dst_substitute) [!SHARED]: Remove fallback
+ call to _dl_get_origin.
+ * elf/dl-open.c (dl_open_worker): Remove !SHARED special casing
+ around call_map.
+ (_dl_open) [!SHARED]: Remove code to initialize GL(dl_nns).
+ * dlfcn/modstatic3.c: New file.
+ * dlfcn/tststatic3.c: New file.
+ * dlfcn/tststatic4.c: New file.
+ * dlfcn/Makefile (tests): Add tststatic3 and tststatic4.
+ (tests-static): Likewise.
+ (modules-names): Add modstatic3.
+ (tststatic3-ENV, tststatic4-ENV): New variables.
+ ($(objpfx)tststatic3, $(objpfx)tststatic3.out): New dependencies.
+ ($(objpfx)tststatic4, $(objpfx)tststatic4.out): Likewise.
+
2013-06-26 Joseph Myers <joseph@codesourcery.com>
* configure.in (CC): Require GCC version 4.4 or later.
diff --git a/NEWS b/NEWS
index 60fbe73c65..e7fcf8158b 100644
--- a/NEWS
+++ b/NEWS
@@ -14,14 +14,14 @@ Version 2.18
14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496, 14582,
14686, 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952, 14964,
14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006, 15007,
- 15014, 15020, 15023, 15036, 15054, 15055, 15062, 15078, 15084, 15085,
- 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287,
- 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15339,
- 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394, 15395, 15405,
- 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429, 15431,
- 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490, 15492,
- 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583, 15618, 15627,
- 15631, 15654, 15655, 15666, 15667, 15674.
+ 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062, 15078, 15084,
+ 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283, 15285,
+ 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337,
+ 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394, 15395,
+ 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429,
+ 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490,
+ 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583, 15618,
+ 15627, 15631, 15654, 15655, 15666, 15667, 15674.
* CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
#15078).
diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 20e6f0294e..fca0951a5a 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -47,11 +47,13 @@ glreflib2.so-no-z-defs = yes
errmsg1mod.so-no-z-defs = yes
ifeq (yes,$(build-shared))
-tests += tststatic tststatic2
-tests-static += tststatic tststatic2
-modules-names += modstatic modstatic2
+tests += tststatic tststatic2 tststatic3 tststatic4
+tests-static += tststatic tststatic2 tststatic3 tststatic4
+modules-names += modstatic modstatic2 modstatic3
tststatic-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
tststatic2-ENV = $(tststatic-ENV)
+tststatic3-ENV = $(tststatic-ENV)
+tststatic4-ENV = $(tststatic-ENV)
endif
extra-test-objs += $(modules-names:=.os)
@@ -104,6 +106,12 @@ $(objpfx)tststatic2.out: $(objpfx)tststatic2 $(objpfx)modstatic.so \
$(objpfx)modstatic2.so: $(libdl)
+$(objpfx)tststatic3: $(objpfx)libdl.a
+$(objpfx)tststatic3.out: $(objpfx)tststatic3 $(objpfx)modstatic3.so
+
+$(objpfx)tststatic4: $(objpfx)libdl.a
+$(objpfx)tststatic4.out: $(objpfx)tststatic4 $(objpfx)modstatic3.so
+
$(objpfx)bug-dlopen1: $(libdl)
$(objpfx)bug-dlsym1: $(libdl) $(objpfx)bug-dlsym1-lib2.so
diff --git a/dlfcn/modstatic3.c b/dlfcn/modstatic3.c
new file mode 100644
index 0000000000..cd24986f23
--- /dev/null
+++ b/dlfcn/modstatic3.c
@@ -0,0 +1,31 @@
+/* DSO used for dlopen testing with a static executable.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+unsigned int foo;
+
+unsigned int
+getfoo (void)
+{
+ return foo;
+}
+
+void
+setfoo (unsigned int f)
+{
+ foo = f;
+}
diff --git a/dlfcn/tststatic3.c b/dlfcn/tststatic3.c
new file mode 100644
index 0000000000..8a3421e80c
--- /dev/null
+++ b/dlfcn/tststatic3.c
@@ -0,0 +1,128 @@
+/* Global-scope DSO mapping test with a static executable (BZ #15022).
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define MAGIC0 0
+#define MAGIC1 0x5500ffaa
+#define MAGIC2 0xaaff0055
+
+/* Mapping a DSO into the global scope used to crash in static
+ executables. Check that it succeeds and then that symbols from
+ the DSO can be accessed and operate as expected. */
+static int
+do_test (void)
+{
+ unsigned int (*getfoo) (void);
+ void (*setfoo) (unsigned int);
+ unsigned int *foop;
+ unsigned int foo;
+ void *handle;
+
+ /* Try to map a module into the global scope. */
+ handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (handle == NULL)
+ {
+ printf ("dlopen (modstatic3.so): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Get at its symbols. */
+ foop = dlsym (handle, "foo");
+ if (foop == NULL)
+ {
+ printf ("dlsym (foo): %s\n", dlerror ());
+ return 1;
+ }
+
+ getfoo = dlsym (handle, "getfoo");
+ if (getfoo == NULL)
+ {
+ printf ("dlsym (getfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ setfoo = dlsym (handle, "setfoo");
+ if (setfoo == NULL)
+ {
+ printf ("dlsym (setfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Make sure the view of the initial state is consistent. */
+ foo = *foop;
+ if (foo != MAGIC0)
+ {
+ printf ("*foop: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ foo = getfoo ();
+ if (foo != MAGIC0)
+ {
+ printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ /* Likewise with one change to its state. */
+ setfoo (MAGIC1);
+
+ foo = *foop;
+ if (foo != MAGIC1)
+ {
+ printf ("*foop: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ foo = getfoo ();
+ if (foo != MAGIC1)
+ {
+ printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ /* And with another. */
+ setfoo (MAGIC2);
+
+ foo = *foop;
+ if (foo != MAGIC2)
+ {
+ printf ("*foop: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ foo = getfoo ();
+ if (foo != MAGIC2)
+ {
+ printf ("getfoo: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ /* All done, clean up. */
+ getfoo = NULL;
+ setfoo = NULL;
+ foop = NULL;
+ dlclose (handle);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/dlfcn/tststatic4.c b/dlfcn/tststatic4.c
new file mode 100644
index 0000000000..f6078e07a6
--- /dev/null
+++ b/dlfcn/tststatic4.c
@@ -0,0 +1,363 @@
+/* Global object symbol access tests with a static executable (BZ #15022).
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define MAGIC0 0
+#define MAGIC1 0x5500ffaa
+#define MAGIC2 0xaaff0055
+#define MAGIC3 0xff55aa00
+
+/* Check the ability to access the global symbol object and then
+ global-scope symbol access consistency via different mappings
+ requested from a static executable. */
+static int
+do_test (void)
+{
+ unsigned int (*initial_getfoo) (void);
+ void (*initial_setfoo) (unsigned int);
+ unsigned int (*global_getfoo) (void);
+ void (*global_setfoo) (unsigned int);
+ unsigned int (*local_getfoo) (void);
+ void (*local_setfoo) (unsigned int);
+ unsigned int *initial_foop;
+ unsigned int *global_foop;
+ unsigned int *local_foop;
+ void *initial_handle;
+ void *global_handle;
+ void *local_handle;
+ unsigned int foo;
+
+ /* Try to map self. */
+ initial_handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL);
+ if (initial_handle == NULL)
+ {
+ printf ("dlopen [initial] (NULL): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Make sure symbol lookups fail gracefully. */
+ initial_foop = dlsym (initial_handle, "foo");
+ if (initial_foop != NULL)
+ {
+ printf ("dlsym [initial] (foo): got %p, expected NULL\n", initial_foop);
+ return 1;
+ }
+
+ initial_getfoo = dlsym (initial_handle, "getfoo");
+ if (initial_getfoo != NULL)
+ {
+ printf ("dlsym [initial] (getfoo): got %p, expected NULL\n",
+ initial_getfoo);
+ return 1;
+ }
+
+ initial_setfoo = dlsym (initial_handle, "setfoo");
+ if (initial_setfoo != NULL)
+ {
+ printf ("dlsym [initial] (setfoo): got %p, expected NULL\n",
+ initial_setfoo);
+ return 1;
+ }
+
+ /* Try to map a module into the global scope. */
+ global_handle = dlopen ("modstatic3.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (global_handle == NULL)
+ {
+ printf ("dlopen [global] (modstatic3.so): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Get at its symbols. */
+ global_foop = dlsym (global_handle, "foo");
+ if (global_foop == NULL)
+ {
+ printf ("dlsym [global] (foo): %s\n", dlerror ());
+ return 1;
+ }
+
+ global_getfoo = dlsym (global_handle, "getfoo");
+ if (global_getfoo == NULL)
+ {
+ printf ("dlsym [global] (getfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ global_setfoo = dlsym (global_handle, "setfoo");
+ if (global_setfoo == NULL)
+ {
+ printf ("dlsym [global] (setfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Try to map self again now. */
+ local_handle = dlopen (NULL, RTLD_LAZY | RTLD_LOCAL);
+ if (local_handle == NULL)
+ {
+ printf ("dlopen [local] (NULL): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Make sure we can get at the previously loaded module's symbols
+ via this handle too. */
+ local_foop = dlsym (local_handle, "foo");
+ if (local_foop == NULL)
+ {
+ printf ("dlsym [local] (foo): %s\n", dlerror ());
+ return 1;
+ }
+
+ local_getfoo = dlsym (local_handle, "getfoo");
+ if (local_getfoo == NULL)
+ {
+ printf ("dlsym [local] (getfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ local_setfoo = dlsym (local_handle, "setfoo");
+ if (local_setfoo == NULL)
+ {
+ printf ("dlsym [local] (setfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Make sure we can get at the previously loaded module's symbols
+ via a handle that was obtained before the module was loaded too. */
+ initial_foop = dlsym (initial_handle, "foo");
+ if (initial_foop == NULL)
+ {
+ printf ("dlsym [initial] (foo): %s\n", dlerror ());
+ return 1;
+ }
+
+ initial_getfoo = dlsym (initial_handle, "getfoo");
+ if (initial_getfoo == NULL)
+ {
+ printf ("dlsym [initial] (getfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ initial_setfoo = dlsym (initial_handle, "setfoo");
+ if (initial_setfoo == NULL)
+ {
+ printf ("dlsym [initial] (setfoo): %s\n", dlerror ());
+ return 1;
+ }
+
+ /* Make sure the view of the initial state is consistent. */
+ foo = *initial_foop;
+ if (foo != MAGIC0)
+ {
+ printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ foo = *global_foop;
+ if (foo != MAGIC0)
+ {
+ printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ foo = *local_foop;
+ if (foo != MAGIC0)
+ {
+ printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ foo = initial_getfoo ();
+ if (foo != MAGIC0)
+ {
+ printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ foo = global_getfoo ();
+ if (foo != MAGIC0)
+ {
+ printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ foo = local_getfoo ();
+ if (foo != MAGIC0)
+ {
+ printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC0);
+ return 1;
+ }
+
+ /* Likewise with a change to its state made through the first handle. */
+ initial_setfoo (MAGIC1);
+
+ foo = *initial_foop;
+ if (foo != MAGIC1)
+ {
+ printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ foo = *global_foop;
+ if (foo != MAGIC1)
+ {
+ printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ foo = *local_foop;
+ if (foo != MAGIC1)
+ {
+ printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ foo = initial_getfoo ();
+ if (foo != MAGIC1)
+ {
+ printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ foo = global_getfoo ();
+ if (foo != MAGIC1)
+ {
+ printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ foo = local_getfoo ();
+ if (foo != MAGIC1)
+ {
+ printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC1);
+ return 1;
+ }
+
+ /* Likewise with a change to its state made through the second handle. */
+ global_setfoo (MAGIC2);
+
+ foo = *initial_foop;
+ if (foo != MAGIC2)
+ {
+ printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ foo = *global_foop;
+ if (foo != MAGIC2)
+ {
+ printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ foo = *local_foop;
+ if (foo != MAGIC2)
+ {
+ printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ foo = initial_getfoo ();
+ if (foo != MAGIC2)
+ {
+ printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ foo = global_getfoo ();
+ if (foo != MAGIC2)
+ {
+ printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ foo = local_getfoo ();
+ if (foo != MAGIC2)
+ {
+ printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC2);
+ return 1;
+ }
+
+ /* Likewise with a change to its state made through the third handle. */
+ local_setfoo (MAGIC3);
+
+ foo = *initial_foop;
+ if (foo != MAGIC3)
+ {
+ printf ("*foop [initial]: got %#x, expected %#x\n", foo, MAGIC3);
+ return 1;
+ }
+
+ foo = *global_foop;
+ if (foo != MAGIC3)
+ {
+ printf ("*foop [global]: got %#x, expected %#x\n", foo, MAGIC3);
+ return 1;
+ }
+
+ foo = *local_foop;
+ if (foo != MAGIC3)
+ {
+ printf ("*foop [local]: got %#x, expected %#x\n", foo, MAGIC3);
+ return 1;
+ }
+
+ foo = initial_getfoo ();
+ if (foo != MAGIC3)
+ {
+ printf ("getfoo [initial]: got %#x, expected %#x\n", foo, MAGIC3);
+ return 1;
+ }
+
+ foo = global_getfoo ();
+ if (foo != MAGIC3)
+ {
+ printf ("getfoo [global]: got %#x, expected %#x\n", foo, MAGIC3);
+ return 1;
+ }
+
+ foo = local_getfoo ();
+ if (foo != MAGIC3)
+ {
+ printf ("getfoo [local]: got %#x, expected %#x\n", foo, MAGIC3);
+ return 1;
+ }
+
+ /* All done, clean up. */
+ initial_getfoo = NULL;
+ initial_setfoo = NULL;
+ initial_foop = NULL;
+
+ local_getfoo = NULL;
+ local_setfoo = NULL;
+ local_foop = NULL;
+ dlclose (local_handle);
+
+ global_getfoo = NULL;
+ global_setfoo = NULL;
+ global_foop = NULL;
+ dlclose (global_handle);
+
+ dlclose (initial_handle);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 757b6ec56b..d53ead4db3 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -342,13 +342,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
if ((len = is_dst (start, name, "ORIGIN", is_path,
INTUSE(__libc_enable_secure))) != 0)
{
-#ifndef SHARED
- if (l == NULL)
- repl = _dl_get_origin ();
- else
-#endif
- repl = l->l_origin;
-
+ repl = l->l_origin;
check_for_trusted = (INTUSE(__libc_enable_secure)
&& l->l_type == lt_executable);
}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 15221c8d57..7adf66b221 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -204,11 +204,9 @@ dl_open_worker (void *a)
{
const void *caller_dlopen = args->caller_dlopen;
-#ifdef SHARED
/* We have to find out from which object the caller is calling.
By default we assume this is the main application. */
call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-#endif
struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
@@ -216,15 +214,7 @@ dl_open_worker (void *a)
call_map = l;
if (args->nsid == __LM_ID_CALLER)
- {
-#ifndef SHARED
- /* In statically linked apps there might be no loaded object. */
- if (call_map == NULL)
- args->nsid = LM_ID_BASE;
- else
-#endif
- args->nsid = call_map->l_ns;
- }
+ args->nsid = call_map->l_ns;
}
assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT);
@@ -642,12 +632,6 @@ no more namespaces available for dlmopen()"));
|| GL(dl_ns)[nsid]._ns_loaded->l_auditing))
_dl_signal_error (EINVAL, file, NULL,
N_("invalid target namespace in dlmopen()"));
-#ifndef SHARED
- else if ((nsid == LM_ID_BASE || nsid == __LM_ID_CALLER)
- && GL(dl_ns)[LM_ID_BASE]._ns_loaded == NULL
- && GL(dl_nns) == 0)
- GL(dl_nns) = 1;
-#endif
struct dl_open_args args;
args.file = file;
diff --git a/elf/dl-support.c b/elf/dl-support.c
index b3ab9560ad..76752f33f3 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -70,17 +70,52 @@ const char *_dl_origin_path;
/* Nonzero if runtime lookup should not update the .got/.plt. */
int _dl_bind_not;
+/* A dummy link map for the executable, used by dlopen to access the global
+ scope. We don't export any symbols ourselves, so this can be minimal. */
+static struct link_map _dl_main_map =
+ {
+ .l_name = (char *) "",
+ .l_real = &_dl_main_map,
+ .l_ns = LM_ID_BASE,
+ .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 },
+ .l_searchlist =
+ {
+ .r_list = &(struct link_map *) { &_dl_main_map },
+ .r_nlist = 1,
+ },
+ .l_symbolic_searchlist = { .r_list = &(struct link_map *) { NULL } },
+ .l_type = lt_executable,
+ .l_scope_mem = { &_dl_main_map.l_searchlist },
+ .l_scope_max = (sizeof (_dl_main_map.l_scope_mem)
+ / sizeof (_dl_main_map.l_scope_mem[0])),
+ .l_scope = _dl_main_map.l_scope_mem,
+ .l_local_scope = { &_dl_main_map.l_searchlist },
+ .l_used = 1,
+ .l_tls_offset = NO_TLS_OFFSET,
+ .l_serial = 1,
+ };
+
/* Namespace information. */
-struct link_namespaces _dl_ns[DL_NNS];
-size_t _dl_nns;
+struct link_namespaces _dl_ns[DL_NNS] =
+ {
+ [LM_ID_BASE] =
+ {
+ ._ns_loaded = &_dl_main_map,
+ ._ns_nloaded = 1,
+ ._ns_main_searchlist = &_dl_main_map.l_searchlist,
+ }
+ };
+size_t _dl_nns = 1;
/* Incremented whenever something may have been added to dl_loaded. */
-unsigned long long _dl_load_adds;
+unsigned long long _dl_load_adds = 1;
-/* Fake scope. In dynamically linked binaries this is the scope of the
- main application but here we don't have something like this. So
- create a fake scope containing nothing. */
-struct r_scope_elem _dl_initial_searchlist;
+/* Fake scope of the main application. */
+struct r_scope_elem _dl_initial_searchlist =
+ {
+ .r_list = &(struct link_map *) { &_dl_main_map },
+ .r_nlist = 1,
+ };
#ifndef HAVE_INLINED_SYSCALLS
/* Nonzero during startup. */
@@ -265,6 +300,8 @@ void
internal_function
_dl_non_dynamic_init (void)
{
+ _dl_main_map.l_origin = _dl_get_origin ();
+
if (HP_TIMING_AVAIL)
HP_TIMING_NOW (_dl_cpuclock_offset);