summaryrefslogtreecommitdiff
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
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
-rw-r--r--libnativeloader/library_namespaces.cpp183
-rw-r--r--libnativeloader/library_namespaces.h45
-rw-r--r--libnativeloader/native_loader.cpp130
-rw-r--r--libnativeloader/native_loader_lazy.cpp2
-rw-r--r--libnativeloader/native_loader_namespace.cpp8
-rw-r--r--libnativeloader/native_loader_test.cpp14
-rw-r--r--libnativeloader/public_libraries.cpp30
7 files changed, 228 insertions, 184 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;
}
diff --git a/libnativeloader/library_namespaces.h b/libnativeloader/library_namespaces.h
index 4871528f47..25edf4faf7 100644
--- a/libnativeloader/library_namespaces.h
+++ b/libnativeloader/library_namespaces.h
@@ -21,20 +21,40 @@
#error "Not available for host or linux target"
#endif
-#define LOG_TAG "nativeloader"
-
-#include "native_loader_namespace.h"
-
#include <list>
#include <string>
-#include <android-base/result.h>
-#include <jni.h>
+#include "android-base/result.h"
+#include "jni.h"
+#include "native_loader_namespace.h"
namespace android::nativeloader {
using android::base::Result;
+// 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";
+
+// API domains, roughly corresponding to partitions. Interdependencies between
+// these must follow API restrictions, while intradependencies do not.
+using ApiDomain = enum {
+ API_DOMAIN_DEFAULT = 0, // Locations other than those below, in particular for ordinary apps
+ API_DOMAIN_VENDOR = 1, // Vendor partition
+ API_DOMAIN_PRODUCT = 2, // Product partition
+};
+
+nativeloader::ApiDomain GetApiDomainFromPath(const std::string& path);
+
// LibraryNamespaces is a singleton object that manages NativeLoaderNamespace
// objects for an app process. Its main job is to create (and configure) a new
// NativeLoaderNamespace object for a Java ClassLoader, and to find an existing
@@ -53,10 +73,15 @@ class LibraryNamespaces {
initialized_ = false;
app_main_namespace_ = nullptr;
}
- Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
- jobject class_loader, bool is_shared, jstring dex_path,
- jstring java_library_path, jstring java_permitted_path,
- jstring uses_library_list);
+ Result<NativeLoaderNamespace*> 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);
NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
private:
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 2deb5ef3d0..42a0d39a87 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -27,16 +27,17 @@
#include <string>
#include <vector>
-#include <android-base/file.h>
-#include <android-base/macros.h>
-#include <android-base/strings.h>
-#include <android-base/thread_annotations.h>
-#include <nativebridge/native_bridge.h>
-#include <nativehelper/scoped_utf_chars.h>
+#include "android-base/file.h"
+#include "android-base/macros.h"
+#include "android-base/strings.h"
+#include "android-base/thread_annotations.h"
+#include "nativebridge/native_bridge.h"
+#include "nativehelper/scoped_utf_chars.h"
+#include "public_libraries.h"
#ifdef ART_TARGET_ANDROID
-#include <log/log.h>
#include "library_namespaces.h"
+#include "log/log.h"
#include "nativeloader/dlext_namespaces.h"
#endif
@@ -46,6 +47,9 @@ namespace {
#if defined(ART_TARGET_ANDROID)
+using ::android::base::Result;
+using ::android::nativeloader::LibraryNamespaces;
+
// NATIVELOADER_DEFAULT_NAMESPACE_LIBS is an environment variable that can be
// used to list extra libraries (separated by ":") that libnativeloader will
// load from the default namespace. The libraries must be listed without paths,
@@ -62,14 +66,12 @@ namespace {
// test libraries that depend on ART internal libraries.
constexpr const char* kNativeloaderExtraLibs = "nativeloader-extra-libs";
-using android::nativeloader::LibraryNamespaces;
-
std::mutex g_namespaces_mutex;
-LibraryNamespaces* g_namespaces = new LibraryNamespaces;
-NativeLoaderNamespace* g_nativeloader_extra_libs_namespace = nullptr;
+LibraryNamespaces* g_namespaces GUARDED_BY(g_namespaces_mutex) = new LibraryNamespaces;
+NativeLoaderNamespace* g_nativeloader_extra_libs_namespace GUARDED_BY(g_namespaces_mutex) = nullptr;
android_namespace_t* FindExportedNamespace(const char* caller_location) {
- auto name = nativeloader::FindApexNamespaceName(caller_location);
+ Result<std::string> name = nativeloader::FindApexNamespaceName(caller_location);
if (name.ok()) {
android_namespace_t* boot_namespace = android_get_exported_namespace(name->c_str());
LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
@@ -139,20 +141,22 @@ Result<void*> TryLoadNativeloaderExtraLib(const char* path) {
Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
int32_t target_sdk_version,
jobject class_loader,
+ nativeloader::ApiDomain api_domain,
bool is_shared,
- jstring dex_path,
- jstring library_path,
- jstring permitted_path,
- jstring uses_library_list)
+ const std::string& dex_path,
+ jstring library_path_j,
+ jstring permitted_path_j,
+ jstring uses_library_list_j)
REQUIRES(g_namespaces_mutex) {
Result<NativeLoaderNamespace*> ns = g_namespaces->Create(env,
target_sdk_version,
class_loader,
+ api_domain,
is_shared,
dex_path,
- library_path,
- permitted_path,
- uses_library_list);
+ library_path_j,
+ permitted_path_j,
+ uses_library_list_j);
if (!ns.ok()) {
return ns;
}
@@ -163,7 +167,7 @@ Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env,
return ns;
}
-#endif // #if defined(ART_TARGET_ANDROID)
+#endif // ART_TARGET_ANDROID
} // namespace
@@ -183,36 +187,63 @@ void ResetNativeLoader() {
#endif
}
-jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
- bool is_shared, jstring dex_path, jstring library_path,
- jstring permitted_path, jstring uses_library_list) {
+jstring CreateClassLoaderNamespace(JNIEnv* env,
+ int32_t target_sdk_version,
+ jobject class_loader,
+ bool is_shared,
+ jstring dex_path_j,
+ jstring library_path_j,
+ jstring permitted_path_j,
+ jstring uses_library_list_j) {
#if defined(ART_TARGET_ANDROID)
+ std::string dex_path;
+ if (dex_path_j != nullptr) {
+ ScopedUtfChars dex_path_chars(env, dex_path_j);
+ dex_path = dex_path_chars.c_str();
+ }
+ nativeloader::ApiDomain api_domain = nativeloader::GetApiDomainFromPath(dex_path);
+
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
Result<NativeLoaderNamespace*> ns = CreateClassLoaderNamespaceLocked(env,
target_sdk_version,
class_loader,
+ api_domain,
is_shared,
dex_path,
- library_path,
- permitted_path,
- uses_library_list);
+ library_path_j,
+ permitted_path_j,
+ uses_library_list_j);
if (!ns.ok()) {
return env->NewStringUTF(ns.error().message().c_str());
}
+
#else
- UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path,
- uses_library_list);
+ UNUSED(env,
+ target_sdk_version,
+ class_loader,
+ is_shared,
+ dex_path_j,
+ library_path_j,
+ permitted_path_j,
+ uses_library_list_j);
#endif
+
return nullptr;
}
-void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
- jobject class_loader, const char* caller_location, jstring library_path,
- bool* needs_native_bridge, char** error_msg) {
+void* OpenNativeLibrary(JNIEnv* env,
+ int32_t target_sdk_version,
+ const char* path,
+ jobject class_loader,
+ const char* caller_location,
+ jstring library_path_j,
+ bool* needs_native_bridge,
+ char** error_msg) {
#if defined(ART_TARGET_ANDROID)
- UNUSED(target_sdk_version);
-
if (class_loader == nullptr) {
+ // class_loader is null only for the boot class loader (see
+ // IsBootClassLoader call in JavaVMExt::LoadNativeLibrary), i.e. the caller
+ // is in the boot classpath.
*needs_native_bridge = false;
if (caller_location != nullptr) {
android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
@@ -244,8 +275,6 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
// Fall back to the system namespace. This happens for preloaded JNI
// libraries in the zygote.
- // TODO(b/185833744): Investigate if this should fall back to the app main
- // namespace (aka anonymous namespace) instead.
void* handle = OpenSystemLibrary(path, RTLD_NOW);
if (handle == nullptr) {
*error_msg = strdup(dlerror());
@@ -254,43 +283,46 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
}
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
- NativeLoaderNamespace* ns;
+ NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
- if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
+ if (ns == nullptr) {
// This is the case where the classloader was not created by ApplicationLoaders
// In this case we create an isolated not-shared namespace for it.
+ const std::string empty_dex_path;
Result<NativeLoaderNamespace*> isolated_ns =
CreateClassLoaderNamespaceLocked(env,
target_sdk_version,
class_loader,
+ nativeloader::API_DOMAIN_DEFAULT,
/*is_shared=*/false,
- /*dex_path=*/nullptr,
- library_path,
+ empty_dex_path,
+ library_path_j,
/*permitted_path=*/nullptr,
/*uses_library_list=*/nullptr);
if (!isolated_ns.ok()) {
*error_msg = strdup(isolated_ns.error().message().c_str());
return nullptr;
} else {
- ns = *isolated_ns;
+ ns = isolated_ns.value();
}
}
return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
-#else
+
+#else // !ART_TARGET_ANDROID
UNUSED(env, target_sdk_version, class_loader, caller_location);
// Do some best effort to emulate library-path support. It will not
// work for dependencies.
//
// Note: null has a special meaning and must be preserved.
- std::string c_library_path; // Empty string by default.
- if (library_path != nullptr && path != nullptr && path[0] != '/') {
- ScopedUtfChars library_path_utf_chars(env, library_path);
- c_library_path = library_path_utf_chars.c_str();
+ std::string library_path; // Empty string by default.
+ if (library_path_j != nullptr && path != nullptr && path[0] != '/') {
+ ScopedUtfChars library_path_utf_chars(env, library_path_j);
+ library_path = library_path_utf_chars.c_str();
}
- std::vector<std::string> library_paths = base::Split(c_library_path, ":");
+ std::vector<std::string> library_paths = base::Split(library_path, ":");
for (const std::string& lib_path : library_paths) {
*needs_native_bridge = false;
@@ -323,7 +355,7 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat
}
}
return nullptr;
-#endif
+#endif // !ART_TARGET_ANDROID
}
bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
@@ -351,7 +383,7 @@ void NativeLoaderFreeErrorMessage(char* msg) {
#if defined(ART_TARGET_ANDROID)
void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
bool* needs_native_bridge, char** error_msg) {
- auto handle = ns->Load(path);
+ Result<void*> handle = ns->Load(path);
if (!handle.ok() && error_msg != nullptr) {
*error_msg = strdup(handle.error().message().c_str());
}
@@ -397,4 +429,4 @@ void LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderName
#endif // ART_TARGET_ANDROID
-}; // namespace android
+} // namespace android
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
index 5b82d00560..1c82dc428f 100644
--- a/libnativeloader/native_loader_lazy.cpp
+++ b/libnativeloader/native_loader_lazy.cpp
@@ -35,7 +35,7 @@ void* GetLibHandle() {
template <typename FuncPtr>
FuncPtr GetFuncPtr(const char* function_name) {
- auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
+ FuncPtr f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
return f;
}
diff --git a/libnativeloader/native_loader_namespace.cpp b/libnativeloader/native_loader_namespace.cpp
index 669fa74dc2..cfb84b7d9e 100644
--- a/libnativeloader/native_loader_namespace.cpp
+++ b/libnativeloader/native_loader_namespace.cpp
@@ -52,12 +52,12 @@ std::string GetLinkerError(bool is_bridged) {
Result<NativeLoaderNamespace> NativeLoaderNamespace::GetExportedNamespace(const std::string& name,
bool is_bridged) {
if (!is_bridged) {
- auto raw = android_get_exported_namespace(name.c_str());
+ android_namespace_t* raw = android_get_exported_namespace(name.c_str());
if (raw != nullptr) {
return NativeLoaderNamespace(name, raw);
}
} else {
- auto raw = NativeBridgeGetExportedNamespace(name.c_str());
+ native_bridge_namespace_t* raw = NativeBridgeGetExportedNamespace(name.c_str());
if (raw != nullptr) {
return NativeLoaderNamespace(name, raw);
}
@@ -69,7 +69,7 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::GetExportedNamespace(const
// "system" for those in the Runtime APEX. Try "system" first since
// "default" always exists.
Result<NativeLoaderNamespace> NativeLoaderNamespace::GetSystemNamespace(bool is_bridged) {
- auto ns = GetExportedNamespace(kSystemNamespaceName, is_bridged);
+ Result<NativeLoaderNamespace> ns = GetExportedNamespace(kSystemNamespaceName, is_bridged);
if (ns.ok()) return ns;
ns = GetExportedNamespace(kDefaultNamespaceName, is_bridged);
if (ns.ok()) return ns;
@@ -96,7 +96,7 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
}
// Fall back to the system namespace if no parent is set.
- auto system_ns = GetSystemNamespace(is_bridged);
+ Result<NativeLoaderNamespace> system_ns = GetSystemNamespace(is_bridged);
if (!system_ns.ok()) {
return system_ns.error();
}
diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp
index 72348ed364..3b05aae06b 100644
--- a/libnativeloader/native_loader_test.cpp
+++ b/libnativeloader/native_loader_test.cpp
@@ -564,7 +564,8 @@ jni com_android_bar libbar.so:libbar2.so
public com_android_bar libpublic.so
)";
- auto jni_libs = ParseApexLibrariesConfig(file_content, "jni");
+ Result<std::map<std::string, std::string>> jni_libs =
+ ParseApexLibrariesConfig(file_content, "jni");
ASSERT_RESULT_OK(jni_libs);
std::map<std::string, std::string> expected_jni_libs {
{"com_android_foo", "libfoo.so"},
@@ -572,7 +573,8 @@ jni com_android_bar libbar.so:libbar2.so
};
ASSERT_EQ(expected_jni_libs, *jni_libs);
- auto public_libs = ParseApexLibrariesConfig(file_content, "public");
+ Result<std::map<std::string, std::string>> public_libs =
+ ParseApexLibrariesConfig(file_content, "public");
ASSERT_RESULT_OK(public_libs);
std::map<std::string, std::string> expected_public_libs {
{"com_android_bar", "libpublic.so"},
@@ -586,7 +588,7 @@ jni com_android_foo libfoo
# missing <library list>
jni com_android_bar
)";
- auto result = ParseApexLibrariesConfig(file_content, "jni");
+ Result<std::map<std::string, std::string>> result = ParseApexLibrariesConfig(file_content, "jni");
ASSERT_FALSE(result.ok());
ASSERT_EQ("Malformed line \"jni com_android_bar\"", result.error().message());
}
@@ -598,7 +600,7 @@ public apex2 lib
# unknown tag
unknown com_android_foo libfoo
)";
- auto result = ParseApexLibrariesConfig(file_content, "jni");
+ Result<std::map<std::string, std::string>> result = ParseApexLibrariesConfig(file_content, "jni");
ASSERT_FALSE(result.ok());
ASSERT_EQ("Invalid tag \"unknown com_android_foo libfoo\"", result.error().message());
}
@@ -608,7 +610,7 @@ TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidApexNamespace) {
# apex linker namespace should be mangled ('.' -> '_')
jni com.android.foo lib
)";
- auto result = ParseApexLibrariesConfig(file_content, "jni");
+ Result<std::map<std::string, std::string>> result = ParseApexLibrariesConfig(file_content, "jni");
ASSERT_FALSE(result.ok());
ASSERT_EQ("Invalid apex_namespace \"jni com.android.foo lib\"", result.error().message());
}
@@ -618,7 +620,7 @@ TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidLibraryList) {
# library list is ":" separated list of filenames
jni com_android_foo lib64/libfoo.so
)";
- auto result = ParseApexLibrariesConfig(file_content, "jni");
+ Result<std::map<std::string, std::string>> result = ParseApexLibrariesConfig(file_content, "jni");
ASSERT_FALSE(result.ok());
ASSERT_EQ("Invalid library_list \"jni com_android_foo lib64/libfoo.so\"", result.error().message());
}
diff --git a/libnativeloader/public_libraries.cpp b/libnativeloader/public_libraries.cpp
index 0ba18f3ecf..af965a09a9 100644
--- a/libnativeloader/public_libraries.cpp
+++ b/libnativeloader/public_libraries.cpp
@@ -78,7 +78,7 @@ std::string vndk_version_str(bool use_product_vndk) {
// insert vndk version in every {} placeholder
void InsertVndkVersionStr(std::string* file_name, bool use_product_vndk) {
CHECK(file_name != nullptr);
- auto version = vndk_version_str(use_product_vndk);
+ const std::string version = vndk_version_str(use_product_vndk);
size_t pos = file_name->find("{}");
while (pos != std::string::npos) {
file_name->replace(pos, 2, version);
@@ -123,7 +123,7 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam
"Error extracting company name from public native library list file path \"%s\"",
config_file_path.c_str());
- auto ret = ReadConfig(
+ Result<std::vector<std::string>> ret = ReadConfig(
config_file_path, [&company_name](const struct ConfigEntry& entry) -> Result<bool> {
if (android::base::StartsWith(entry.soname, "lib") &&
android::base::EndsWith(entry.soname, "." + company_name + ".so")) {
@@ -149,7 +149,7 @@ void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonam
static std::string InitDefaultPublicLibraries(bool for_preload) {
std::string config_file = root_dir() + kDefaultPublicLibrariesFile;
- auto sonames =
+ Result<std::vector<std::string>> sonames =
ReadConfig(config_file, [&for_preload](const struct ConfigEntry& entry) -> Result<bool> {
if (for_preload) {
return !entry.nopreload;
@@ -167,8 +167,8 @@ static std::string InitDefaultPublicLibraries(bool for_preload) {
if (!for_preload) {
// Remove the public libs provided by apexes because these libs are available
// from apex namespaces.
- for (const auto& p : apex_public_libraries()) {
- auto public_libs = base::Split(p.second, ":");
+ for (const std::pair<std::string, std::string>& p : apex_public_libraries()) {
+ std::vector<std::string> public_libs = base::Split(p.second, ":");
sonames->erase(std::remove_if(sonames->begin(),
sonames->end(),
[&public_libs](const std::string& v) {
@@ -186,7 +186,7 @@ static std::string InitDefaultPublicLibraries(bool for_preload) {
static std::string InitVendorPublicLibraries() {
// This file is optional, quietly ignore if the file does not exist.
- auto sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
+ Result<std::vector<std::string>> sonames = ReadConfig(kVendorPublicLibrariesFile, always_true);
if (!sonames.ok()) {
ALOGI("InitVendorPublicLibraries skipped: %s", sonames.error().message().c_str());
return "";
@@ -250,7 +250,7 @@ static std::string InitLlndkLibrariesVendor() {
} else {
config_file = kLlndkLibrariesNoVndkFile;
}
- auto sonames = ReadConfig(config_file, always_true);
+ Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
if (!sonames.ok()) {
LOG_ALWAYS_FATAL("%s: %s", config_file.c_str(), sonames.error().message().c_str());
return "";
@@ -272,7 +272,7 @@ static std::string InitLlndkLibrariesProduct() {
} else {
config_file = kLlndkLibrariesNoVndkFile;
}
- auto sonames = ReadConfig(config_file, always_true);
+ Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
if (!sonames.ok()) {
LOG_ALWAYS_FATAL("%s: %s", config_file.c_str(), sonames.error().message().c_str());
return "";
@@ -290,7 +290,7 @@ static std::string InitVndkspLibrariesVendor() {
std::string config_file = kVndkLibrariesFile;
InsertVndkVersionStr(&config_file, false);
- auto sonames = ReadConfig(config_file, always_true);
+ Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
if (!sonames.ok()) {
LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
return "";
@@ -307,7 +307,7 @@ static std::string InitVndkspLibrariesProduct() {
}
std::string config_file = kVndkLibrariesFile;
InsertVndkVersionStr(&config_file, true);
- auto sonames = ReadConfig(config_file, always_true);
+ Result<std::vector<std::string>> sonames = ReadConfig(config_file, always_true);
if (!sonames.ok()) {
LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str());
return "";
@@ -460,8 +460,8 @@ Result<std::vector<std::string>> ParseConfig(
std::vector<std::string> lines = base::Split(file_content, "\n");
std::vector<std::string> sonames;
- for (auto& line : lines) {
- auto trimmed_line = base::Trim(line);
+ for (std::string& line : lines) {
+ std::string trimmed_line = base::Trim(line);
if (trimmed_line[0] == '#' || trimmed_line.empty()) {
continue;
}
@@ -528,12 +528,12 @@ Result<std::vector<std::string>> ParseConfig(
Result<std::map<std::string, std::string>> ParseApexLibrariesConfig(const std::string& file_content, const std::string& tag) {
std::map<std::string, std::string> entries;
std::vector<std::string> lines = base::Split(file_content, "\n");
- for (auto& line : lines) {
- auto trimmed_line = base::Trim(line);
+ for (std::string& line : lines) {
+ std::string trimmed_line = base::Trim(line);
if (trimmed_line[0] == '#' || trimmed_line.empty()) {
continue;
}
- auto config_line = ParseApexLibrariesConfigLine(trimmed_line);
+ Result<ApexLibrariesConfigLine> config_line = ParseApexLibrariesConfigLine(trimmed_line);
if (!config_line.ok()) {
return config_line.error();
}