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/linker.cpp b/linker/linker.cpp
index 05efc55..0b8d5ee 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1430,7 +1430,7 @@
}
// 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.
+ // loaded in the namespace but has not yet been loaded there before.
task->set_soinfo(nullptr);
return true;
}
@@ -2363,7 +2363,8 @@
add_soinfos_to_namespace(parent_namespace->soinfo_list(), ns);
// and copy parent namespace links
for (auto& link : parent_namespace->linked_namespaces()) {
- ns->add_linked_namespace(link.linked_namespace(), link.shared_lib_sonames());
+ ns->add_linked_namespace(link.linked_namespace(), link.shared_lib_sonames(),
+ link.allow_all_shared_libs());
}
} else {
// If not shared - copy only the shared group
@@ -2399,7 +2400,25 @@
std::unordered_set<std::string> sonames_set(sonames.begin(), sonames.end());
ProtectedDataGuard guard;
- namespace_from->add_linked_namespace(namespace_to, sonames_set);
+ namespace_from->add_linked_namespace(namespace_to, sonames_set, false);
+
+ return true;
+}
+
+bool link_namespaces_all_libs(android_namespace_t* namespace_from,
+ android_namespace_t* namespace_to) {
+ if (namespace_from == nullptr) {
+ DL_ERR("error linking namespaces: namespace_from is null.");
+ return false;
+ }
+
+ if (namespace_to == nullptr) {
+ DL_ERR("error linking namespaces: namespace_to is null.");
+ return false;
+ }
+
+ ProtectedDataGuard guard;
+ namespace_from->add_linked_namespace(namespace_to, std::unordered_set<std::string>(), true);
return true;
}
@@ -3763,7 +3782,11 @@
auto it_to = namespaces.find(ns_link.ns_name());
CHECK(it_to != namespaces.end());
android_namespace_t* namespace_to = it_to->second;
- link_namespaces(namespace_from, namespace_to, ns_link.shared_libs().c_str());
+ if (ns_link.allow_all_shared_libs()) {
+ link_namespaces_all_libs(namespace_from, namespace_to);
+ } else {
+ link_namespaces(namespace_from, namespace_to, ns_link.shared_libs().c_str());
+ }
}
}
// we can no longer rely on the fact that libdl.so is part of default namespace