aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Angelo Daros de Luca <luizluca@gmail.com>2019-08-13 03:01:07 -0300
committerHauke Mehrtens <hauke@hauke-m.de>2019-08-17 17:23:17 +0200
commit5e3b21c91647f72e73a550f3059fa7ea8146759f (patch)
tree6b6d000fa65fbe64b3daf9582f218c35535c8058
parent2df2b75208dce06dee02508c8d589fc5f540023d (diff)
downloadupstream-5e3b21c91647f72e73a550f3059fa7ea8146759f.tar.gz
upstream-5e3b21c91647f72e73a550f3059fa7ea8146759f.tar.bz2
upstream-5e3b21c91647f72e73a550f3059fa7ea8146759f.zip
musl: ldso/dlsym: fix mips returning undef dlsym
This happens only the second time a library is loaded by dlopen(). After lib1 is loaded, dlsym(lib1,"undef1") correctly resolves the undef symbol from lib1 dependencies. After the second library is loaded, dlsym(lib2,"undef1") was returning the address of "undef1" in lib2 instead of searching lib2 dependencies. Backporting upstream fix which now uses the same logic for relocation time and dlsym. Fixes openwrt/packages#9297 Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
-rw-r--r--package/libs/toolchain/Makefile2
-rw-r--r--toolchain/musl/common.mk2
-rw-r--r--toolchain/musl/patches/020-make-relocation-time-symbol-lookup-and-dlsym-consistent.patch139
3 files changed, 141 insertions, 2 deletions
diff --git a/package/libs/toolchain/Makefile b/package/libs/toolchain/Makefile
index febc7c2dbc..ac5f21d31a 100644
--- a/package/libs/toolchain/Makefile
+++ b/package/libs/toolchain/Makefile
@@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=toolchain
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=GPL-3.0-with-GCC-exception
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)