summaryrefslogtreecommitdiff
path: root/libnativeloader/library_namespaces.cpp
diff options
context:
space:
mode:
author Martin Stjernholm <mast@google.com> 2024-01-30 21:33:09 +0000
committer Martin Stjernholm <mast@google.com> 2024-02-15 18:22:04 +0000
commit8a9b51e34f3769a5e3ea3a4383e3f00489088738 (patch)
tree37b3705e0387d216b50bc2d1e027b1f8ccf5f914 /libnativeloader/library_namespaces.cpp
parent149b912110c31a2e1e69930e48fed8bbfbe04700 (diff)
Refactorings to make more logic available at the top level in
native_loader.cpp. - Make the code that determines the partition from the dex path available to code in native_loader.cpp, and rename it since it'll be applied to arbitrary paths, not just APK's. - Move the linker namespace constants to a header file. - Various other minor code cleanups. To prepare for a later CL that needs to access these things from OpenNativeLibrary. No functional changes. Test: atest libnativeloader_e2e_tests libnativeloader_test Bug: 237577392 Change-Id: Ifc762bf6d4664b2d477c4ed3af58f149fb4c1189
Diffstat (limited to 'libnativeloader/library_namespaces.cpp')
-rw-r--r--libnativeloader/library_namespaces.cpp183
1 files changed, 84 insertions, 99 deletions
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp
index 1e29f4e457..683e76247f 100644
--- a/libnativeloader/library_namespaces.cpp
+++ b/libnativeloader/library_namespaces.cpp
@@ -16,6 +16,8 @@
#if defined(ART_TARGET_ANDROID)
+#define LOG_TAG "nativeloader"
+
#include "library_namespaces.h"
#include <dirent.h>
@@ -25,14 +27,13 @@
#include <string>
#include <vector>
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/result.h>
-#include <android-base/strings.h>
-#include <android-base/stringprintf.h>
-#include <nativehelper/scoped_utf_chars.h>
-
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/macros.h"
+#include "android-base/result.h"
+#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+#include "nativehelper/scoped_utf_chars.h"
#include "nativeloader/dlext_namespaces.h"
#include "public_libraries.h"
#include "utils.h"
@@ -43,19 +44,6 @@ namespace {
constexpr const char* kApexPath = "/apex/";
-// The device may be configured to have the vendor libraries loaded to a separate namespace.
-// For historical reasons this namespace was named sphal but effectively it is intended
-// to use to load vendor libraries to separate namespace with controlled interface between
-// vendor and system namespaces.
-constexpr const char* kVendorNamespaceName = "sphal";
-// Similar to sphal namespace, product namespace provides some product libraries.
-constexpr const char* kProductNamespaceName = "product";
-
-// vndk namespace for unbundled vendor apps
-constexpr const char* kVndkNamespaceName = "vndk";
-// vndk_product namespace for unbundled product apps
-constexpr const char* kVndkProductNamespaceName = "vndk_product";
-
// clns-XX is a linker namespace that is created for normal apps installed in
// the data partition. To be specific, it is created for the app classloader.
// When System.load() is called from a Java class that is loaded from the
@@ -89,15 +77,8 @@ constexpr const char* kVendorLibPath = "/vendor/" LIB;
// a symlink to the other.
constexpr const char* kProductLibPath = "/product/" LIB ":/system/product/" LIB;
-const std::regex kVendorDexPathRegex("(^|:)(/system)?/vendor/");
-const std::regex kProductDexPathRegex("(^|:)(/system)?/product/");
-
-// Define origin partition of APK
-using ApkOrigin = enum {
- APK_ORIGIN_DEFAULT = 0,
- APK_ORIGIN_VENDOR = 1, // Includes both /vendor and /system/vendor
- APK_ORIGIN_PRODUCT = 2, // Includes both /product and /system/product
-};
+const std::regex kVendorPathRegex("(^|:)(/system)?/vendor/");
+const std::regex kProductPathRegex("(^|:)(/system)?/product/");
jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
@@ -107,23 +88,22 @@ jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
return env->CallObjectMethod(class_loader, get_parent);
}
-ApkOrigin GetApkOriginFromDexPath(const std::string& dex_path) {
- ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;
- if (std::regex_search(dex_path, kVendorDexPathRegex)) {
- apk_origin = APK_ORIGIN_VENDOR;
- }
- if (std::regex_search(dex_path, kProductDexPathRegex)) {
- LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
- "Dex path contains both vendor and product partition : %s",
- dex_path.c_str());
+} // namespace
- apk_origin = APK_ORIGIN_PRODUCT;
+ApiDomain GetApiDomainFromPath(const std::string& path) {
+ ApiDomain api_domain = API_DOMAIN_DEFAULT;
+ if (std::regex_search(path, kVendorPathRegex)) {
+ api_domain = API_DOMAIN_VENDOR;
}
- return apk_origin;
+ if (is_product_treblelized() && std::regex_search(path, kProductPathRegex)) {
+ LOG_ALWAYS_FATAL_IF(api_domain == API_DOMAIN_VENDOR,
+ "Path matches both vendor and product partitions: %s",
+ path.c_str());
+ api_domain = API_DOMAIN_PRODUCT;
+ }
+ return api_domain;
}
-} // namespace
-
void LibraryNamespaces::Initialize() {
// Once public namespace is initialized there is no
// point in running this code - it will have no effect
@@ -170,7 +150,7 @@ static const std::string filter_public_libraries(
}
std::vector<std::string> filtered;
std::vector<std::string> orig = android::base::Split(public_libraries, ":");
- for (const auto& lib : uses_libraries) {
+ for (const std::string& lib : uses_libraries) {
if (std::find(orig.begin(), orig.end(), lib) != orig.end()) {
filtered.emplace_back(lib);
}
@@ -178,32 +158,29 @@ static const std::string filter_public_libraries(
return android::base::Join(filtered, ":");
}
-Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version,
- jobject class_loader, bool is_shared,
- jstring dex_path_j,
- jstring java_library_path,
- jstring java_permitted_path,
- jstring uses_library_list) {
+Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env,
+ uint32_t target_sdk_version,
+ jobject class_loader,
+ ApiDomain api_domain,
+ bool is_shared,
+ const std::string& dex_path,
+ jstring library_path_j,
+ jstring permitted_path_j,
+ jstring uses_library_list_j) {
std::string library_path; // empty string by default.
- std::string dex_path;
- if (java_library_path != nullptr) {
- ScopedUtfChars library_path_utf_chars(env, java_library_path);
+ if (library_path_j != nullptr) {
+ ScopedUtfChars library_path_utf_chars(env, library_path_j);
library_path = library_path_utf_chars.c_str();
}
- if (dex_path_j != nullptr) {
- ScopedUtfChars dex_path_chars(env, dex_path_j);
- dex_path = dex_path_chars.c_str();
- }
-
std::vector<std::string> uses_libraries;
- if (uses_library_list != nullptr) {
- ScopedUtfChars names(env, uses_library_list);
+ if (uses_library_list_j != nullptr) {
+ ScopedUtfChars names(env, uses_library_list_j);
uses_libraries = android::base::Split(names.c_str(), ":");
} else {
- // uses_library_list could be nullptr when System.loadLibrary is called from a
- // custom classloader. In that case, we don't know the list of public
+ // uses_library_list_j could be nullptr when System.loadLibrary is called
+ // from a custom classloader. In that case, we don't know the list of public
// libraries because we don't know which apk the classloader is for. Only
// choices we can have are 1) allowing all public libs (as before), or 2)
// not allowing all but NDK libs. Here we take #1 because #2 would surprise
@@ -214,8 +191,6 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
uses_libraries.emplace_back(LIBRARY_ALL);
}
- ApkOrigin apk_origin = GetApkOriginFromDexPath(dex_path);
-
// (http://b/27588281) This is a workaround for apps using custom
// classloaders and calling System.load() with an absolute path which
// is outside of the classloader library search path.
@@ -224,8 +199,8 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
// under /data and /mnt/expand
std::string permitted_path = kAlwaysPermittedDirectories;
- if (java_permitted_path != nullptr) {
- ScopedUtfChars path(env, java_permitted_path);
+ if (permitted_path_j != nullptr) {
+ ScopedUtfChars path(env, permitted_path_j);
if (path.c_str() != nullptr && path.size() > 0) {
permitted_path = permitted_path + ":" + path.c_str();
}
@@ -236,13 +211,13 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
std::string system_exposed_libraries = default_public_libraries();
std::string namespace_name = kClassloaderNamespaceName;
- ApkOrigin unbundled_app_origin = APK_ORIGIN_DEFAULT;
- const char* apk_origin_msg = "other apk"; // Only for debug logging.
+ ApiDomain unbundled_app_domain = API_DOMAIN_DEFAULT;
+ const char* api_domain_msg = "other apk"; // Only for debug logging.
if (!is_shared) {
- if (apk_origin == APK_ORIGIN_VENDOR) {
- unbundled_app_origin = APK_ORIGIN_VENDOR;
- apk_origin_msg = "unbundled vendor apk";
+ if (api_domain == API_DOMAIN_VENDOR) {
+ unbundled_app_domain = API_DOMAIN_VENDOR;
+ api_domain_msg = "unbundled vendor apk";
// For vendor apks, give access to the vendor libs even though they are
// treated as unbundled; the libs and apks are still bundled together in the
@@ -255,9 +230,9 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
// Different name is useful for debugging
namespace_name = kVendorClassloaderNamespaceName;
- } else if (apk_origin == APK_ORIGIN_PRODUCT && is_product_treblelized()) {
- unbundled_app_origin = APK_ORIGIN_PRODUCT;
- apk_origin_msg = "unbundled product apk";
+ } else if (api_domain == API_DOMAIN_PRODUCT) {
+ unbundled_app_domain = API_DOMAIN_PRODUCT;
+ api_domain_msg = "unbundled product apk";
// Like for vendor apks, give access to the product libs since they are
// bundled together in the same partition.
@@ -287,20 +262,20 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
"Configuring %s for %s %s. target_sdk_version=%u, uses_libraries=%s, library_path=%s, "
"permitted_path=%s",
namespace_name.c_str(),
- apk_origin_msg,
+ api_domain_msg,
dex_path.c_str(),
static_cast<unsigned>(target_sdk_version),
android::base::Join(uses_libraries, ':').c_str(),
library_path.c_str(),
permitted_path.c_str());
- if (unbundled_app_origin != APK_ORIGIN_VENDOR) {
+ if (unbundled_app_domain != API_DOMAIN_VENDOR) {
// Extended public libraries are NOT available to unbundled vendor apks, but
// they are to other apps, including those in system, system_ext, and
// product partitions. The reason is that when GSI is used, the system
// partition may get replaced, and then vendor apps may fail. It's fine for
// product apps, because that partition isn't mounted in GSI tests.
- auto libs =
+ const std::string libs =
filter_public_libraries(target_sdk_version, uses_libraries, extended_public_libraries());
if (!libs.empty()) {
ALOGD("Extending system_exposed_libraries: %s", libs.c_str());
@@ -320,27 +295,33 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
bool also_used_as_anonymous = is_main_classloader;
// Note: this function is executed with g_namespaces_mutex held, thus no
// racing here.
- auto app_ns = NativeLoaderNamespace::Create(
- namespace_name, library_path, permitted_path, parent_ns, is_shared,
- target_sdk_version < 24 /* is_exempt_list_enabled */, also_used_as_anonymous);
+ Result<NativeLoaderNamespace> app_ns =
+ NativeLoaderNamespace::Create(namespace_name,
+ library_path,
+ permitted_path,
+ parent_ns,
+ is_shared,
+ target_sdk_version < 24 /* is_exempt_list_enabled */,
+ also_used_as_anonymous);
if (!app_ns.ok()) {
return app_ns.error();
}
// ... and link to other namespaces to allow access to some public libraries
bool is_bridged = app_ns->IsBridged();
- auto system_ns = NativeLoaderNamespace::GetSystemNamespace(is_bridged);
+ Result<NativeLoaderNamespace> system_ns = NativeLoaderNamespace::GetSystemNamespace(is_bridged);
if (!system_ns.ok()) {
return system_ns.error();
}
- auto linked = app_ns->Link(&system_ns.value(), system_exposed_libraries);
+ Result<void> linked = app_ns->Link(&system_ns.value(), system_exposed_libraries);
if (!linked.ok()) {
return linked.error();
}
for (const auto&[apex_ns_name, public_libs] : apex_public_libraries()) {
- auto ns = NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged);
+ Result<NativeLoaderNamespace> ns =
+ NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged);
// Even if APEX namespace is visible, it may not be available to bridged.
if (ns.ok()) {
linked = app_ns->Link(&ns.value(), public_libs);
@@ -351,8 +332,9 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
}
// Give access to VNDK-SP libraries from the 'vndk' namespace for unbundled vendor apps.
- if (unbundled_app_origin == APK_ORIGIN_VENDOR && !vndksp_libraries_vendor().empty()) {
- auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
+ if (unbundled_app_domain == API_DOMAIN_VENDOR && !vndksp_libraries_vendor().empty()) {
+ Result<NativeLoaderNamespace> vndk_ns =
+ NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged);
if (vndk_ns.ok()) {
linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_vendor());
if (!linked.ok()) {
@@ -362,8 +344,9 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
}
// Give access to VNDK-SP libraries from the 'vndk_product' namespace for unbundled product apps.
- if (unbundled_app_origin == APK_ORIGIN_PRODUCT && !vndksp_libraries_product().empty()) {
- auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged);
+ if (unbundled_app_domain == API_DOMAIN_PRODUCT && !vndksp_libraries_product().empty()) {
+ Result<NativeLoaderNamespace> vndk_ns =
+ NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged);
if (vndk_ns.ok()) {
linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_product());
if (!linked.ok()) {
@@ -373,11 +356,12 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
}
for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) {
- auto apex_ns_name = FindApexNamespaceName(each_jar_path);
+ Result<std::string> apex_ns_name = FindApexNamespaceName(each_jar_path);
if (apex_ns_name.ok()) {
- const auto& jni_libs = apex_jni_libraries(*apex_ns_name);
+ const std::string& jni_libs = apex_jni_libraries(*apex_ns_name);
if (jni_libs != "") {
- auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
+ Result<NativeLoaderNamespace> apex_ns =
+ NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged);
if (apex_ns.ok()) {
linked = app_ns->Link(&apex_ns.value(), jni_libs);
if (!linked.ok()) {
@@ -388,12 +372,13 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
}
}
- auto vendor_libs = filter_public_libraries(target_sdk_version, uses_libraries,
- vendor_public_libraries());
+ const std::string vendor_libs =
+ filter_public_libraries(target_sdk_version, uses_libraries, vendor_public_libraries());
if (!vendor_libs.empty()) {
- auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
+ Result<NativeLoaderNamespace> vendor_ns =
+ NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged);
// when vendor_ns is not configured, link to the system namespace
- auto target_ns = vendor_ns.ok() ? vendor_ns : system_ns;
+ Result<NativeLoaderNamespace> target_ns = vendor_ns.ok() ? vendor_ns : system_ns;
if (target_ns.ok()) {
linked = app_ns->Link(&target_ns.value(), vendor_libs);
if (!linked.ok()) {
@@ -402,10 +387,10 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
}
}
- auto product_libs = filter_public_libraries(target_sdk_version, uses_libraries,
- product_public_libraries());
+ const std::string product_libs =
+ filter_public_libraries(target_sdk_version, uses_libraries, product_public_libraries());
if (!product_libs.empty()) {
- auto target_ns = system_ns;
+ Result<NativeLoaderNamespace> target_ns = system_ns;
if (is_product_treblelized()) {
target_ns = NativeLoaderNamespace::GetExportedNamespace(kProductNamespaceName, is_bridged);
}
@@ -422,8 +407,8 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
}
}
- auto& emplaced = namespaces_.emplace_back(
- std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
+ std::pair<jweak, NativeLoaderNamespace>& emplaced =
+ namespaces_.emplace_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
if (is_main_classloader) {
app_main_namespace_ = &emplaced.second;
}