diff options
author | Timo Teräs <timo.teras@iki.fi> | 2017-03-21 15:17:26 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2017-03-21 15:27:08 +0200 |
commit | dd232808d24fb6cba3f06117f5e974effd3051c7 (patch) | |
tree | d956a5df2228b1710bd64648e8f05bda2d3d9d8f /main | |
parent | ebada60098b1cfc0d1f7a21bdd3e7ed27af2f873 (diff) | |
download | aports-dd232808d24fb6cba3f06117f5e974effd3051c7.tar.bz2 aports-dd232808d24fb6cba3f06117f5e974effd3051c7.tar.xz |
main/musl: cherry-pick ldso improvements and lazy relocation emulation
Diffstat (limited to 'main')
6 files changed, 601 insertions, 1 deletions
diff --git a/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch b/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch new file mode 100644 index 0000000000..03e1da813b --- /dev/null +++ b/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch @@ -0,0 +1,255 @@ +From 4ff234f6cba96403b5de6d29d48a59fd73252040 Mon Sep 17 00:00:00 2001 +From: Rich Felker <dalias@aerifal.cx> +Date: Sun, 12 Mar 2017 21:03:05 -0400 +Subject: [PATCH] rework ldso handling of global symbol table for consistency + +when loading libraries with dlopen, the caller can request that the +library's symbols become part of the global symbol table, or that they +only be used for resolving relocations in the loaded library and its +dependencies. in the latter case, a subsequent dlopen of the same +library can upgrade it to global status. + +previously, if a library was upgraded from local to global mode, its +symbols entered the symbol lookup search order at the point where the +library was originally loaded. this means that a new call to dlopen +could change the value of a symbol that already had a visible +definition, an inconsistency which applications could observe. + +POSIX is unclear whether this should happen or whether it's permitted +to happen, but the resolution of Austin Group issue #982 made it +formally unspecified. + +with this patch, a library whose mode is upgraded from local to global +enters the symbol lookup order at the point where it was made global, +so that symbol resolution before and after the upgrade are consistent. + +in order to implement this change, the per-dso global flag is replaced +with a separate set of linked-list pointers for participation in the +global symbol table. this permits the order of dso objects for symbol +resolution to differ from the order used for iteration of all loaded +libraries. it also improves performance of find_sym, by avoiding a +branch per iteration and skipping, and especially in the case where +many non-global libraries have been loaded, by allowing the loop to +skip over them entirely. logic for temporarily adding non-global +libraries to the symbol table for relocation purposes is also mildly +simplified. +--- + ldso/dynlink.c | 97 ++++++++++++++++++++++++++++++++-------------------------- + 1 file changed, 53 insertions(+), 44 deletions(-) + +diff --git a/ldso/dynlink.c b/ldso/dynlink.c +index d00827a3..0e394e0d 100644 +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -58,11 +58,11 @@ struct dso { + uint32_t *ghashtab; + int16_t *versym; + char *strings; ++ struct dso *syms_next; + unsigned char *map; + size_t map_len; + dev_t dev; + ino_t ino; +- signed char global; + char relocated; + char constructed; + char kernel_mapped; +@@ -113,7 +113,7 @@ static struct builtin_tls { + static size_t *saved_addends, *apply_addends_to; + + static struct dso ldso; +-static struct dso *head, *tail, *fini_head; ++static struct dso *head, *tail, *fini_head, *syms_tail; + static char *env_path, *sys_path; + static unsigned long long gencnt; + static int runtime; +@@ -261,9 +261,8 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def) + uint32_t h = 0, gh, gho, *ght; + size_t ghm = 0; + struct symdef def = {0}; +- for (; dso; dso=dso->next) { ++ for (; dso; dso=dso->syms_next) { + Sym *sym; +- if (!dso->global) continue; + if ((ght = dso->ghashtab)) { + if (!ghm) { + gh = gnu_hash(s); +@@ -329,7 +328,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + if (sym_index) { + sym = syms + sym_index; + name = strings + sym->st_name; +- ctx = type==REL_COPY ? head->next : head; ++ ctx = type==REL_COPY ? head->syms_next : head; + def = (sym->st_info&0xf) == STT_SECTION + ? (struct symdef){ .dso = dso, .sym = sym } + : find_sym(ctx, name, type==REL_PLT); +@@ -932,7 +931,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by) + if (!ldso.prev) { + tail->next = &ldso; + ldso.prev = tail; +- tail = ldso.next ? ldso.next : &ldso; ++ tail = &ldso; + } + return &ldso; + } +@@ -1113,9 +1112,24 @@ static void load_preload(char *s) + } + } + +-static void make_global(struct dso *p) ++static void add_syms(struct dso *p) + { +- for (; p; p=p->next) p->global = 1; ++ if (!p->syms_next && syms_tail != p) { ++ syms_tail->syms_next = p; ++ syms_tail = p; ++ } ++} ++ ++static void revert_syms(struct dso *old_tail) ++{ ++ struct dso *p, *next; ++ /* Chop off the tail of the list of dsos that participate in ++ * the global symbol table, reverting them to RTLD_LOCAL. */ ++ for (p=old_tail; p; p=next) { ++ next = p->syms_next; ++ p->syms_next = 0; ++ } ++ syms_tail = old_tail; + } + + static void do_mips_relocs(struct dso *p, size_t *got) +@@ -1344,7 +1358,6 @@ void __dls2(unsigned char *base, size_t *sp) + } + Ehdr *ehdr = (void *)ldso.base; + ldso.name = ldso.shortname = "libc.so"; +- ldso.global = 1; + ldso.phnum = ehdr->e_phnum; + ldso.phdr = laddr(&ldso, ehdr->e_phoff); + ldso.phentsize = ehdr->e_phentsize; +@@ -1532,7 +1545,6 @@ _Noreturn void __dls3(size_t *sp) + #endif + tls_align = MAXP2(tls_align, app.tls.align); + } +- app.global = 1; + decode_dyn(&app); + if (DL_FDPIC) { + makefuncdescs(&app); +@@ -1547,7 +1559,21 @@ _Noreturn void __dls3(size_t *sp) + argv[-3] = (void *)app.loadmap; + } + +- /* Attach to vdso, if provided by the kernel */ ++ /* Initial dso chain consists only of the app. */ ++ head = tail = syms_tail = &app; ++ ++ /* Donate unused parts of app and library mapping to malloc */ ++ reclaim_gaps(&app); ++ reclaim_gaps(&ldso); ++ ++ /* Load preload/needed libraries, add symbols to global namespace. */ ++ if (env_preload) load_preload(env_preload); ++ load_deps(&app); ++ for (struct dso *p=head; p; p=p->next) ++ add_syms(p); ++ ++ /* Attach to vdso, if provided by the kernel, last so that it does ++ * not become part of the global namespace. */ + if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR) && vdso_base) { + Ehdr *ehdr = (void *)vdso_base; + Phdr *phdr = vdso.phdr = (void *)(vdso_base + ehdr->e_phoff); +@@ -1561,26 +1587,13 @@ _Noreturn void __dls3(size_t *sp) + } + vdso.name = ""; + vdso.shortname = "linux-gate.so.1"; +- vdso.global = 1; + vdso.relocated = 1; + decode_dyn(&vdso); +- vdso.prev = &ldso; +- ldso.next = &vdso; ++ vdso.prev = tail; ++ tail->next = &vdso; ++ tail = &vdso; + } + +- /* Initial dso chain consists only of the app. */ +- head = tail = &app; +- +- /* Donate unused parts of app and library mapping to malloc */ +- reclaim_gaps(&app); +- reclaim_gaps(&ldso); +- +- /* Load preload/needed libraries, add their symbols to the global +- * namespace, and perform all remaining relocations. */ +- if (env_preload) load_preload(env_preload); +- load_deps(&app); +- make_global(&app); +- + for (i=0; app.dynv[i]; i+=2) { + if (!DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG) + app.dynv[i+1] = (size_t)&debug; +@@ -1641,7 +1654,7 @@ _Noreturn void __dls3(size_t *sp) + + void *dlopen(const char *file, int mode) + { +- struct dso *volatile p, *orig_tail, *next; ++ struct dso *volatile p, *orig_tail, *orig_syms_tail, *next; + struct tls_module *orig_tls_tail; + size_t orig_tls_cnt, orig_tls_offset, orig_tls_align; + size_t i; +@@ -1659,15 +1672,14 @@ void *dlopen(const char *file, int mode) + orig_tls_cnt = tls_cnt; + orig_tls_offset = tls_offset; + orig_tls_align = tls_align; ++ orig_syms_tail = syms_tail; + orig_tail = tail; + noload = mode & RTLD_NOLOAD; + + rtld_fail = &jb; + if (setjmp(*rtld_fail)) { + /* Clean up anything new that was (partially) loaded */ +- if (p && p->deps) for (i=0; p->deps[i]; i++) +- if (p->deps[i]->global < 0) +- p->deps[i]->global = 0; ++ revert_syms(orig_syms_tail); + for (p=orig_tail->next; p; p=next) { + next = p->next; + while (p->td_index) { +@@ -1703,24 +1715,21 @@ void *dlopen(const char *file, int mode) + } + + /* First load handling */ +- if (!p->deps) { ++ if (!p->relocated) { + load_deps(p); ++ /* Make new symbols global, at least temporarily, so we can do ++ * relocations. If not RTLD_GLOBAL, this is reverted below. */ ++ add_syms(p); + if (p->deps) for (i=0; p->deps[i]; i++) +- if (!p->deps[i]->global) +- p->deps[i]->global = -1; +- if (!p->global) p->global = -1; ++ add_syms(p->deps[i]); + reloc_all(p); +- if (p->deps) for (i=0; p->deps[i]; i++) +- if (p->deps[i]->global < 0) +- p->deps[i]->global = 0; +- if (p->global < 0) p->global = 0; + } + +- if (mode & RTLD_GLOBAL) { +- if (p->deps) for (i=0; p->deps[i]; i++) +- p->deps[i]->global = 1; +- p->global = 1; +- } ++ /* If RTLD_GLOBAL was not specified, undo any new additions ++ * to the global symbol table. This is a nop if the library was ++ * previously loaded and already global. */ ++ if (!(mode & RTLD_GLOBAL)) ++ revert_syms(orig_syms_tail); + + update_tls_size(); + _dl_debug_state(); +-- +2.12.1 + diff --git a/main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch b/main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch new file mode 100644 index 0000000000..970c2e99ad --- /dev/null +++ b/main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch @@ -0,0 +1,68 @@ +From 4823b13a75b40c4408c1101b363ab00fd118fb27 Mon Sep 17 00:00:00 2001 +From: Rich Felker <dalias@aerifal.cx> +Date: Mon, 13 Mar 2017 00:30:26 -0400 +Subject: [PATCH] reorder addend handling before symbol lookup in relocation + code + +these two tasks are independent now, but in order to support lazy +relocations, the failure path for symbol lookup may want the addend to +be available. +--- + ldso/dynlink.c | 33 +++++++++++++++++---------------- + 1 file changed, 17 insertions(+), 16 deletions(-) + +diff --git a/ldso/dynlink.c b/ldso/dynlink.c +index 0e394e0d..0bd9d50c 100644 +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -323,8 +323,24 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue; + type = R_TYPE(rel[1]); + if (type == REL_NONE) continue; +- sym_index = R_SYM(rel[1]); + reloc_addr = laddr(dso, rel[0]); ++ ++ if (stride > 2) { ++ addend = rel[2]; ++ } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) { ++ addend = 0; ++ } else if (reuse_addends) { ++ /* Save original addend in stage 2 where the dso ++ * chain consists of just ldso; otherwise read back ++ * saved addend since the inline one was clobbered. */ ++ if (head==&ldso) ++ saved_addends[save_slot] = *reloc_addr; ++ addend = saved_addends[save_slot++]; ++ } else { ++ addend = *reloc_addr; ++ } ++ ++ sym_index = R_SYM(rel[1]); + if (sym_index) { + sym = syms + sym_index; + name = strings + sym->st_name; +@@ -345,21 +361,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + def.dso = dso; + } + +- if (stride > 2) { +- addend = rel[2]; +- } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) { +- addend = 0; +- } else if (reuse_addends) { +- /* Save original addend in stage 2 where the dso +- * chain consists of just ldso; otherwise read back +- * saved addend since the inline one was clobbered. */ +- if (head==&ldso) +- saved_addends[save_slot] = *reloc_addr; +- addend = saved_addends[save_slot++]; +- } else { +- addend = *reloc_addr; +- } +- + sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0; + tls_val = def.sym ? def.sym->st_value : 0; + +-- +2.12.1 + diff --git a/main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch b/main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch new file mode 100644 index 0000000000..19e3764e68 --- /dev/null +++ b/main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch @@ -0,0 +1,172 @@ +From 6476b8135760659b25c93ff9308425ca98a9e777 Mon Sep 17 00:00:00 2001 +From: Rich Felker <dalias@aerifal.cx> +Date: Mon, 13 Mar 2017 08:52:41 -0400 +Subject: [PATCH] emulate lazy relocation as deferrable relocation + +traditional lazy relocation with call-time plt resolver is +intentionally not implemented, as it is a huge bug surface and demands +significant amounts of arch-specific code and requires ongoing +maintenance to ensure compatibility with applications which make use +of new additions to the arch's register file in passing function +arguments. + +some applications, however, depend on the ability to dlopen modules +which have unsatisfied symbol references at the time they are loaded, +either avoiding use of the affected interfaces or manually loading +another module to provide the missing definition via their own module +dependency tracking outside the ELF data structures. while such usage +is non-conforming, failure to support it has been a significant +obstacle for users/distributions trying to support affected software, +particularly the X.org server. + +instead of resolving lazy relocations at call time, this patch saves +unresolved GOT/PLT relocations for deferral and retries them after +each subsequent dlopen until they are resolved. since dlopen is the +only time at which the effective global symbol table can change, this +behavior is not observably different from traditional lazy binding, +and the required code is minimal. +--- + ldso/dynlink.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 66 insertions(+), 3 deletions(-) + +diff --git a/ldso/dynlink.c b/ldso/dynlink.c +index 0bd9d50c..f8db1f82 100644 +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -58,7 +58,8 @@ struct dso { + uint32_t *ghashtab; + int16_t *versym; + char *strings; +- struct dso *syms_next; ++ struct dso *syms_next, *lazy_next; ++ size_t *lazy, lazy_cnt; + unsigned char *map; + size_t map_len; + dev_t dev; +@@ -113,7 +114,7 @@ static struct builtin_tls { + static size_t *saved_addends, *apply_addends_to; + + static struct dso ldso; +-static struct dso *head, *tail, *fini_head, *syms_tail; ++static struct dso *head, *tail, *fini_head, *syms_tail, *lazy_head; + static char *env_path, *sys_path; + static unsigned long long gencnt; + static int runtime; +@@ -350,6 +351,13 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + : find_sym(ctx, name, type==REL_PLT); + if (!def.sym && (sym->st_shndx != SHN_UNDEF + || sym->st_info>>4 != STB_WEAK)) { ++ if (dso->lazy && (type==REL_PLT || type==REL_GOT)) { ++ dso->lazy[3*dso->lazy_cnt+0] = rel[0]; ++ dso->lazy[3*dso->lazy_cnt+1] = rel[1]; ++ dso->lazy[3*dso->lazy_cnt+2] = addend; ++ dso->lazy_cnt++; ++ continue; ++ } + error("Error relocating %s: %s: symbol not found", + dso->name, name); + if (runtime) longjmp(*rtld_fail, 1); +@@ -451,6 +459,26 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri + } + } + ++static void redo_lazy_relocs() ++{ ++ struct dso *p = lazy_head, *next; ++ lazy_head = 0; ++ for (; p; p=next) { ++ next = p->lazy_next; ++ size_t size = p->lazy_cnt*3*sizeof(size_t); ++ p->lazy_cnt = 0; ++ do_relocs(p, p->lazy, size, 3); ++ if (p->lazy_cnt) { ++ p->lazy_next = lazy_head; ++ lazy_head = p; ++ } else { ++ free(p->lazy); ++ p->lazy = 0; ++ p->lazy_next = 0; ++ } ++ } ++} ++ + /* A huge hack: to make up for the wastefulness of shared libraries + * needing at least a page of dirty memory even if they have no global + * data, we reclaim the gaps at the beginning and end of writable maps +@@ -1653,9 +1681,31 @@ _Noreturn void __dls3(size_t *sp) + for(;;); + } + ++static void prepare_lazy(struct dso *p) ++{ ++ size_t dyn[DYN_CNT], n, flags1=0; ++ decode_vec(p->dynv, dyn, DYN_CNT); ++ search_vec(p->dynv, &flags1, DT_FLAGS_1); ++ if (dyn[DT_BIND_NOW] || (dyn[DT_FLAGS] & DF_BIND_NOW) || (flags1 & DF_1_NOW)) ++ return; ++ n = dyn[DT_RELSZ]/2 + dyn[DT_RELASZ]/3 + dyn[DT_PLTRELSZ]/2 + 1; ++ if (NEED_MIPS_GOT_RELOCS) { ++ size_t j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM); ++ size_t i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO); ++ n += i-j; ++ } ++ p->lazy = calloc(n, 3*sizeof(size_t)); ++ if (!p->lazy) { ++ error("Error preparing lazy relocation for %s: %m", p->name); ++ longjmp(*rtld_fail, 1); ++ } ++ p->lazy_next = lazy_head; ++ lazy_head = p; ++} ++ + void *dlopen(const char *file, int mode) + { +- struct dso *volatile p, *orig_tail, *orig_syms_tail, *next; ++ struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next; + struct tls_module *orig_tls_tail; + size_t orig_tls_cnt, orig_tls_offset, orig_tls_align; + size_t i; +@@ -1673,6 +1723,7 @@ void *dlopen(const char *file, int mode) + orig_tls_cnt = tls_cnt; + orig_tls_offset = tls_offset; + orig_tls_align = tls_align; ++ orig_lazy_head = lazy_head; + orig_syms_tail = syms_tail; + orig_tail = tail; + noload = mode & RTLD_NOLOAD; +@@ -1701,6 +1752,7 @@ void *dlopen(const char *file, int mode) + tls_cnt = orig_tls_cnt; + tls_offset = orig_tls_offset; + tls_align = orig_tls_align; ++ lazy_head = orig_lazy_head; + tail = orig_tail; + tail->next = 0; + p = 0; +@@ -1718,6 +1770,12 @@ void *dlopen(const char *file, int mode) + /* First load handling */ + if (!p->relocated) { + load_deps(p); ++ if ((mode & RTLD_LAZY)) { ++ prepare_lazy(p); ++ if (p->deps) for (i=0; p->deps[i]; i++) ++ if (!p->deps[i]->relocated) ++ prepare_lazy(p->deps[i]); ++ } + /* Make new symbols global, at least temporarily, so we can do + * relocations. If not RTLD_GLOBAL, this is reverted below. */ + add_syms(p); +@@ -1732,6 +1790,11 @@ void *dlopen(const char *file, int mode) + if (!(mode & RTLD_GLOBAL)) + revert_syms(orig_syms_tail); + ++ /* Processing of deferred lazy relocations must not happen until ++ * the new libraries are committed; otherwise we could end up with ++ * relocations resolved to symbol definitions that get removed. */ ++ redo_lazy_relocs(); ++ + update_tls_size(); + _dl_debug_state(); + orig_tail = tail; +-- +2.12.1 + diff --git a/main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch b/main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch new file mode 100644 index 0000000000..4ad7149fc8 --- /dev/null +++ b/main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch @@ -0,0 +1,51 @@ +From a393d5cc8d22b628fcc1da1b3a2cdae42ca643a9 Mon Sep 17 00:00:00 2001 +From: Rich Felker <dalias@aerifal.cx> +Date: Wed, 15 Mar 2017 16:50:19 -0400 +Subject: [PATCH] precalculate gnu hash rather than doing it lazily in find_sym + inner loop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +this change was suggested based on testing done by Timo Teräs almost +two years ago; the branch (and probably call prep overhead) in the +inner loop was found to contribute noticably to total symbol lookup +time. this change will make lookup slightly slower if libraries were +built with only the traditional "sysv" ELF hash table, but based on +how much slower lookup tends to be without the gnu hash table, it +seems reasonable to assume that (1) users building without gnu hash +don't care about dynamic linking performance, and (2) the extra time +spent computing the gnu hash is likely to be dominated by the slowness +of the sysv hash table lookup anyway. +--- + ldso/dynlink.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/ldso/dynlink.c b/ldso/dynlink.c +index 178fe27e..5361b844 100644 +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -258,18 +258,12 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso, + + static struct symdef find_sym(struct dso *dso, const char *s, int need_def) + { +- uint32_t h = 0, gh, gho, *ght; +- size_t ghm = 0; ++ uint32_t h = 0, gh = gnu_hash(s), gho = gh / (8*sizeof(size_t)), *ght; ++ size_t ghm = 1ul << gh % (8*sizeof(size_t)); + struct symdef def = {0}; + for (; dso; dso=dso->syms_next) { + Sym *sym; + if ((ght = dso->ghashtab)) { +- if (!ghm) { +- gh = gnu_hash(s); +- int maskbits = 8 * sizeof ghm; +- gho = gh / maskbits; +- ghm = 1ul << gh % maskbits; +- } + sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm); + } else { + if (!h) h = sysv_hash(s); +-- +2.12.1 + diff --git a/main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch b/main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch new file mode 100644 index 0000000000..81fd2d7145 --- /dev/null +++ b/main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch @@ -0,0 +1,44 @@ +From 0c53178ec09478ca5f6ca6b5ad09d50a10c8f19d Mon Sep 17 00:00:00 2001 +From: Rich Felker <dalias@aerifal.cx> +Date: Tue, 21 Mar 2017 08:35:59 -0400 +Subject: [PATCH] fix dlopen/dlsym regression opening libs already loaded at + startup + +commit 4ff234f6cba96403b5de6d29d48a59fd73252040 erroneously changed +the condition for running certain code at dlopen time to check whether +the library was already relocated rather than whether it already had +its deps[] table filled. this was out of concern over whether the code +under the conditional would be idempotent/safe to call on an +already-loaded libraries. however, I missed a consideration in the +opposite direction: if a library was loaded at program startup rather +than dlopen, its deps[] table was not yet allocated/filled, and +load_deps needs to be called at dlopen time in order for dlsym to be +able to perform dependency-order symbol lookups. + +in order to avoid wasteful allocation of lazy-binding relocation +tables for libraries which were already loaded and relocated at +startup, the check for !p->relocated is not deleted entirely, but +moved to apply only to allocation of these dables. +--- + ldso/dynlink.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ldso/dynlink.c b/ldso/dynlink.c +index 5361b844..d20dbd87 100644 +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -1768,9 +1768,9 @@ void *dlopen(const char *file, int mode) + } + + /* First load handling */ +- if (!p->relocated) { ++ if (!p->deps) { + load_deps(p); +- if ((mode & RTLD_LAZY)) { ++ if (!p->relocated && (mode & RTLD_LAZY)) { + prepare_lazy(p); + if (p->deps) for (i=0; p->deps[i]; i++) + if (!p->deps[i]->relocated) +-- +2.12.1 + diff --git a/main/musl/APKBUILD b/main/musl/APKBUILD index 3425bba77b..6987757653 100644 --- a/main/musl/APKBUILD +++ b/main/musl/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Timo Teräs <timo.teras@iki.fi> pkgname=musl pkgver=1.1.16 -pkgrel=5 +pkgrel=6 pkgdesc="the musl c library (libc) implementation" url="http://www.musl-libc.org/" arch="all" @@ -32,6 +32,9 @@ source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz 0013-fix-lsearch-and-lfind-to-pass-key-as-first-arg-to-th.patch 0014-fix-ld-behavior-dependent-crash-in-ppc64-ldso-startu.patch 0015-treat-STB_WEAK-and-STB_GNU_UNIQUE-like-STB_GLOBAL-in.patch + 0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch + 0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch + 0018-emulate-lazy-relocation-as-deferrable-relocation.patch 0019-fix-free-of-uninitialized-buffer-pointer-on-error-in.patch 0020-in-static-dl_iterate_phdr-fix-use-of-possibly-uninit.patch 0021-fix-possible-fd-leak-unrestored-cancellation-state-o.patch @@ -40,8 +43,10 @@ source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz 0024-avoid-loading-of-multiple-libc-versions-via-explicit.patch 0025-remove-unused-refcnt-field-for-shared-libraries.patch 0026-fix-threshold-constants-in-j0f-y0f-j1f-y1f.patch + 0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch 0028-s390x-fix-fpreg_t-and-remove-unused-per_struct.patch 0029-fix-POSIX-format-TZ-dst-transition-times-for-souther.patch + 0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch ldconfig __stack_chk_fail_local.c @@ -177,6 +182,9 @@ d73358b5377db7b708dd8fecda8f6bdae007423e853cde86b33ce5078e31761eab3f2169541aca5b e3fe35bf310c9d5813553e6762c66764b384a9c2f405e3ba3cea887ff55f6bcd947e55012c5f3e06e16a66d5f289b694ac898fc9b1d4bb0cfb50cf92135e36a3 0013-fix-lsearch-and-lfind-to-pass-key-as-first-arg-to-th.patch 7a6cd67a5ca246eaedb992f9267bb94b0baccbbd5bb9a6a10a503f623ef052480fc4832da4330b5d3531f239580fdb9e36072f456fe4dd2e9ca6ae6050c55aab 0014-fix-ld-behavior-dependent-crash-in-ppc64-ldso-startu.patch 48d4fd3510404b2fe934dffb2fc725c6a31e30e33421dc81073673d680d00866890f9c826bf48874845c863db52ebbb015c9e94b45c7a20b6949236f76f81709 0015-treat-STB_WEAK-and-STB_GNU_UNIQUE-like-STB_GLOBAL-in.patch +41b8ba87082e586393b6c9570b7fc32455832a4a294ca1bb344f9eb72cd971be92cd03e590508cc1cd44fea532ab860690f38daaae665c68864302a20f11a01d 0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch +cad53ef772bc3ceae7695304df2a202d01a72cd4a707cffa9a7489947c9151ddd72bd2e2672e6508f56ec188973c886a0a99f85d4a4c54306284fe1b241c52db 0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch +e4935a23787e5eb5df4f1d487c10d63d4d2f34509ba5871c40037229f09057caad0679d12c444d7e7c5c719c2106e1b130921275d2ed3b1b8ffc6c97c9dde67a 0018-emulate-lazy-relocation-as-deferrable-relocation.patch 0754297d5e2cc9d2244835badb39325b0907604e377ddbabbb865a12429741c71b461ee9f19ebdebc6bd9b6e878919b2bc292b113e1477591171627623dbf557 0019-fix-free-of-uninitialized-buffer-pointer-on-error-in.patch 0fb792b688bea5024a59645eda680c57c509ad5f6923c8816647644ce5b438f18ef2036b4252ae2993c003e0e192d3a0cfd1f909d5a8c3cd8c21ef1130fca929 0020-in-static-dl_iterate_phdr-fix-use-of-possibly-uninit.patch 5cb2e43b01d30b9552668508bc4e855c7e90b323c811bf34989eae97b8cfbdccbe50e13bf95cac727314c0077af823eb4666318e53cb2d4584052b2870c36a3b 0021-fix-possible-fd-leak-unrestored-cancellation-state-o.patch @@ -185,8 +193,10 @@ efabb66abd01dbf73d89933328beffb738d71b227f7d7dd48b02ca0c9b04b554475bde70a814317b b1141d2b5c28d16848dcd8b40182938d634023a4aa0e7f0be567fa7e6c40c03431574e9214949e723a031f90a6c20153ca1a6c21eda3b8ea05de5cebf6b1fe38 0024-avoid-loading-of-multiple-libc-versions-via-explicit.patch 955882a1a2a3e7211e20527858ca5dc0944b5d44fdacb547e0d4b4bd27fdf63672b95e16faa4b37e9ee4b384e7f33ce394ee556a201be6011630c84ebf64b312 0025-remove-unused-refcnt-field-for-shared-libraries.patch dad1ed979898ddaa0a49c601160a948ba229b251307210a14240e4ebf6230b16ffc0138f396fc226942c487e196211964449e7314f83d208ac219a071a4e11b3 0026-fix-threshold-constants-in-j0f-y0f-j1f-y1f.patch +9b91076729245d4192c01b82700898e8baca0d3db11fdb5f257f88a40d3d59442c30d13434a81e4a067553e28477ceea9edd0960c49da9bba684147dd645a85d 0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch 0472694cdd5a95b8df9b0e585afc7171ae9138133832ad7c0fadae4ea0a742eaa09a4d4449197ccaaefeae99c3cb7ec784068243a3a2d434429a0455c396e6bb 0028-s390x-fix-fpreg_t-and-remove-unused-per_struct.patch 33c24b895bcf1b84d90a522328b39d5b0a4aff822d0701f2f9db07a6c44c49bb3a8b16a19150c550b4fe04fad40e9af43fdf5e1fda0201e9779a471088fe9f23 0029-fix-POSIX-format-TZ-dst-transition-times-for-souther.patch +adcb5b213ebd9fc5d50cc46d4444ed64a4f928a6b4767428d7d720c6a563ba1d4a3173d6546b41379356b155a26eaad652d7b831776cc3f31e942f155db9239d 0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch 8d3a2d5315fc56fee7da9abb8b89bb38c6046c33d154c10d168fb35bfde6b0cf9f13042a3bceee34daf091bc409d699223735dcf19f382eeee1f6be34154f26f ldconfig 062bb49fa54839010acd4af113e20f7263dde1c8a2ca359b5fb2661ef9ed9d84a0f7c3bc10c25dcfa10bb3c5a4874588dff636ac43d5dbb3d748d75400756d0b __stack_chk_fail_local.c 0d80f37b34a35e3d14b012257c50862dfeb9d2c81139ea2dfa101d981d093b009b9fa450ba27a708ac59377a48626971dfc58e20a3799084a65777a0c32cbc7d getconf.c |