DO NOT MERGE: Merge Oreo MR1 into master

Exempt-From-Owner-Approval: Changes already landed internally
Change-Id: Ib379c20f06c4b22a16bc715b34ba39b87b5f10fd
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 7bf3a5b..abfd00f 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1163,6 +1163,27 @@
   return *candidate != nullptr;
 }
 
+static bool find_loaded_library_by_realpath(android_namespace_t* ns, const char* realpath,
+                                            bool search_linked_namespaces, soinfo** candidate) {
+  auto predicate = [&](soinfo* si) { return strcmp(realpath, si->get_realpath()) == 0; };
+
+  *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,
@@ -2015,12 +2036,18 @@
 
   const char* translated_name = name;
   if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
-    char translated_path[PATH_MAX];
-    if (realpath(translated_name, translated_path) != nullptr) {
-      asan_name_holder = std::string(kAsanLibDirPrefix) + translated_path;
+    char original_path[PATH_MAX];
+    if (realpath(name, original_path) != nullptr) {
+      asan_name_holder = std::string(kAsanLibDirPrefix) + original_path;
       if (file_exists(asan_name_holder.c_str())) {
-        translated_name = asan_name_holder.c_str();
-        PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+        soinfo* si = nullptr;
+        if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
+          PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
+                asan_name_holder.c_str());
+        } else {
+          PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+          translated_name = asan_name_holder.c_str();
+        }
       }
     }
   }
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 3f6da59..249d341 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1270,29 +1270,49 @@
 
   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
 
+  // create a parent namespace to use instead of the default namespace. This is
+  // to make this test be independent from the configuration of the default
+  // namespace.
+  android_namespace_t* ns_parent =
+          android_create_namespace("parent",
+                                   nullptr,
+                                   nullptr,
+                                   ANDROID_NAMESPACE_TYPE_REGULAR,
+                                   nullptr,
+                                   nullptr);
+  ASSERT_TRUE(ns_parent != nullptr) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_parent, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+  extinfo.library_namespace = ns_parent;
+
   const std::string lib_public_path = get_testlib_root() + "/public_namespace_libs/" + g_public_lib;
-  void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
+  void* handle_public = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle_public != nullptr) << dlerror();
 
   android_set_application_target_sdk_version(42U); // something > 23
 
   ASSERT_TRUE(android_init_anonymous_namespace(shared_libs.c_str(), nullptr)) << dlerror();
 
-  // preload this library to the default namespace to check if it
+  // preload this library to the parent namespace to check if it
   // is shared later on.
   void* handle_dlopened =
-          dlopen((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW);
+          android_dlopen_ext((get_testlib_root() + "/private_namespace_libs/libnstest_dlopened.so").c_str(), RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle_dlopened != nullptr) << dlerror();
 
+  // create two child namespaces of 'ns_parent'. One with regular, the other
+  // with isolated & shared.
   android_namespace_t* ns_not_isolated =
           android_create_namespace("private",
                                    nullptr,
                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
                                    ANDROID_NAMESPACE_TYPE_REGULAR,
                                    nullptr,
-                                   nullptr);
+                                   ns_parent);
   ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
-  ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, shared_libs.c_str())) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_not_isolated, ns_parent, g_public_lib)) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_not_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
 
   android_namespace_t* ns_isolated_shared =
           android_create_namespace("private_isolated_shared",
@@ -1300,23 +1320,22 @@
                                    (get_testlib_root() + "/private_namespace_libs").c_str(),
                                    ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_SHARED,
                                    nullptr,
-                                   nullptr);
+                                   ns_parent);
   ASSERT_TRUE(ns_isolated_shared != nullptr) << dlerror();
-  ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, shared_libs.c_str())) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, ns_parent, g_public_lib)) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_isolated_shared, nullptr, g_core_shared_libs.c_str())) << dlerror();
 
-  ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
+  ASSERT_TRUE(android_dlopen_ext(root_lib, RTLD_NOW, &extinfo) == nullptr);
   ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
 
   std::string lib_private_external_path =
       get_testlib_root() + "/private_namespace_libs_external/libnstest_private_external.so";
 
-  // Load lib_private_external_path to default namespace
+  // Load lib_private_external_path to the parent namespace
   // (it should remain invisible for the isolated namespaces after this)
-  void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
+  void* handle = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle != nullptr) << dlerror();
 
-  android_dlextinfo extinfo;
-  extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   extinfo.library_namespace = ns_not_isolated;
 
   void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);