linker: Allow link namespaces without name filters

This commit allows users to create a link without soname filters between
two linker namespaces.

The motivation is to establish one-way shared library isolation.  For
example, assume that there are two linker namespaces `default` and
`vndk`.  We would like to limit the shared libraries that can be used by
the `default` namespace.  In the meanwhile, we would like to allow the
`vndk` namespace to use shared libs from the `default` namespace if the
soname cannot be find in the search path or loaded sonames of the `vndk`
namespace.

          shared_libs  = %VNDK_CORE_LIBRARIES%
          shared_libs += %VNDK_SAMEPROCESS_LIBRARIES%
    vndk <-------------------------------------------- default
       \_______________________________________________/^
                allow_all_shared_libs = true

android_link_namespaces_all_libs() is added to libdl, but it is
versioned as LIBC_PRIVATE.  android_link_namespaces_all_libs() is only
for unit tests.

Bug: 69824336

Test: adb shell /data/nativetest/linker-unit-tests/linker-unit-tests32
Test: adb shell /data/nativetest64/linker-unit-tests/linker-unit-tests64

Test: adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
Test: adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests

Test: Update /system/etc/ld.config*.txt and check whether the vndk
linker namespace of the vendor process can access the shared libs from
the default linker namespace.

Change-Id: I2879f0c5f5af60c7e56f8f743ebd2872e552286b
diff --git a/linker/tests/linker_config_test.cpp b/linker/tests/linker_config_test.cpp
index 4c0dcdd..e716879 100644
--- a/linker/tests/linker_config_test.cpp
+++ b/linker/tests/linker_config_test.cpp
@@ -81,6 +81,8 @@
   "namespace.vndk.search.paths = /system/${LIB}/vndk\n"
   "namespace.vndk.asan.search.paths = /data\n"
   "namespace.vndk.asan.search.paths += /system/${LIB}/vndk\n"
+  "namespace.vndk.links = default\n"
+  "namespace.vndk.link.default.allow_all_shared_libs = true\n"
   "\n";
 
 static bool write_version(const std::string& path, uint32_t version) {
@@ -154,10 +156,14 @@
 
   const auto& default_ns_links = default_ns_config->links();
   ASSERT_EQ(2U, default_ns_links.size());
+
   ASSERT_EQ("system", default_ns_links[0].ns_name());
   ASSERT_EQ("libc.so:libm.so:libdl.so:libstdc++.so", default_ns_links[0].shared_libs());
+  ASSERT_FALSE(default_ns_links[0].allow_all_shared_libs());
+
   ASSERT_EQ("vndk", default_ns_links[1].ns_name());
   ASSERT_EQ("libcutils.so:libbase.so", default_ns_links[1].shared_libs());
+  ASSERT_FALSE(default_ns_links[1].allow_all_shared_libs());
 
   auto& ns_configs = config->namespace_configs();
   ASSERT_EQ(3U, ns_configs.size());
@@ -187,8 +193,13 @@
   ASSERT_TRUE(ns_vndk != nullptr) << "vndk namespace was not found";
 
   ASSERT_FALSE(ns_vndk->isolated()); // malformed bool property
-  ASSERT_FALSE(ns_vndk->visible()); // undefined bool property 
+  ASSERT_FALSE(ns_vndk->visible()); // undefined bool property
   ASSERT_EQ(kExpectedVndkSearchPath, ns_vndk->search_paths());
+
+  const auto& ns_vndk_links = ns_vndk->links();
+  ASSERT_EQ(1U, ns_vndk_links.size());
+  ASSERT_EQ("default", ns_vndk_links[0].ns_name());
+  ASSERT_TRUE(ns_vndk_links[0].allow_all_shared_libs());
 }
 
 TEST(linker_config, smoke) {
@@ -198,3 +209,40 @@
 TEST(linker_config, asan_smoke) {
   run_linker_config_smoke_test(true);
 }
+
+TEST(linker_config, ns_link_shared_libs_invalid_settings) {
+  // This unit test ensures an error is emitted when a namespace link in ld.config.txt specifies
+  // both shared_libs and allow_all_shared_libs.
+
+  static const char config_str[] =
+    "dir.test = /data/local/tmp\n"
+    "\n"
+    "[test]\n"
+    "additional.namespaces = system\n"
+    "namespace.default.links = system\n"
+    "namespace.default.link.system.shared_libs = libc.so:libm.so\n"
+    "namespace.default.link.system.allow_all_shared_libs = true\n"
+    "\n";
+
+  TemporaryFile tmp_file;
+  close(tmp_file.fd);
+  tmp_file.fd = -1;
+
+  android::base::WriteStringToFile(config_str, tmp_file.path);
+
+  TemporaryDir tmp_dir;
+
+  std::string executable_path = std::string(tmp_dir.path) + "/some-binary";
+
+  const Config* config = nullptr;
+  std::string error_msg;
+  ASSERT_FALSE(Config::read_binary_config(tmp_file.path,
+                                          executable_path.c_str(),
+                                          false,
+                                          &config,
+                                          &error_msg));
+  ASSERT_TRUE(config == nullptr);
+  ASSERT_EQ(std::string(tmp_file.path) + ":6: "
+            "error: both shared_libs and allow_all_shared_libs are set for default->system link.",
+            error_msg);
+}