diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 8705d9a5c..a70abf51b 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "private/bionic_tls.h" @@ -260,6 +261,7 @@ soinfo* get_libdl_info() { __libdl_info->strtab_size_ = sizeof(ANDROID_LIBDL_STRTAB); __libdl_info->local_group_root_ = __libdl_info; __libdl_info->soname_ = "libdl.so"; + __libdl_info->target_sdk_version_ = __ANDROID_API__; #if defined(__arm__) strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_)); #endif diff --git a/linker/linker.cpp b/linker/linker.cpp index a0f82fc6c..5aabacc7f 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -26,6 +26,7 @@ * SUCH DAMAGE. */ +#include #include #include #include @@ -1001,7 +1002,10 @@ const ElfW(Sym)* dlsym_linear_lookup(const char* name, const ElfW(Sym)* s = nullptr; for (soinfo* si = start; si != nullptr; si = si->next) { - if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0) { + // Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...) + // if the library is opened by application with target api level <= 22 + // See http://b/21565766 + if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0 && si->get_target_sdk_version() > 22) { continue; } @@ -1230,8 +1234,7 @@ static int open_library(const char* name, off64_t* file_offset) { static const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) { #if !defined(__LP64__) // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029 - uint32_t target_sdk_version = get_application_target_sdk_version(); - if (target_sdk_version != 0 && target_sdk_version <= 22) { + if (get_application_target_sdk_version() <= 22) { const char* bname = basename(dt_needed); if (bname != dt_needed) { DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed); @@ -2406,6 +2409,17 @@ soinfo* soinfo::get_local_group_root() const { return local_group_root_; } +// This function returns api-level at the time of +// dlopen/load. Note that libraries opened by system +// will always have 'current' api level. +uint32_t soinfo::get_target_sdk_version() const { + if (!has_min_version(2)) { + return __ANDROID_API__; + } + + return local_group_root_->target_sdk_version_; +} + /* Force any of the closed stdin, stdout and stderr to be associated with /dev/null. */ static int nullify_closed_stdio() { @@ -2877,13 +2891,13 @@ bool soinfo::prelink_image() { } // Before M release linker was using basename in place of soname. - // In the case when dt_soname is absent some apps stop working: + // In the case when dt_soname is absent some apps stop working // because they can't find dt_needed library by soname. // This workaround should keep them working. (applies only - // for apps targeting sdk version <=22). Make an exception for main - // executable which does not need dt_soname. - uint32_t target_sdk_version = get_application_target_sdk_version(); - if (soname_ == nullptr && this != somain && target_sdk_version != 0 && target_sdk_version <= 22) { + // for apps targeting sdk version <=22). Make an exception for + // the main executable and linker; they do not need to have dt_soname + if (soname_ == nullptr && this != somain && (flags_ & FLAG_LINKER) == 0 && + get_application_target_sdk_version() <= 22) { soname_ = basename(realpath_.c_str()); DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"", get_realpath(), soname_); @@ -2899,6 +2913,10 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group_root_ = this; } + if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) { + target_sdk_version_ = get_application_target_sdk_version(); + } + VersionTracker version_tracker; if (!version_tracker.init(this)) { diff --git a/linker/linker.h b/linker/linker.h index 04b584ed5..6042cb844 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -334,6 +334,8 @@ struct soinfo { bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const; + uint32_t get_target_sdk_version() const; + private: bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const; ElfW(Sym)* elf_addr_lookup(const void* addr); @@ -393,6 +395,8 @@ struct soinfo { ElfW(Addr) verneed_ptr_; size_t verneed_cnt_; + uint32_t target_sdk_version_; + friend soinfo* get_libdl_info(); }; diff --git a/linker/linker_sdk_versions.cpp b/linker/linker_sdk_versions.cpp index c73eb38d9..e9ad3dc25 100644 --- a/linker/linker_sdk_versions.cpp +++ b/linker/linker_sdk_versions.cpp @@ -15,9 +15,10 @@ */ #include "linker.h" +#include #include -static std::atomic g_target_sdk_version; +static std::atomic g_target_sdk_version(__ANDROID_API__); void set_application_target_sdk_version(uint32_t target) { g_target_sdk_version = target;