summaryrefslogtreecommitdiff
path: root/ldso/dynlink.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-03-01 14:37:52 -0500
committerRich Felker <dalias@aerifal.cx>2019-03-02 17:29:11 -0500
commit0c5c8f5da6e36fe4ab704bee0cd981837859e23f (patch)
treea00d7d9ee1d24ba9c919559571dd1a7a8256cd69 /ldso/dynlink.c
parent403555690775f7c8806372644f543518e6664e3b (diff)
downloadmusl-0c5c8f5da6e36fe4ab704bee0cd981837859e23f.tar.gz
fix unsafety of new ldso dep tracking in presence of malloc replacement
commit 403555690775f7c8806372644f543518e6664e3b introduced runtime realloc of an array that may have been allocated before symbols were resolved outside of libc, which is invalid if the allocator has been replaced. track this condition and manually copy if needed.
Diffstat (limited to 'ldso/dynlink.c')
-rw-r--r--ldso/dynlink.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 34775b83..c230b833 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -73,6 +73,7 @@ struct dso {
char kernel_mapped;
char mark;
char bfs_built;
+ char runtime_loaded;
struct dso **deps, *needed_by;
size_t ndeps_direct;
char *rpath_orig, *rpath;
@@ -1107,6 +1108,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
p->ino = st.st_ino;
p->needed_by = needed_by;
p->name = p->buf;
+ p->runtime_loaded = runtime;
strcpy(p->name, pathname);
/* Add a shortname only if name arg was not an explicit pathname. */
if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
@@ -1180,6 +1182,10 @@ static void extend_bfs_deps(struct dso *p)
size_t i, j, cnt, ndeps_all;
struct dso **tmp;
+ /* Can't use realloc if the original p->deps was allocated at
+ * program entry and malloc has been replaced. */
+ int no_realloc = __malloc_replaced && !p->runtime_loaded;
+
if (p->bfs_built) return;
ndeps_all = p->ndeps_direct;
@@ -1195,12 +1201,18 @@ static void extend_bfs_deps(struct dso *p)
struct dso *dep = p->deps[i];
for (j=cnt=0; j<dep->ndeps_direct; j++)
if (!dep->deps[j]->mark) cnt++;
- tmp = realloc(p->deps, sizeof(*p->deps) * (ndeps_all+cnt+1));
+ tmp = no_realloc ?
+ malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) :
+ realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1));
if (!tmp) {
error("Error recording dependencies for %s", p->name);
if (runtime) longjmp(*rtld_fail, 1);
continue;
}
+ if (no_realloc) {
+ memcpy(tmp, p->deps, sizeof(*tmp) * (ndeps_all+1));
+ no_realloc = 0;
+ }
p->deps = tmp;
for (j=0; j<dep->ndeps_direct; j++) {
if (dep->deps[j]->mark) continue;