From 4cd07681158830ec49f763f746d6644099a73b42 Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Tue, 23 Feb 2016 14:23:51 -0800 Subject: [PATCH] Added function to explicitly initialize a namespace This change replaces lazy get-or-create logic for linker namespaces with the explicit one. ApplicationLoaders.getClassLoader(..) is now resposible for the namespace initialization for PathClassLoaders. Bug: http://b/27189432 Bug: http://b/22548808 Change-Id: Ife987c3ca1db33a47c20f363a5ed61512be8b5a7 (cherry picked from commit d047c925af62e1fe28fcd1c1940df4afe18d458a) --- .../include/nativeloader/native_loader.h | 16 ++++- libnativeloader/native_loader.cpp | 72 ++++++++++++++----- 2 files changed, 67 insertions(+), 21 deletions(-) diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h index 5644aa637..b16c0e66e 100644 --- a/libnativeloader/include/nativeloader/native_loader.h +++ b/libnativeloader/include/nativeloader/native_loader.h @@ -29,9 +29,19 @@ __attribute__((visibility("default"))) void PreloadPublicNativeLibraries(); __attribute__((visibility("default"))) -void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, - jobject class_loader, bool is_shared, jstring library_path, - jstring permitted_path); +jstring CreateClassLoaderNamespace(JNIEnv* env, + int32_t target_sdk_version, + jobject class_loader, + bool is_shared, + jstring library_path, + jstring permitted_path); + +__attribute__((visibility("default"))) +void* OpenNativeLibrary(JNIEnv* env, + int32_t target_sdk_version, + const char* path, + jobject class_loader, + jstring library_path); #if defined(__ANDROID__) // Look up linker namespace by class_loader. Returns nullptr if diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp index f8bb5fdd1..9a1f98f86 100644 --- a/libnativeloader/native_loader.cpp +++ b/libnativeloader/native_loader.cpp @@ -21,6 +21,7 @@ #ifdef __ANDROID__ #include #include "cutils/properties.h" +#include "log/log.h" #endif #include @@ -59,10 +60,11 @@ class LibraryNamespaces { public: LibraryNamespaces() : initialized_(false) { } - android_namespace_t* GetOrCreate(JNIEnv* env, jobject class_loader, - bool is_shared, - jstring java_library_path, - jstring java_permitted_path) { + android_namespace_t* Create(JNIEnv* env, + jobject class_loader, + bool is_shared, + jstring java_library_path, + jstring java_permitted_path) { ScopedUtfChars library_path(env, java_library_path); std::string permitted_path; @@ -79,9 +81,7 @@ class LibraryNamespaces { android_namespace_t* ns = FindNamespaceByClassLoader(env, class_loader); - if (ns != nullptr) { - return ns; - } + LOG_FATAL_IF(ns != nullptr, "There is already a namespace associated with this classloader"); uint64_t namespace_type = ANDROID_NAMESPACE_TYPE_ISOLATED; if (is_shared) { @@ -96,7 +96,9 @@ class LibraryNamespaces { permitted_path.c_str() : nullptr); - namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns)); + if (ns != nullptr) { + namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns)); + } return ns; } @@ -135,6 +137,10 @@ class LibraryNamespaces { }; static LibraryNamespaces* g_namespaces = new LibraryNamespaces; + +static bool namespaces_enabled(uint32_t target_sdk_version) { + return target_sdk_version > 0; +} #endif void PreloadPublicNativeLibraries() { @@ -144,20 +150,51 @@ void PreloadPublicNativeLibraries() { } -void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, - jobject class_loader, bool is_shared, jstring java_library_path, - jstring java_permitted_path) { +jstring CreateClassLoaderNamespace(JNIEnv* env, + int32_t target_sdk_version, + jobject class_loader, + bool is_shared, + jstring library_path, + jstring permitted_path) { #if defined(__ANDROID__) - if (target_sdk_version == 0 || class_loader == nullptr) { + if (!namespaces_enabled(target_sdk_version)) { + return nullptr; + } + + android_namespace_t* ns = g_namespaces->Create(env, + class_loader, + is_shared, + library_path, + permitted_path); + if (ns == nullptr) { + return env->NewStringUTF(dlerror()); + } +#else + UNUSED(env, target_sdk_version, class_loader, is_shared, + library_path, permitted_path); +#endif + return nullptr; +} + +void* OpenNativeLibrary(JNIEnv* env, + int32_t target_sdk_version, + const char* path, + jobject class_loader, + jstring library_path) { +#if defined(__ANDROID__) + if (!namespaces_enabled(target_sdk_version) || class_loader == nullptr) { return dlopen(path, RTLD_NOW); } - android_namespace_t* ns = - g_namespaces->GetOrCreate(env, class_loader, is_shared, - java_library_path, java_permitted_path); + android_namespace_t* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader); if (ns == nullptr) { - return 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. + ns = g_namespaces->Create(env, class_loader, false, library_path, nullptr); + if (ns == nullptr) { + return nullptr; + } } android_dlextinfo extinfo; @@ -166,8 +203,7 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat return android_dlopen_ext(path, RTLD_NOW, &extinfo); #else - UNUSED(env, target_sdk_version, class_loader, is_shared, - java_library_path, java_permitted_path); + UNUSED(env, target_sdk_version, class_loader, library_path); return dlopen(path, RTLD_NOW); #endif }