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/tests/Android.bp b/tests/Android.bp
index c1e455d..1521b73 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -554,6 +554,10 @@
         "libnstest_root",
         "libnstest_public",
         "libnstest_public_internal",
+        "libnstest_ns_a_public1",
+        "libnstest_ns_a_public1_internal",
+        "libnstest_ns_b_public2",
+        "libnstest_ns_b_public3",
     ],
 }
 
diff --git a/tests/dlext_private.h b/tests/dlext_private.h
index dea92ee..2621a68 100644
--- a/tests/dlext_private.h
+++ b/tests/dlext_private.h
@@ -95,6 +95,9 @@
                                     android_namespace_t* to,
                                     const char* shared_libs_sonames);
 
+extern bool android_link_namespaces_all_libs(android_namespace_t* from,
+                                             android_namespace_t* to);
+
 extern void android_set_application_target_sdk_version(uint32_t target);
 
 __END_DECLS
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 64cfa08..bb2d8a3 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1737,6 +1737,123 @@
   ASSERT_EQ(expected_dlerror, dlerror());
 }
 
+TEST(dlext, ns_link_namespaces_invalid_arguments) {
+  ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
+
+  android_namespace_t* ns =
+          android_create_namespace("private",
+                                   nullptr,
+                                   (get_testlib_root() + "/private_namespace_libs").c_str(),
+                                   ANDROID_NAMESPACE_TYPE_REGULAR,
+                                   nullptr,
+                                   nullptr);
+  ASSERT_TRUE(ns != nullptr) << dlerror();
+
+  // Test android_link_namespaces()
+  ASSERT_FALSE(android_link_namespaces(nullptr, nullptr, "libc.so"));
+  ASSERT_STREQ("android_link_namespaces failed: error linking namespaces: namespace_from is null.",
+               dlerror());
+
+  ASSERT_FALSE(android_link_namespaces(ns, nullptr, nullptr));
+  ASSERT_STREQ("android_link_namespaces failed: "
+               "error linking namespaces \"private\"->\"(default)\": "
+               "the list of shared libraries is empty.", dlerror());
+
+  ASSERT_FALSE(android_link_namespaces(ns, nullptr, ""));
+  ASSERT_STREQ("android_link_namespaces failed: "
+               "error linking namespaces \"private\"->\"(default)\": "
+               "the list of shared libraries is empty.", dlerror());
+
+  // Test android_link_namespaces_all_libs()
+  ASSERT_FALSE(android_link_namespaces_all_libs(nullptr, nullptr));
+  ASSERT_STREQ("android_link_namespaces_all_libs failed: "
+               "error linking namespaces: namespace_from is null.", dlerror());
+
+  ASSERT_FALSE(android_link_namespaces_all_libs(nullptr, ns));
+  ASSERT_STREQ("android_link_namespaces_all_libs failed: "
+               "error linking namespaces: namespace_from is null.", dlerror());
+
+  ASSERT_FALSE(android_link_namespaces_all_libs(ns, nullptr));
+  ASSERT_STREQ("android_link_namespaces_all_libs failed: "
+               "error linking namespaces: namespace_to is null.", dlerror());
+}
+
+TEST(dlext, ns_allow_all_shared_libs) {
+  ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
+
+  android_namespace_t* ns_a =
+          android_create_namespace("ns_a",
+                                   nullptr,
+                                   (get_testlib_root() + "/ns_a").c_str(),
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                   nullptr,
+                                   nullptr);
+  ASSERT_TRUE(ns_a != nullptr) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+  android_namespace_t* ns_b =
+          android_create_namespace("ns_b",
+                                   nullptr,
+                                   (get_testlib_root() + "/ns_b").c_str(),
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                   nullptr,
+                                   nullptr);
+  ASSERT_TRUE(ns_b != nullptr) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+  ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
+  ASSERT_TRUE(android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
+
+  // Load libs with android_dlopen_ext() from namespace b
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+  extinfo.library_namespace = ns_b;
+
+  void* ns_b_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_b_handle1 != nullptr) << dlerror();
+
+  void* ns_b_handle1_internal =
+      android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_b_handle1_internal == nullptr);
+
+  void* ns_b_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_b_handle2 != nullptr) << dlerror();
+
+  void* ns_b_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_b_handle3 != nullptr) << dlerror();
+
+  // Load libs with android_dlopen_ext() from namespace a
+  extinfo.library_namespace = ns_a;
+
+  void* ns_a_handle1 = android_dlopen_ext("libnstest_ns_a_public1.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_a_handle1 != nullptr) << dlerror();
+
+  void* ns_a_handle1_internal =
+      android_dlopen_ext("libnstest_ns_a_public1_internal.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_a_handle1_internal != nullptr) << dlerror();
+
+  void* ns_a_handle2 = android_dlopen_ext("libnstest_ns_b_public2.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_a_handle2 != nullptr) << dlerror();
+
+  void* ns_a_handle3 = android_dlopen_ext("libnstest_ns_b_public3.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(ns_a_handle3 != nullptr) << dlerror();
+
+  // Compare the dlopen handle
+  ASSERT_EQ(ns_b_handle1, ns_a_handle1);
+  ASSERT_EQ(ns_b_handle2, ns_a_handle2);
+  ASSERT_EQ(ns_b_handle3, ns_a_handle3);
+
+  // Close libs
+  dlclose(ns_b_handle1);
+  dlclose(ns_b_handle2);
+  dlclose(ns_b_handle3);
+
+  dlclose(ns_a_handle1);
+  dlclose(ns_a_handle1_internal);
+  dlclose(ns_a_handle2);
+  dlclose(ns_a_handle3);
+}
+
 TEST(dlext, ns_anonymous) {
   static const char* root_lib = "libnstest_root.so";
   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 61a837f..cae30b5 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -259,6 +259,58 @@
 }
 
 // -----------------------------------------------------------------------------
+// Build test helper libraries for linker namespaces for allow all shared libs
+//
+// This set of libraries is used to verify linker namespaces for allow all
+// shared libs.
+//
+// Test cases
+// 1. Check that namespace a exposes libnstest_ns_a_public1 to
+//    namespace b while keeping libnstest_ns_a_public1_internal as an
+//    internal lib.
+// 2. Check that namespace b exposes all libraries to namespace a.
+//
+// Dependency tree (visibility)
+// libnstest_ns_b_public2.so  (ns:b)
+// +-> libnstest_ns_a_public1.so  (ns:a)
+//     +-> libnstest_ns_a_public2_internal.so  (ns:a)
+//     +-> libnstest_ns_b_public3.so  (ns:b)
+//
+// -----------------------------------------------------------------------------
+cc_test_library {
+    name: "libnstest_ns_a_public1",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["libnstest_ns_a_public1.cpp"],
+    relative_install_path: "bionic-loader-test-libs/ns_a",
+    shared_libs: [
+        "libnstest_ns_a_public1_internal",
+        "libnstest_ns_b_public3",
+    ],
+}
+
+cc_test_library {
+    name: "libnstest_ns_a_public1_internal",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["libnstest_ns_a_public1_internal.cpp"],
+    relative_install_path: "bionic-loader-test-libs/ns_a",
+}
+
+cc_test_library {
+    name: "libnstest_ns_b_public2",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["libnstest_ns_b_public2.cpp"],
+    relative_install_path: "bionic-loader-test-libs/ns_b",
+    shared_libs: ["libnstest_ns_a_public1"],
+}
+
+cc_test_library {
+    name: "libnstest_ns_b_public3",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["libnstest_ns_b_public3.cpp"],
+    relative_install_path: "bionic-loader-test-libs/ns_b",
+}
+
+// -----------------------------------------------------------------------------
 // Build DT_RUNPATH test helper libraries
 // -----------------------------------------------------------------------------
 // include $(LOCAL_PATH)/Android.build.dt_runpath.mk
diff --git a/tests/libs/libnstest_ns_a_public1.cpp b/tests/libs/libnstest_ns_a_public1.cpp
new file mode 100644
index 0000000..c095e60
--- /dev/null
+++ b/tests/libs/libnstest_ns_a_public1.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static const char ns_a_public1_string[] = "libnstest_ns_a_public1.so";
+
+extern "C" const char* get_ns_a_public1_string() {
+  return ns_a_public1_string;
+}
+
+
+extern "C" const char *get_ns_a_public1_internal_string();
+
+extern "C" const char *delegate_get_ns_a_public1_internal_string() {
+  return get_ns_a_public1_internal_string();
+}
+
+
+extern "C" const char *get_ns_b_public3_string();
+
+extern "C" const char *delegate_get_ns_b_public3_string() {
+  return get_ns_b_public3_string();
+}
diff --git a/tests/libs/libnstest_ns_a_public1_internal.cpp b/tests/libs/libnstest_ns_a_public1_internal.cpp
new file mode 100644
index 0000000..6529936
--- /dev/null
+++ b/tests/libs/libnstest_ns_a_public1_internal.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static const char ns_a_public1_internal_string[] = "libnstest_ns_a_public1_internal.so";
+
+extern "C" const char* get_ns_a_public1_internal_string() {
+  return ns_a_public1_internal_string;
+}
diff --git a/tests/libs/libnstest_ns_b_public2.cpp b/tests/libs/libnstest_ns_b_public2.cpp
new file mode 100644
index 0000000..6251a8d
--- /dev/null
+++ b/tests/libs/libnstest_ns_b_public2.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static const char ns_b_public2_string[] = "libnstest_ns_b_public2.so";
+
+extern "C" const char* get_ns_b_public2_string() {
+  return ns_b_public2_string;
+}
+
+
+extern "C" const char* get_ns_a_public1_string();
+
+extern "C" const char* delegate_get_ns_a_public1_string() {
+  return get_ns_a_public1_string();
+}
diff --git a/tests/libs/libnstest_ns_b_public3.cpp b/tests/libs/libnstest_ns_b_public3.cpp
new file mode 100644
index 0000000..b332445
--- /dev/null
+++ b/tests/libs/libnstest_ns_b_public3.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static const char ns_b_public3_string[] = "libnstest_ns_b_public3.so";
+
+extern "C" const char* get_ns_b_public3_string() {
+  return ns_b_public3_string;
+}