From e612d094b1d27e1d61940e58d8aaeb249c54e768 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 3 Mar 2019 12:12:59 -0500 Subject: avoid malloc of deps array for programs with no external deps traditionally, we've provided a guarantee that dynamic-linked applications with no external dependencies (nothing but libc) and no thread-local storage have no failure paths before the entry point. normally, thanks to reclaim_gaps, such a malloc will not require a syscall anyway, but if segment alignment is unlucky, it might. use a builtin array for this common special case. --- ldso/dynlink.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'ldso') diff --git a/ldso/dynlink.c b/ldso/dynlink.c index a2f059cb..255ace2d 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -133,6 +133,7 @@ static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN; static size_t static_tls_cnt; static pthread_mutex_t init_fini_lock; static pthread_cond_t ctor_cond; +static struct dso *builtin_deps[2]; static struct dso **main_ctor_queue; static struct fdpic_loadmap *app_loadmap; static struct fdpic_dummy_loadmap app_dummy_loadmap; @@ -1152,6 +1153,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by) static void load_direct_deps(struct dso *p) { size_t i, cnt=0; + if (p->deps) return; /* For head, all preloads are direct pseudo-dependencies. * Count and include them now to avoid realloc later. */ @@ -1159,7 +1161,10 @@ static void load_direct_deps(struct dso *p) cnt++; for (i=0; p->dynv[i]; i+=2) if (p->dynv[i] == DT_NEEDED) cnt++; - p->deps = calloc(cnt+1, sizeof *p->deps); + /* Use builtin buffer for apps with no external deps, to + * preserve property of no runtime failure paths. */ + p->deps = (p==head && cnt<2) ? builtin_deps : + calloc(cnt+1, sizeof *p->deps); if (!p->deps) { error("Error loading dependencies for %s", p->name); if (runtime) longjmp(*rtld_fail, 1); @@ -1195,8 +1200,10 @@ static void extend_bfs_deps(struct dso *p) 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; + * program entry and malloc has been replaced, or if it's + * the builtin non-allocated trivial main program deps array. */ + int no_realloc = (__malloc_replaced && !p->runtime_loaded) + || p->deps == builtin_deps; if (p->bfs_built) return; ndeps_all = p->ndeps_direct; -- cgit v1.2.1