diff options
Diffstat (limited to 'toolchain')
-rw-r--r-- | toolchain/musl/common.mk | 2 | ||||
-rw-r--r-- | toolchain/musl/patches/020-make-relocation-time-symbol-lookup-and-dlsym-consistent.patch | 139 |
2 files changed, 140 insertions, 1 deletions
diff --git a/toolchain/musl/common.mk b/toolchain/musl/common.mk index 87424646c3..93049479b2 100644 --- a/toolchain/musl/common.mk +++ b/toolchain/musl/common.mk @@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/target.mk PKG_NAME:=musl PKG_VERSION:=1.1.19 -PKG_RELEASE=1 +PKG_RELEASE=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) diff --git a/toolchain/musl/patches/020-make-relocation-time-symbol-lookup-and-dlsym-consistent.patch b/toolchain/musl/patches/020-make-relocation-time-symbol-lookup-and-dlsym-consistent.patch new file mode 100644 index 0000000000..05e2af02e7 --- /dev/null +++ b/toolchain/musl/patches/020-make-relocation-time-symbol-lookup-and-dlsym-consistent.patch @@ -0,0 +1,139 @@ +>From a57cd35acf26ba6202ed6534a57f496464f431a1 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <nsz@port70.net> +Date: Sat, 10 Aug 2019 23:14:40 +0000 +Subject: [PATCH] make relocation time symbol lookup and dlsym consistent + +Using common code path for all symbol lookups fixes three dlsym issues: + +- st_shndx of STT_TLS symbols were not checked and thus an undefined + tls symbol reference could be incorrectly treated as a definition + (the sysv hash lookup returns undefined symbols, gnu does not, so should + be rare in practice). + +- symbol binding was not checked so a hidden symbol may be returned + (in principle STB_LOCAL symbols may appear in the dynamic symbol table + for hidden symbols, but linkers most likely don't produce it). + +- mips specific behaviour was not applied (ARCH_SYM_REJECT_UND) so + undefined symbols may be returned on mips. + +always_inline is used to avoid relocation performance regression, the +code generation for find_sym should not be affected. + +BAckported to 1.1.19 + +--- + ldso/dynlink.c | 84 +++++++++++++++++++------------------------------- + 1 file changed, 31 insertions(+), 53 deletions(-) + +--- a/ldso/dynlink.c ++++ b/ldso/dynlink.c +@@ -257,12 +257,16 @@ static Sym *gnu_lookup_filtered(uint32_t + #define ARCH_SYM_REJECT_UND(s) 0 + #endif + +-static struct symdef find_sym(struct dso *dso, const char *s, int need_def) ++#if defined(__GNUC__) ++__attribute__((always_inline)) ++#endif ++static inline struct symdef find_sym2(struct dso *dso, const char *s, int need_def, int use_deps) + { + 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) { ++ struct dso **deps = use_deps ? dso->deps : 0; ++ for (; dso; dso=use_deps ? *deps++ : dso->syms_next) { + Sym *sym; + if ((ght = dso->ghashtab)) { + sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm); +@@ -290,6 +294,11 @@ static struct symdef find_sym(struct dso + __attribute__((__visibility__("hidden"))) + ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic(); + ++static struct symdef find_sym(struct dso *dso, const char *s, int need_def) ++{ ++ return find_sym2(dso, s, need_def, 0); ++} ++ + static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride) + { + unsigned char *base = dso->base; +@@ -1872,58 +1881,27 @@ void *__tls_get_addr(tls_mod_off_t *); + + static void *do_dlsym(struct dso *p, const char *s, void *ra) + { +- size_t i; +- uint32_t h = 0, gh = 0, *ght; +- Sym *sym; +- if (p == head || p == RTLD_DEFAULT || p == RTLD_NEXT) { +- if (p == RTLD_DEFAULT) { +- p = head; +- } else if (p == RTLD_NEXT) { +- p = addr2dso((size_t)ra); +- if (!p) p=head; +- p = p->next; +- } +- struct symdef def = find_sym(p, s, 0); +- if (!def.sym) goto failed; +- if ((def.sym->st_info&0xf) == STT_TLS) +- return __tls_get_addr((tls_mod_off_t []){def.dso->tls_id, def.sym->st_value}); +- if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC) +- return def.dso->funcdescs + (def.sym - def.dso->syms); +- return laddr(def.dso, def.sym->st_value); +- } +- if (__dl_invalid_handle(p)) ++ int use_deps = 0; ++ if (p == head || p == RTLD_DEFAULT) { ++ p = head; ++ } else if (p == RTLD_NEXT) { ++ p = addr2dso((size_t)ra); ++ if (!p) p=head; ++ p = p->next; ++ } else if (__dl_invalid_handle(p)) { ++ return 0; ++ } else ++ use_deps = 1; ++ struct symdef def = find_sym2(p, s, 0, use_deps); ++ if (!def.sym) { ++ error("Symbol not found: %s", s); + return 0; +- if ((ght = p->ghashtab)) { +- gh = gnu_hash(s); +- sym = gnu_lookup(gh, ght, p, s); +- } else { +- h = sysv_hash(s); +- sym = sysv_lookup(s, h, p); + } +- if (sym && (sym->st_info&0xf) == STT_TLS) +- return __tls_get_addr((tls_mod_off_t []){p->tls_id, sym->st_value}); +- if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == STT_FUNC) +- return p->funcdescs + (sym - p->syms); +- if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) +- return laddr(p, sym->st_value); +- for (i=0; p->deps[i]; i++) { +- if ((ght = p->deps[i]->ghashtab)) { +- if (!gh) gh = gnu_hash(s); +- sym = gnu_lookup(gh, ght, p->deps[i], s); +- } else { +- if (!h) h = sysv_hash(s); +- sym = sysv_lookup(s, h, p->deps[i]); +- } +- if (sym && (sym->st_info&0xf) == STT_TLS) +- return __tls_get_addr((tls_mod_off_t []){p->deps[i]->tls_id, sym->st_value}); +- if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == STT_FUNC) +- return p->deps[i]->funcdescs + (sym - p->deps[i]->syms); +- if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) +- return laddr(p->deps[i], sym->st_value); +- } +-failed: +- error("Symbol not found: %s", s); +- return 0; ++ if ((def.sym->st_info&0xf) == STT_TLS) ++ return __tls_get_addr((tls_mod_off_t []){def.dso->tls_id, def.sym->st_value-DTP_OFFSET}); ++ if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC) ++ return def.dso->funcdescs + (def.sym - def.dso->syms); ++ return laddr(def.dso, def.sym->st_value); + } + + int dladdr(const void *addr, Dl_info *info) |