summaryrefslogtreecommitdiff
path: root/libnativeloader/native_loader.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/native_loader.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/native_loader.cpp')
-rw-r--r--libnativeloader/native_loader.cpp130
1 files changed, 81 insertions, 49 deletions
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