linker: the global group is added to all built-in namespaces

With ld.config.txt, we now have multiple built-in namespaces other than
the default namespace. Libs (and their dependents) listed in LD_PRELOAD
must be visible to those additional namespaces as well.

This also adds a debugging only feature: path to the linker config file
can be customized via LD_CONFIG_FILE environment variable. This works
only for debuggable builds.

Bug: 38114603
Bug: 62815515
Test: 1. ./external/compiler-rt/lib/asan/scripts/asan_device_setup --lib
prebuilts/clang/host/linux-x86/clang-stable/lib64/clang/5.0/lib/linux
2. enable talkback shortcut
3. in the home screen, hold vol-up/down together
4. device does not reboots and talkback shortcut is toggled
Test: bionic-unit-tests and linker-unit-tests successful

Change-Id: I9a03591053f4a9caea82f0dcb23e7a3d324bb9bd
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 8e7a141..a212624 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -558,9 +558,10 @@
 
   static LoadTask* create(const char* name,
                           soinfo* needed_by,
+                          android_namespace_t* start_from,
                           std::unordered_map<const soinfo*, ElfReader>* readers_map) {
     LoadTask* ptr = TypeBasedAllocator<LoadTask>::alloc();
-    return new (ptr) LoadTask(name, needed_by, readers_map);
+    return new (ptr) LoadTask(name, needed_by, start_from, readers_map);
   }
 
   const char* get_name() const {
@@ -612,6 +613,11 @@
     is_dt_needed_ = is_dt_needed;
   }
 
+  // returns the namespace from where we need to start loading this.
+  const android_namespace_t* get_start_from() const {
+    return start_from_;
+  }
+
   const ElfReader& get_elf_reader() const {
     CHECK(si_ != nullptr);
     return (*elf_readers_map_)[si_];
@@ -650,10 +656,11 @@
  private:
   LoadTask(const char* name,
            soinfo* needed_by,
+           android_namespace_t* start_from,
            std::unordered_map<const soinfo*, ElfReader>* readers_map)
     : name_(name), needed_by_(needed_by), si_(nullptr),
       fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map),
-      is_dt_needed_(false) {}
+      is_dt_needed_(false), start_from_(start_from) {}
 
   ~LoadTask() {
     if (fd_ != -1 && close_fd_) {
@@ -672,6 +679,7 @@
   // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list)
   bool is_dt_needed_;
   // END OF WORKAROUND
+  const android_namespace_t* const start_from_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask);
 };
@@ -1041,7 +1049,7 @@
                         ZipArchiveCache* zip_archive_cache,
                         const char* name, soinfo *needed_by,
                         off64_t* file_offset, std::string* realpath) {
-  TRACE("[ opening %s ]", name);
+  TRACE("[ opening %s at namespace %s]", name, ns->get_name());
 
   // If the name contains a slash, we should attempt to open it directly and not search the paths.
   if (strchr(name, '/') != nullptr) {
@@ -1273,7 +1281,7 @@
   }
 
   for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
-    load_tasks->push_back(LoadTask::create(name, si, task->get_readers_map()));
+    load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
   });
 
   return true;
@@ -1368,8 +1376,7 @@
 }
 
 static bool find_library_in_linked_namespace(const android_namespace_link_t& namespace_link,
-                                             LoadTask* task,
-                                             int rtld_flags) {
+                                             LoadTask* task) {
   android_namespace_t* ns = namespace_link.linked_namespace();
 
   soinfo* candidate;
@@ -1394,29 +1401,10 @@
     return true;
   }
 
-  // try to load the library - once namespace boundary is crossed
-  // we need to load a library within separate load_group
-  // to avoid using symbols from foreign namespace while.
-  //
-  // All symbols during relocation should be resolved within a
-  // namespace to preserve library locality to a namespace.
-  const char* name = task->get_name();
-  if (find_libraries(ns,
-                     task->get_needed_by(),
-                     &name,
-                     1,
-                     &candidate,
-                     nullptr /* ld_preloads */,
-                     0 /* ld_preload_count*/,
-                     rtld_flags,
-                     nullptr /* extinfo*/,
-                     false /* add_as_children */,
-                     false /* search_linked_namespaces */)) {
-    task->set_soinfo(candidate);
-    return true;
-  }
-
-  return false;
+  // returning true with empty soinfo means that the library is okay to be
+  // loaded in the namespace buy has not yet been loaded there before.
+  task->set_soinfo(nullptr);
+  return true;
 }
 
 static bool find_library_internal(android_namespace_t* ns,
@@ -1445,9 +1433,24 @@
     // if a library was not found - look into linked namespaces
     for (auto& linked_namespace : ns->linked_namespaces()) {
       if (find_library_in_linked_namespace(linked_namespace,
-                                           task,
-                                           rtld_flags)) {
-        return true;
+                                           task)) {
+        if (task->get_soinfo() == nullptr) {
+          // try to load the library - once namespace boundary is crossed
+          // we need to load a library within separate load_group
+          // to avoid using symbols from foreign namespace while.
+          //
+          // However, actual linking is deferred until when the global group
+          // is fully identified and is applied to all namespaces.
+          // Otherwise, the libs in the linked namespace won't get symbols from
+          // the global group.
+          if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
+            return true;
+          }
+          // lib was not found in the namespace. Try next linked namespace.
+        } else {
+          // lib is already loaded
+          return true;
+        }
       }
     }
   }
@@ -1458,44 +1461,6 @@
 static void soinfo_unload(soinfo* si);
 static void soinfo_unload(soinfo* soinfos[], size_t count);
 
-// TODO: this is slightly unusual way to construct
-// the global group for relocation. Not every RTLD_GLOBAL
-// library is included in this group for backwards-compatibility
-// reasons.
-//
-// This group consists of the main executable, LD_PRELOADs
-// and libraries with the DF_1_GLOBAL flag set.
-static soinfo_list_t make_global_group(android_namespace_t* ns) {
-  soinfo_list_t global_group;
-  ns->soinfo_list().for_each([&](soinfo* si) {
-    if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
-      global_group.push_back(si);
-    }
-  });
-
-  return global_group;
-}
-
-// This function provides a list of libraries to be shared
-// by the namespace. For the default namespace this is the global
-// group (see make_global_group). For all others this is a group
-// of RTLD_GLOBAL libraries (which includes the global group from
-// the default namespace).
-static soinfo_list_t get_shared_group(android_namespace_t* ns) {
-  if (ns == &g_default_namespace) {
-    return make_global_group(ns);
-  }
-
-  soinfo_list_t shared_group;
-  ns->soinfo_list().for_each([&](soinfo* si) {
-    if ((si->get_rtld_flags() & RTLD_GLOBAL) != 0) {
-      shared_group.push_back(si);
-    }
-  });
-
-  return shared_group;
-}
-
 static void shuffle(std::vector<LoadTask*>* v) {
   for (size_t i = 0, size = v->size(); i < size; ++i) {
     size_t n = size - i;
@@ -1518,19 +1483,17 @@
                     int rtld_flags,
                     const android_dlextinfo* extinfo,
                     bool add_as_children,
-                    bool search_linked_namespaces) {
+                    bool search_linked_namespaces,
+                    std::unordered_map<const soinfo*, ElfReader>& readers_map,
+                    std::vector<android_namespace_t*>* namespaces) {
   // Step 0: prepare.
   LoadTaskList load_tasks;
-  std::unordered_map<const soinfo*, ElfReader> readers_map;
 
   for (size_t i = 0; i < library_names_count; ++i) {
     const char* name = library_names[i];
-    load_tasks.push_back(LoadTask::create(name, start_with, &readers_map));
+    load_tasks.push_back(LoadTask::create(name, start_with, ns, &readers_map));
   }
 
-  // Construct global_group.
-  soinfo_list_t global_group = make_global_group(ns);
-
   // If soinfos array is null allocate one on stack.
   // The array is needed in case of failure; for example
   // when library_names[] = {libone.so, libtwo.so} and libone.so
@@ -1570,7 +1533,12 @@
     task->set_extinfo(is_dt_needed ? nullptr : extinfo);
     task->set_dt_needed(is_dt_needed);
 
-    if (!find_library_internal(ns,
+    // try to find the load.
+    // Note: start from the namespace that is stored in the LoadTask. This namespace
+    // is different from the current namespace when the LoadTask is for a transitive
+    // dependency and the lib that created the LoadTask is not found in the
+    // current namespace but in one of the linked namespace.
+    if (!find_library_internal(const_cast<android_namespace_t*>(task->get_start_from()),
                                task,
                                &zip_archive_cache,
                                &load_tasks,
@@ -1629,18 +1597,61 @@
     }
   }
 
-  // Step 4: Add LD_PRELOADed libraries to the global group for
-  // future runs. There is no need to explicitly add them to
-  // the global group for this run because they are going to
-  // appear in the local group in the correct order.
+  // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
+  // determined at step 3.
+
+  // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
+  // must be added to the global group
   if (ld_preloads != nullptr) {
     for (auto&& si : *ld_preloads) {
       si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
     }
   }
 
+  // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
+  // run. These will be the new member of the global group
+  soinfo_list_t new_global_group_members;
+  for (auto&& task : load_tasks) {
+    soinfo* si = task->get_soinfo();
+    if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+      new_global_group_members.push_back(si);
+    }
+  }
 
-  // Step 5: link libraries.
+  // Step 4-3: Add the new global group members to all the linked namespaces
+  for (auto si : new_global_group_members) {
+    for (auto linked_ns : *namespaces) {
+      if (si->get_primary_namespace() != linked_ns) {
+        linked_ns->add_soinfo(si);
+        si->add_secondary_namespace(linked_ns);
+      }
+    }
+  }
+
+  // Step 5: link libraries that are not destined to this namespace.
+  // Do this by recursively calling find_libraries on the namespace where the lib
+  // was found during Step 1.
+  for (auto&& task : load_tasks) {
+    soinfo* si = task->get_soinfo();
+    if (si->get_primary_namespace() != ns) {
+      const char* name = task->get_name();
+      if (find_libraries(si->get_primary_namespace(), task->get_needed_by(), &name, 1,
+                         nullptr /* soinfos */, nullptr /* ld_preloads */, 0 /* ld_preload_count */,
+                         rtld_flags, nullptr /* extinfo */, false /* add_as_children */,
+                         false /* search_linked_namespaces */, readers_map, namespaces)) {
+        // If this lib is directly needed by one of the libs in this namespace,
+        // then increment the count
+        soinfo* needed_by = task->get_needed_by();
+        if (needed_by != nullptr && needed_by->get_primary_namespace() == ns && si->is_linked()) {
+          si->increment_ref_count();
+        }
+      } else {
+        return false;
+      }
+    }
+  }
+
+  // Step 6: link libraries in this namespace
   soinfo_list_t local_group;
   walk_dependencies_tree(
       (start_with != nullptr && add_as_children) ? &start_with : soinfos,
@@ -1654,6 +1665,7 @@
     }
   });
 
+  soinfo_list_t global_group = ns->get_global_group();
   bool linked = local_group.visit([&](soinfo* si) {
     if (!si->is_linked()) {
       if (!si->link_image(global_group, local_group, extinfo) ||
@@ -1684,6 +1696,9 @@
                             soinfo* needed_by) {
   soinfo* si;
 
+  // readers_map is shared across recursive calls to find_libraries.
+  // However, the map is not shared across different threads.
+  std::unordered_map<const soinfo*, ElfReader> readers_map;
   if (name == nullptr) {
     si = solist_get_somain();
   } else if (!find_libraries(ns,
@@ -1696,7 +1711,8 @@
                              rtld_flags,
                              extinfo,
                              false /* add_as_children */,
-                             true /* search_linked_namespaces */)) {
+                             true /* search_linked_namespaces */,
+                             readers_map)) {
     return nullptr;
   }
 
@@ -2208,7 +2224,7 @@
     }
   } else {
     // If not shared - copy only the shared group
-    add_soinfos_to_namespace(get_shared_group(parent_namespace), ns);
+    add_soinfos_to_namespace(parent_namespace->get_shared_group(), ns);
   }
 
   ns->set_ld_library_paths(std::move(ld_library_paths));
@@ -3413,7 +3429,7 @@
   return true;
 }
 
-static void init_default_namespace_no_config(bool is_asan) {
+static std::vector<android_namespace_t*> init_default_namespace_no_config(bool is_asan) {
   g_default_namespace.set_isolated(false);
   auto default_ld_paths = is_asan ? kAsanDefaultLdPaths : kDefaultLdPaths;
 
@@ -3428,9 +3444,13 @@
   }
 
   g_default_namespace.set_default_library_paths(std::move(ld_default_paths));
+
+  std::vector<android_namespace_t*> namespaces;
+  namespaces.push_back(&g_default_namespace);
+  return namespaces;
 }
 
-void init_default_namespace(const char* executable_path) {
+std::vector<android_namespace_t*> init_default_namespaces(const char* executable_path) {
   g_default_namespace.set_name("(default)");
 
   soinfo* somain = solist_get_somain();
@@ -3447,14 +3467,24 @@
 
   std::string error_msg;
 
-  if (!Config::read_binary_config(kLdConfigFilePath,
+  const char* config_file = kLdConfigFilePath;
+#ifdef USE_LD_CONFIG_FILE
+  // This is a debugging/testing only feature. Must not be available on
+  // production builds.
+  const char* ld_config_file = getenv("LD_CONFIG_FILE");
+  if (ld_config_file != nullptr && file_exists(ld_config_file)) {
+    config_file = ld_config_file;
+  }
+#endif
+
+  if (!Config::read_binary_config(config_file,
                                   executable_path,
                                   g_is_asan,
                                   &config,
                                   &error_msg)) {
     if (!error_msg.empty()) {
       DL_WARN("error reading config file \"%s\" for \"%s\" (will use default configuration): %s",
-              kLdConfigFilePath,
+              config_file,
               executable_path,
               error_msg.c_str());
     }
@@ -3462,8 +3492,7 @@
   }
 
   if (config == nullptr) {
-    init_default_namespace_no_config(g_is_asan);
-    return;
+    return init_default_namespace_no_config(g_is_asan);
   }
 
   const auto& namespace_configs = config->namespace_configs();
@@ -3514,10 +3543,17 @@
   soinfo* ld_android_so = solist_get_head();
   for (auto it : namespaces) {
     it.second->add_soinfo(ld_android_so);
-    // TODO (dimitry): somain and ld_preloads should probably be added to all of these namespaces too?
+    // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
   }
 
   set_application_target_sdk_version(config->target_sdk_version());
+
+  std::vector<android_namespace_t*> created_namespaces;
+  created_namespaces.reserve(namespaces.size());
+  for (auto kv : namespaces) {
+    created_namespaces.push_back(kv.second);
+  }
+  return created_namespaces;
 }
 
 // This function finds a namespace exported in ld.config.txt by its name.