Merge "Fix greylist exception to account for linked namespaces"
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 136c2b6..a3d1db2 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -132,9 +132,34 @@
return S_ISREG(s.st_mode);
}
+static std::string resolve_soname(const std::string& name) {
+ // We assume that soname equals to basename here
+
+ // TODO(dimitry): consider having honest absolute-path -> soname resolution
+ // note that since we might end up refusing to load this library because
+ // it is not in shared libs list we need to get the soname without actually loading
+ // the library.
+ //
+ // On the other hand there are several places where we already assume that
+ // soname == basename in particular for any not-loaded library mentioned
+ // in DT_NEEDED list.
+ return basename(name.c_str());
+}
+
+static bool maybe_accessible_via_namespace_links(android_namespace_t* ns, const char* name) {
+ std::string soname = resolve_soname(name);
+ for (auto& ns_link : ns->linked_namespaces()) {
+ if (ns_link.is_accessible(soname.c_str())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
// TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
// gradually remove libraries from this list until it is gone.
-static bool is_greylisted(const char* name, const soinfo* needed_by) {
+static bool is_greylisted(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
static const char* const kLibraryGreyList[] = {
"libandroid_runtime.so",
"libbinder.so",
@@ -160,10 +185,10 @@
}
// if the library needed by a system library - implicitly assume it
- // is greylisted
-
+ // is greylisted unless it is in the list of shared libraries for one or
+ // more linked namespaces
if (needed_by != nullptr && is_system_library(needed_by->get_realpath())) {
- return true;
+ return !maybe_accessible_via_namespace_links(ns, name);
}
// if this is an absolute path - make sure it points to /system/lib(64)
@@ -1048,7 +1073,7 @@
}
// TODO(dimitry): workaround for http://b/26394120 (the grey-list)
- if (fd == -1 && ns != &g_default_namespace && is_greylisted(name, needed_by)) {
+ if (fd == -1 && ns != &g_default_namespace && is_greylisted(ns, name, needed_by)) {
// try searching for it on default_namespace default_library_path
fd = open_library_on_paths(zip_archive_cache, name, file_offset,
g_default_namespace.get_default_library_paths(), realpath);
@@ -1144,7 +1169,7 @@
// TODO(dimitry) before O release: add a namespace attribute to have this enabled
// only for classloader-namespaces
const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
- if (is_greylisted(name, needed_by)) {
+ if (is_greylisted(ns, name, needed_by)) {
// print warning only if needed by non-system library
if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
const soinfo* needed_or_dlopened_by = task->get_needed_by();
@@ -1165,15 +1190,18 @@
DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"",
name, needed_or_dlopened_by, ns->get_name());
- PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
- " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
- " permitted_paths=\"%s\"]",
- name, realpath.c_str(),
- needed_or_dlopened_by,
- ns->get_name(),
- android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
- android::base::Join(ns->get_default_library_paths(), ':').c_str(),
- android::base::Join(ns->get_permitted_paths(), ':').c_str());
+ // do not print this if a library is in the list of shared libraries for linked namespaces
+ if (!maybe_accessible_via_namespace_links(ns, name)) {
+ PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
+ " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
+ " permitted_paths=\"%s\"]",
+ name, realpath.c_str(),
+ needed_or_dlopened_by,
+ ns->get_name(),
+ android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
+ android::base::Join(ns->get_default_library_paths(), ':').c_str(),
+ android::base::Join(ns->get_permitted_paths(), ':').c_str());
+ }
return false;
}
}
@@ -1275,21 +1303,6 @@
});
}
-static std::string resolve_soname(const std::string& name) {
- // We assume that soname equals to basename here
-
- // TODO(dimitry): consider having honest absolute-path -> soname resolution
- // note that since we might end up refusing to load this library because
- // it is not in shared libs list we need to get the soname without actually loading
- // the library.
- //
- // On the other hand there are several places where we already assume that
- // soname == basename in particular for any not-loaded library mentioned
- // in DT_NEEDED list.
- return basename(name.c_str());
-}
-
-
static bool find_library_in_linked_namespace(const android_namespace_link_t& namespace_link,
LoadTask* task,
int rtld_flags) {
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 17e1a48..808b708 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -917,12 +917,19 @@
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
extinfo.library_namespace = ns;
+ // An app targeting M can open libnativehelper.so because it's on the greylist.
android_set_application_target_sdk_version(__ANDROID_API_M__);
void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
ASSERT_TRUE(handle != nullptr) << dlerror();
+ // Check that loader did not load another copy of libdl.so while loading greylisted library.
+ void* dlsym_ptr = dlsym(handle, "dlsym");
+ ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
+ ASSERT_EQ(&dlsym, dlsym_ptr);
+
dlclose(handle);
+ // An app targeting N no longer has the greylist.
android_set_application_target_sdk_version(__ANDROID_API_N__);
handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
ASSERT_TRUE(handle == nullptr);
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 48fb6d1..0f24170 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -916,11 +916,6 @@
#endif
}
-#if defined(__LP64__)
-#define PATH_TO_SYSTEM_LIB "/system/lib64/"
-#else
-#define PATH_TO_SYSTEM_LIB "/system/lib/"
-#endif
#if defined (__aarch64__)
#define ALTERNATE_PATH_TO_SYSTEM_LIB "/system/lib/arm64/"
#elif defined (__arm__)
diff --git a/tests/utils.h b/tests/utils.h
index eac6f31..31974d0 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -32,6 +32,12 @@
#include "private/ScopeGuard.h"
+#if defined(__LP64__)
+#define PATH_TO_SYSTEM_LIB "/system/lib64/"
+#else
+#define PATH_TO_SYSTEM_LIB "/system/lib/"
+#endif
+
#if defined(__BIONIC__)
#define KNOWN_FAILURE_ON_BIONIC(x) xfail_ ## x
#else