From b8be671580f22479d534e188aec9c81a01a3d5f8 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sat, 10 Mar 2018 17:20:28 +0200 Subject: linker: Refactor glibc dlopen hacks Allows us to return "valid" pointer when bionic program calls dlopen. --- src/linker/dlfcn.c | 16 ++++++++-------- src/linker/linker.c | 17 +++++++---------- src/linker/linker.h | 3 ++- 3 files changed, 17 insertions(+), 19 deletions(-) (limited to 'src/linker') diff --git a/src/linker/dlfcn.c b/src/linker/dlfcn.c index 38fc215..22d212a 100644 --- a/src/linker/dlfcn.c +++ b/src/linker/dlfcn.c @@ -67,10 +67,11 @@ void *bionic_dlopen(const char *filename, int flag) verbose("%s (%d)", filename, flag); soinfo *ret; pthread_mutex_lock(&apkenv_dl_lock); - ret = apkenv_find_library(filename); + ret = apkenv_find_library(filename, false); if (unlikely(ret == NULL)) { - set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY); + if (!(ret = dlopen(filename, flag))) + set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY); } else { apkenv_call_constructors_recursive(ret); ret->refcount++; @@ -102,12 +103,6 @@ void *bionic_dlsym(void *handle, const char *symbol) pthread_mutex_lock(&apkenv_dl_lock); -#if 0 - if(unlikely(handle == 0)) { - set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE); - goto err; - } -#endif if(unlikely(symbol == 0)) { set_dlerror(DL_ERR_BAD_SYMBOL_NAME); goto err; @@ -127,6 +122,11 @@ void *bionic_dlsym(void *handle, const char *symbol) } } + if(unlikely(handle == 0)) { + set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE); + goto err; + } + if(handle == RTLD_DEFAULT) { sym = apkenv_lookup(symbol, &found, NULL); } else if(handle == RTLD_NEXT) { diff --git a/src/linker/linker.c b/src/linker/linker.c index e72b9aa..12a3521 100644 --- a/src/linker/linker.c +++ b/src/linker/linker.c @@ -1121,7 +1121,7 @@ get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) #endif static soinfo * -apkenv_load_library(const char *name) +apkenv_load_library(const char *name, const bool try_glibc) { char fullpath[512]; int fd = apkenv_open_library(name, fullpath); @@ -1133,14 +1133,11 @@ apkenv_load_library(const char *name) Elf32_Ehdr *hdr; if(fd == -1) { - if (dlopen(name, RTLD_NOW | RTLD_GLOBAL)) { + if (try_glibc && dlopen(name, RTLD_NOW | RTLD_GLOBAL)) { DEBUG("Loaded %s with glibc dlopen\n", name); return NULL; } -#if !LINKER_DEBUG - if (!is_lib_optional(name)) -#endif - DL_ERR("Library '%s' not found", name); + DL_ERR("Bionic library '%s' not found", name); return NULL; } @@ -1245,7 +1242,7 @@ apkenv_init_library(soinfo *si) return si; } -soinfo *apkenv_find_library(const char *name) +soinfo *apkenv_find_library(const char *name, const bool try_glibc) { soinfo *si; const char *bname; @@ -1274,7 +1271,7 @@ soinfo *apkenv_find_library(const char *name) } TRACE("[ %5d '%s' has not been loaded yet. Locating...]\n", apkenv_pid, name); - si = apkenv_load_library(name); + si = apkenv_load_library(name, try_glibc); if(si == NULL) return NULL; return apkenv_init_library(si); @@ -2055,7 +2052,7 @@ static int apkenv_link_image(soinfo *si, unsigned wr_offset) int i; memset(apkenv_preloads, 0, sizeof(apkenv_preloads)); for(i = 0; apkenv_ldpreload_names[i] != NULL; i++) { - soinfo *lsi = apkenv_find_library(apkenv_ldpreload_names[i]); + soinfo *lsi = apkenv_find_library(apkenv_ldpreload_names[i], true); if(lsi == 0) { apkenv_strlcpy(apkenv_tmp_err_buf, apkenv_linker_get_error(), sizeof(apkenv_tmp_err_buf)); DL_ERR("%5d could not load needed library '%s' for '%s' (%s)", @@ -2072,7 +2069,7 @@ static int apkenv_link_image(soinfo *si, unsigned wr_offset) DEBUG("%5d %s needs %s\n", apkenv_pid, si->name, si->strtab + d[1]); soinfo *lsi = NULL; // if (get_builtin_lib_handle(si->strtab + d[1]) == NULL) - lsi = apkenv_find_library(si->strtab + d[1]); + lsi = apkenv_find_library(si->strtab + d[1], true); if(lsi == 0) { /** * XXX Dirty Hack Alarm --thp XXX diff --git a/src/linker/linker.h b/src/linker/linker.h index 13d9bff..6b1924b 100644 --- a/src/linker/linker.h +++ b/src/linker/linker.h @@ -33,6 +33,7 @@ #include #include #include +#include #undef PAGE_MASK #undef PAGE_SIZE @@ -204,7 +205,7 @@ extern soinfo apkenv_libdl_info; #define DT_PREINIT_ARRAYSZ 33 #endif -soinfo *apkenv_find_library(const char *name); +soinfo *apkenv_find_library(const char *name, const bool try_glibc); unsigned apkenv_unload_library(soinfo *si); Elf32_Sym *apkenv_lookup_in_library(soinfo *si, const char *name); Elf32_Sym *apkenv_lookup(const char *name, soinfo **found, soinfo *start); -- cgit v1.2.3