summaryrefslogtreecommitdiff
path: root/linker/linker.cpp
diff options
context:
space:
mode:
authorDimitry Ivanov <dimitry@google.com>2017-03-27 14:11:02 -0700
committerDimitry Ivanov <dimitry@google.com>2017-04-01 19:15:32 -0700
commitdedcf35bcc98e8b62fb6480022cd11ae671280ad (patch)
tree922564308baea40441defe570dce912aff258615 /linker/linker.cpp
parenteca0f9910d3b1fc5608fc82b1ff28325f74678cb (diff)
Fix lookup logic for linked namespaces
When looking for already loaded libraries include linked namespaces to the search, but check if the library is accessible from the main namespace. Bug: http://b/36008422 Bug: http://b/35417197 Bug: http://b/34052337 Bug: http://b/36660652 Bug: https://issuetracker.google.com/36636090 Test: run bionic-unit-tests --gtest_filter=dl*:Dl* Change-Id: Ic7c1d48114da3ca5dc6512ef03f595dd17b6ed17 (cherry picked from commit d3e7d088453e089b3d625b0864ccdf3c74893f18)
Diffstat (limited to 'linker/linker.cpp')
-rw-r--r--linker/linker.cpp101
1 files changed, 75 insertions, 26 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp
index e2d61151f..1647db70b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1112,11 +1112,43 @@ static void for_each_dt_needed(const ElfReader& elf_reader, F action) {
}
}
+static bool find_loaded_library_by_inode(android_namespace_t* ns,
+ const struct stat& file_stat,
+ off64_t file_offset,
+ bool search_linked_namespaces,
+ soinfo** candidate) {
+
+ auto predicate = [&](soinfo* si) {
+ return si->get_st_dev() != 0 &&
+ si->get_st_ino() != 0 &&
+ si->get_st_dev() == file_stat.st_dev &&
+ si->get_st_ino() == file_stat.st_ino &&
+ si->get_file_offset() == file_offset;
+ };
+
+ *candidate = ns->soinfo_list().find_if(predicate);
+
+ if (*candidate == nullptr && search_linked_namespaces) {
+ for (auto& link : ns->linked_namespaces()) {
+ android_namespace_t* linked_ns = link.linked_namespace();
+ soinfo* si = linked_ns->soinfo_list().find_if(predicate);
+
+ if (si != nullptr && link.is_accessible(si->get_soname())) {
+ *candidate = si;
+ return true;
+ }
+ }
+ }
+
+ return *candidate != nullptr;
+}
+
static bool load_library(android_namespace_t* ns,
LoadTask* task,
LoadTaskList* load_tasks,
int rtld_flags,
- const std::string& realpath) {
+ const std::string& realpath,
+ bool search_linked_namespaces) {
off64_t file_offset = task->get_file_offset();
const char* name = task->get_name();
const android_dlextinfo* extinfo = task->get_extinfo();
@@ -1144,17 +1176,8 @@ static bool load_library(android_namespace_t* ns,
// Check for symlink and other situations where
// file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
- auto predicate = [&](soinfo* si) {
- return si->get_st_dev() != 0 &&
- si->get_st_ino() != 0 &&
- si->get_st_dev() == file_stat.st_dev &&
- si->get_st_ino() == file_stat.st_ino &&
- si->get_file_offset() == file_offset;
- };
-
- soinfo* si = ns->soinfo_list().find_if(predicate);
-
- if (si != nullptr) {
+ soinfo* si = nullptr;
+ if (find_loaded_library_by_inode(ns, file_stat, file_offset, search_linked_namespaces, &si)) {
TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
"will return existing soinfo", name, si->get_realpath());
task->set_soinfo(si);
@@ -1249,7 +1272,8 @@ static bool load_library(android_namespace_t* ns,
LoadTask* task,
ZipArchiveCache* zip_archive_cache,
LoadTaskList* load_tasks,
- int rtld_flags) {
+ int rtld_flags,
+ bool search_linked_namespaces) {
const char* name = task->get_name();
soinfo* needed_by = task->get_needed_by();
const android_dlextinfo* extinfo = task->get_extinfo();
@@ -1270,7 +1294,7 @@ static bool load_library(android_namespace_t* ns,
task->set_fd(extinfo->library_fd, false);
task->set_file_offset(file_offset);
- return load_library(ns, task, load_tasks, rtld_flags, realpath);
+ return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
}
// Open the file.
@@ -1283,12 +1307,28 @@ static bool load_library(android_namespace_t* ns,
task->set_fd(fd, true);
task->set_file_offset(file_offset);
- return load_library(ns, task, load_tasks, rtld_flags, realpath);
+ return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
+}
+
+static bool find_loaded_library_by_soname(android_namespace_t* ns,
+ const char* name,
+ soinfo** candidate) {
+ return !ns->soinfo_list().visit([&](soinfo* si) {
+ const char* soname = si->get_soname();
+ if (soname != nullptr && (strcmp(name, soname) == 0)) {
+ *candidate = si;
+ return false;
+ }
+
+ return true;
+ });
}
// Returns true if library was found and false otherwise
static bool find_loaded_library_by_soname(android_namespace_t* ns,
- const char* name, soinfo** candidate) {
+ const char* name,
+ bool search_linked_namespaces,
+ soinfo** candidate) {
*candidate = nullptr;
// Ignore filename with path.
@@ -1296,15 +1336,24 @@ static bool find_loaded_library_by_soname(android_namespace_t* ns,
return false;
}
- return !ns->soinfo_list().visit([&](soinfo* si) {
- const char* soname = si->get_soname();
- if (soname != nullptr && (strcmp(name, soname) == 0)) {
- *candidate = si;
- return false;
+ bool found = find_loaded_library_by_soname(ns, name, candidate);
+
+ if (!found && search_linked_namespaces) {
+ // if a library was not found - look into linked namespaces
+ for (auto& link : ns->linked_namespaces()) {
+ if (!link.is_accessible(name)) {
+ continue;
+ }
+
+ android_namespace_t* linked_ns = link.linked_namespace();
+
+ if (find_loaded_library_by_soname(linked_ns, name, candidate)) {
+ return true;
+ }
}
+ }
- return true;
- });
+ return found;
}
static bool find_library_in_linked_namespace(const android_namespace_link_t& namespace_link,
@@ -1316,7 +1365,7 @@ static bool find_library_in_linked_namespace(const android_namespace_link_t& nam
bool loaded = false;
std::string soname;
- if (find_loaded_library_by_soname(ns, task->get_name(), &candidate)) {
+ if (find_loaded_library_by_soname(ns, task->get_name(), false, &candidate)) {
loaded = true;
soname = candidate->get_soname();
} else {
@@ -1367,7 +1416,7 @@ static bool find_library_internal(android_namespace_t* ns,
bool search_linked_namespaces) {
soinfo* candidate;
- if (find_loaded_library_by_soname(ns, task->get_name(), &candidate)) {
+ if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {
task->set_soinfo(candidate);
return true;
}
@@ -1377,7 +1426,7 @@ static bool find_library_internal(android_namespace_t* ns,
TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",
task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
- if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags)) {
+ if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {
return true;
}