diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 6 | ||||
-rw-r--r-- | elf/dl-error.c | 4 | ||||
-rw-r--r-- | elf/dl-open.c | 7 | ||||
-rw-r--r-- | elf/dl-sym.c | 20 | ||||
-rw-r--r-- | elf/restest2.c | 33 | ||||
-rw-r--r-- | elf/rtld.c | 14 |
6 files changed, 69 insertions, 15 deletions
diff --git a/elf/Makefile b/elf/Makefile index 0668bb3251..8301683b80 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -101,7 +101,8 @@ tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ constload1 order $(tests-vis-$(have-protected)) noload filter unload \ reldep reldep2 reldep3 next $(tests-nodelete-$(have-z-nodelete)) \ $(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \ - neededtest3 neededtest4 unload2 lateglobal initfirst global + neededtest3 neededtest4 unload2 lateglobal initfirst global \ + restest2 test-srcs = tst-pathopt tests-vis-yes = vismain tests-nodelete-yes = nodelete @@ -303,6 +304,9 @@ $(objpfx)neededtest4.out: $(objpfx)neededobj5.so $(objpfx)neededobj6.so $(objpfx)restest1: $(objpfx)testobj1.so $(objpfx)testobj1_1.so $(libdl) LDFLAGS-restest1 = -rdynamic +$(objpfx)restest2: $(libdl) +LDFLAGS-restest2 = -rdynamic + $(objpfx)restest1.out: $(test-modules) preloadtest-preloads = testobj1 testobj2 testobj3 testobj4 testobj5 diff --git a/elf/dl-error.c b/elf/dl-error.c index 1cd4cc3852..440fea35d7 100644 --- a/elf/dl-error.c +++ b/elf/dl-error.c @@ -71,6 +71,8 @@ _dl_signal_error (int errcode, const char *objname, const char *errstring) errstring = N_("DYNAMIC LINKER BUG!!!"); lcatch = tsd_getspecific (); + if (objname == NULL) + objname = ""; if (lcatch != NULL) { /* We are inside _dl_catch_error. Return to it. We have to @@ -100,7 +102,7 @@ _dl_signal_error (int errcode, const char *objname, const char *errstring) _dl_fatal_printf ("\ %s: error while loading shared libraries: %s%s%s%s%s\n", _dl_argv[0] ?: "<program name unknown>", - objname ?: "", objname && *objname ? ": " : "", + objname, *objname ? ": " : "", errstring, errcode ? ": " : "", (errcode ? __strerror_r (errcode, buffer, sizeof buffer) diff --git a/elf/dl-open.c b/elf/dl-open.c index 440da67d0d..43daf60d58 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -188,13 +188,10 @@ dl_open_worker (void *a) _dl_signal_error (0, "dlopen", N_("DST not allowed in SUID/SGID programs")); - /* We have to find out from which object the caller is calling. - Find the highest-addressed object that ADDRESS is not below. */ + /* We have to find out from which object the caller is calling. */ call_map = NULL; for (l = _dl_loaded; l; l = l->l_next) - if (l->l_addr != 0 /* Make sure we do not currently set this map up - in this moment. */ - && caller >= (const void *) l->l_map_start + if (caller >= (const void *) l->l_map_start && caller < (const void *) l->l_map_end) { /* There must be exactly one DSO for the range of the virtual diff --git a/elf/dl-sym.c b/elf/dl-sym.c index ffc36bc8f9..9ca2af81e4 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -41,7 +41,7 @@ _dl_sym (void *handle, const char *name, void *who) /* Find the highest-addressed object that CALLER is not below. */ for (l = _dl_loaded; l != NULL; l = l->l_next) - if (l->l_addr != 0 && caller >= l->l_map_start && caller < l->l_map_end) + if (caller >= l->l_map_start && caller < l->l_map_end) { /* There must be exactly one DSO for the range of the virtual memory. Otherwise something is really broken. */ @@ -65,8 +65,13 @@ _dl_sym (void *handle, const char *name, void *who) else { if (__builtin_expect (match == _dl_loaded, 0)) - _dl_signal_error (0, NULL, N_("\ + { + if (! _dl_loaded + || caller < _dl_loaded->l_map_start + || caller >= _dl_loaded->l_map_end) + _dl_signal_error (0, NULL, N_("\ RTLD_NEXT used in code not dynamically loaded")); + } l = match; while (l->l_loader != NULL) @@ -107,7 +112,7 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who) /* Find the highest-addressed object that CALLER is not below. */ for (l = _dl_loaded; l != NULL; l = l->l_next) - if (l->l_addr != 0 && caller >= l->l_map_start && caller < l->l_map_end) + if (caller >= l->l_map_start && caller < l->l_map_end) { /* There must be exactly one DSO for the range of the virtual memory. Otherwise something is really broken. */ @@ -121,9 +126,14 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who) &vers, 0, 0); else if (handle == RTLD_NEXT) { - if (match == _dl_loaded) - _dl_signal_error (0, NULL, N_("\ + if (__builtin_expect (match == _dl_loaded, 0)) + { + if (! _dl_loaded + || caller < _dl_loaded->l_map_start + || caller >= _dl_loaded->l_map_end) + _dl_signal_error (0, NULL, N_("\ RTLD_NEXT used in code not dynamically loaded")); + } l = match; while (l->l_loader != NULL) diff --git a/elf/restest2.c b/elf/restest2.c new file mode 100644 index 0000000000..f959f030a0 --- /dev/null +++ b/elf/restest2.c @@ -0,0 +1,33 @@ +#include <sys/types.h> +#include <dlfcn.h> +#include <error.h> +#include <mcheck.h> +#include <stdlib.h> +#include <unistd.h> + +pid_t pid, pid2; + +pid_t getpid(void) +{ + pid_t (*f)(void); + f = (pid_t (*)(void)) dlsym (RTLD_NEXT, "getpid"); + if (f == NULL) + error (EXIT_FAILURE, 0, "dlsym (RTLD_NEXT, \"getpid\"): %s", dlerror ()); + return (pid2 = f()) + 26; +} + +int +main (void) +{ + pid_t (*f)(void); + + mtrace (); + + f = (pid_t (*)(void)) dlsym (RTLD_DEFAULT, "getpid"); + if (f == NULL) + error (EXIT_FAILURE, 0, "dlsym (RTLD_DEFAULT, \"getpid\"): %s", dlerror ()); + pid = f(); + if (pid != pid2 + 26) + error (EXIT_FAILURE, 0, "main getpid() not called"); + return 0; +} diff --git a/elf/rtld.c b/elf/rtld.c index 8b2ca2984e..ee48af3b3b 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -542,8 +542,7 @@ of this helper program; chances are you did not intend to run this program.\n\ information for the program. */ } - /* It is not safe to load stuff after the main program. */ - _dl_loaded->l_map_end = ~0; + _dl_loaded->l_map_end = 0; /* Perhaps the executable has no PT_LOAD header entries at all. */ _dl_loaded->l_map_start = ~0; @@ -591,15 +590,24 @@ of this helper program; chances are you did not intend to run this program.\n\ has_interp = 1; break; case PT_LOAD: - /* Remember where the main program starts in memory. */ { ElfW(Addr) mapstart; + ElfW(Addr) allocend; + + /* Remember where the main program starts in memory. */ mapstart = _dl_loaded->l_addr + (ph->p_vaddr & ~(ph->p_align - 1)); if (_dl_loaded->l_map_start > mapstart) _dl_loaded->l_map_start = mapstart; + + /* Also where it ends. */ + allocend = _dl_loaded->l_addr + ph->p_vaddr + ph->p_memsz; + if (_dl_loaded->l_map_end < allocend) + _dl_loaded->l_map_end = allocend; } break; } + if (! _dl_loaded->l_map_end) + _dl_loaded->l_map_end = ~0; if (! _dl_rtld_map.l_libname && _dl_rtld_map.l_name) { /* We were invoked directly, so the program might not have a |