>From 18008eb03acd59f6cbaa82c607f1969c70707e21 Mon Sep 17 00:00:00 2001 From: Markus Wichmann Date: Thu, 7 Feb 2019 18:17:25 +0100 Subject: [PATCH 9/9] Fix runtime dependency accounting in dlopen(). As Alexey Izbyshev pointed out, the library given as argument to dlopen() does not necessarily have to be the last in the chain. Nor do any of the dependencies. Therefore it is wrong to assume that walking the chain of libraries from any of them forward will only walk over dependencies of the freshly loaded library. I had to split the runtime and loadtime paths of load_deps() apart, or otherwise I would have had to allocate the deps array for the application at loadtime. And then I would have needed a resolution for allocation failure, which would have been a crash. --- ldso/dynlink.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 6ffeca85..66e6f18b 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1136,10 +1136,10 @@ static struct dso *load_library(const char *name, struct dso *needed_by) return p; } -static void load_deps(struct dso *p) -{ - size_t i, ndeps=0; - struct dso ***deps = &p->deps, **tmp, *dep; +static void load_deps_loadtime(struct dso *p) { + size_t i; + struct dso *dep; + p->deps = (struct dso**)&nodeps_dummy; for (; p; p=p->next) { for (i=0; p->dynv[i]; i+=2) { if (p->dynv[i] != DT_NEEDED) continue; @@ -1147,19 +1147,32 @@ static void load_deps(struct dso *p) if (!dep) { error("Error loading shared library %s: %m (needed by %s)", p->strings + p->dynv[i+1], p->name); - if (runtime) longjmp(*rtld_fail, 1); - continue; } - if (runtime) { - tmp = realloc(*deps, sizeof(*tmp)*(ndeps+2)); - if (!tmp) longjmp(*rtld_fail, 1); - tmp[ndeps++] = dep; - tmp[ndeps] = 0; - *deps = tmp; + } + } +} + +static void load_deps_runtime(struct dso *p) +{ + size_t i, ndeps=0, j=0; + struct dso ***deps = &p->deps, **tmp, *dep; + for (; p; p=(*deps)[j++]) { + for (i=0; p->dynv[i]; i+=2) { + if (p->dynv[i] != DT_NEEDED) continue; + dep = load_library(p->strings + p->dynv[i+1], p); + if (!dep) { + error("Error loading shared library %s: %m (needed by %s)", + p->strings + p->dynv[i+1], p->name); + longjmp(*rtld_fail, 1); } + tmp = realloc(*deps, sizeof(*tmp)*(ndeps+2)); + if (!tmp) longjmp(*rtld_fail, 1); + tmp[ndeps++] = dep; + tmp[ndeps] = 0; + *deps = tmp; } } - if (!*deps) *deps = (struct dso **)&nodeps_dummy; + if (!*deps) *deps = (struct dso**)&nodeps_dummy; } static void load_preload(char *s) @@ -1653,7 +1666,7 @@ _Noreturn void __dls3(size_t *sp) /* Load preload/needed libraries, add symbols to global namespace. */ if (env_preload) load_preload(env_preload); - load_deps(&app); + load_deps_loadtime(&app); for (struct dso *p=head; p; p=p->next) add_syms(p); @@ -1836,7 +1849,7 @@ void *dlopen(const char *file, int mode) /* First load handling */ int first_load = !p->deps; if (first_load) { - load_deps(p); + load_deps_runtime(p); if (!p->relocated && (mode & RTLD_LAZY)) { prepare_lazy(p); for (i=0; p->deps[i]; i++) -- 2.20.1