diff options
-rw-r--r-- | libnativeloader/library_namespaces.cpp | 13 | ||||
-rw-r--r-- | libnativeloader/library_namespaces.h | 3 | ||||
-rw-r--r-- | libnativeloader/native_loader.cpp | 124 |
3 files changed, 96 insertions, 44 deletions
diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp index 683e76247f..2aeaf88a1e 100644 --- a/libnativeloader/library_namespaces.cpp +++ b/libnativeloader/library_namespaces.cpp @@ -23,6 +23,7 @@ #include <dirent.h> #include <dlfcn.h> +#include <optional> #include <regex> #include <string> #include <vector> @@ -356,12 +357,12 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, } for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) { - Result<std::string> apex_ns_name = FindApexNamespaceName(each_jar_path); - if (apex_ns_name.ok()) { - const std::string& jni_libs = apex_jni_libraries(*apex_ns_name); + std::optional<std::string> apex_ns_name = FindApexNamespaceName(each_jar_path); + if (apex_ns_name.has_value()) { + const std::string& jni_libs = apex_jni_libraries(apex_ns_name.value()); if (jni_libs != "") { Result<NativeLoaderNamespace> apex_ns = - NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged); + NativeLoaderNamespace::GetExportedNamespace(apex_ns_name.value(), is_bridged); if (apex_ns.ok()) { linked = app_ns->Link(&apex_ns.value(), jni_libs); if (!linked.ok()) { @@ -444,7 +445,7 @@ NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEn return nullptr; } -base::Result<std::string> FindApexNamespaceName(const std::string& location) { +std::optional<std::string> FindApexNamespaceName(const std::string& location) { // Lots of implicit assumptions here: we expect `location` to be of the form: // /apex/modulename/... // @@ -458,7 +459,7 @@ base::Result<std::string> FindApexNamespaceName(const std::string& location) { std::replace(name.begin(), name.end(), '.', '_'); return name; } - return base::Error(); + return std::nullopt; } } // namespace android::nativeloader diff --git a/libnativeloader/library_namespaces.h b/libnativeloader/library_namespaces.h index 25edf4faf7..741d4116b8 100644 --- a/libnativeloader/library_namespaces.h +++ b/libnativeloader/library_namespaces.h @@ -22,6 +22,7 @@ #endif #include <list> +#include <optional> #include <string> #include "android-base/result.h" @@ -93,7 +94,7 @@ class LibraryNamespaces { std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_; }; -Result<std::string> FindApexNamespaceName(const std::string& location); +std::optional<std::string> FindApexNamespaceName(const std::string& location); } // namespace android::nativeloader diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp index 42a0d39a87..80af4da502 100644 --- a/libnativeloader/native_loader.cpp +++ b/libnativeloader/native_loader.cpp @@ -24,6 +24,7 @@ #include <algorithm> #include <memory> #include <mutex> +#include <optional> #include <string> #include <vector> @@ -70,15 +71,20 @@ std::mutex g_namespaces_mutex; 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) { - 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), - "Error finding namespace of apex: no namespace called %s", name->c_str()); - return boot_namespace; +std::optional<NativeLoaderNamespace> FindApexNamespace(const char* caller_location) { + std::optional<std::string> name = nativeloader::FindApexNamespaceName(caller_location); + if (name.has_value()) { + // Native Bridge is never used for APEXes. + Result<NativeLoaderNamespace> ns = + NativeLoaderNamespace::GetExportedNamespace(name.value(), /*is_bridged=*/false); + LOG_ALWAYS_FATAL_IF(!ns.ok(), + "Error finding ns %s for APEX location %s: %s", + name.value().c_str(), + caller_location, + ns.error().message().c_str()); + return ns.value(); } - return nullptr; + return std::nullopt; } Result<void> CreateNativeloaderDefaultNamespaceLibsLink(NativeLoaderNamespace& ns) @@ -135,7 +141,13 @@ Result<void*> TryLoadNativeloaderExtraLib(const char* path) { if (!ns.ok()) { return ns.error(); } - return ns.value()->Load(path); + + Result<void*> res = ns.value()->Load(path); + ALOGD("Load %s using ns %s from NATIVELOADER_DEFAULT_NAMESPACE_LIBS match: %s", + path, + ns.value()->name().c_str(), + res.ok() ? "ok" : res.error().message().c_str()); + return res; } Result<NativeLoaderNamespace*> CreateClassLoaderNamespaceLocked(JNIEnv* env, @@ -246,15 +258,21 @@ void* OpenNativeLibrary(JNIEnv* env, // is in the boot classpath. *needs_native_bridge = false; if (caller_location != nullptr) { - android_namespace_t* boot_namespace = FindExportedNamespace(caller_location); - if (boot_namespace != nullptr) { + std::optional<NativeLoaderNamespace> ns = FindApexNamespace(caller_location); + if (ns.has_value()) { const android_dlextinfo dlextinfo = { .flags = ANDROID_DLEXT_USE_NAMESPACE, - .library_namespace = boot_namespace, + .library_namespace = ns.value().ToRawAndroidNamespace(), }; void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo); - if (handle == nullptr) { - *error_msg = strdup(dlerror()); + char* dlerror_msg = handle == nullptr ? strdup(dlerror()) : nullptr; + ALOGD("Load %s using APEX ns %s for caller %s: %s", + path, + ns.value().name().c_str(), + caller_location, + dlerror_msg == nullptr ? "ok" : dlerror_msg); + if (dlerror_msg != nullptr) { + *error_msg = dlerror_msg; } return handle; } @@ -276,38 +294,70 @@ void* OpenNativeLibrary(JNIEnv* env, // Fall back to the system namespace. This happens for preloaded JNI // libraries in the zygote. void* handle = OpenSystemLibrary(path, RTLD_NOW); - if (handle == nullptr) { - *error_msg = strdup(dlerror()); + char* dlerror_msg = handle == nullptr ? strdup(dlerror()) : nullptr; + ALOGD("Load %s using system ns (caller=%s): %s", + path, + caller_location == nullptr ? "<unknown>" : caller_location, + dlerror_msg == nullptr ? "ok" : dlerror_msg); + if (dlerror_msg != nullptr) { + *error_msg = dlerror_msg; } return handle; } std::lock_guard<std::mutex> guard(g_namespaces_mutex); - NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader); - 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, - 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.value(); + { + NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader); + if (ns != nullptr) { + *needs_native_bridge = ns->IsBridged(); + Result<void*> handle = ns->Load(path); + ALOGD("Load %s using ns %s from class loader (caller=%s): %s", + path, + ns->name().c_str(), + caller_location == nullptr ? "<unknown>" : caller_location, + handle.ok() ? "ok" : handle.error().message().c_str()); + if (!handle.ok()) { + *error_msg = strdup(handle.error().message().c_str()); + return nullptr; + } + return handle.value(); } } - return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg); + // 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, + empty_dex_path, + library_path_j, + /*permitted_path=*/nullptr, + /*uses_library_list=*/nullptr); + if (!isolated_ns.ok()) { + ALOGD("Failed to create isolated ns for %s (caller=%s)", + path, + caller_location == nullptr ? "<unknown>" : caller_location); + *error_msg = strdup(isolated_ns.error().message().c_str()); + return nullptr; + } + + *needs_native_bridge = isolated_ns.value()->IsBridged(); + Result<void*> handle = isolated_ns.value()->Load(path); + ALOGD("Load %s using isolated ns %s (caller=%s): %s", + path, + isolated_ns.value()->name().c_str(), + caller_location == nullptr ? "<unknown>" : caller_location, + handle.ok() ? "ok" : handle.error().message().c_str()); + if (!handle.ok()) { + *error_msg = strdup(handle.error().message().c_str()); + return nullptr; + } + return handle.value(); #else // !ART_TARGET_ANDROID UNUSED(env, target_sdk_version, class_loader, caller_location); |