diff options
author | 2015-11-11 14:18:55 -0800 | |
---|---|---|
committer | 2015-12-10 17:25:14 -0800 | |
commit | f5a3099c509cf9b8a4ce9c3073a4db47e14a23bc (patch) | |
tree | 5f07f3ea531240643f4f637c9d3abbad6feafa52 | |
parent | 748047de833061466e230baf374480a147568f73 (diff) |
Use isolated namespaces for app native libs
Linker namespaces provide necessary level
of isolation for application native libraries.
The native libraries will no longer be able to
mistakenly depend on platform private libraries
like /system/lib/libssl.so
This change creates one namespace for each instance
of class-loader and uses it when loading native libraries.
For backwards compatibility with older apps we keep
using default namespace and LD_LIBRARY_PATH if target
sdk version is <= 23. (currently set to 0 for testing)
Bug: http://b/22548808
Change-Id: I64e97af7450fbf7e3740ccddda96bb2f7c52e03b
-rw-r--r-- | compiler/jni/jni_compiler_test.cc | 6 | ||||
-rw-r--r-- | runtime/Android.mk | 14 | ||||
-rw-r--r-- | runtime/java_vm_ext.cc | 6 | ||||
-rw-r--r-- | runtime/java_vm_ext.h | 4 | ||||
-rw-r--r-- | runtime/native/java_lang_Runtime.cc | 24 | ||||
-rw-r--r-- | runtime/runtime.cc | 6 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 5 |
7 files changed, 46 insertions, 19 deletions
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc index f3bda2fa72..cf836a9c9f 100644 --- a/compiler/jni/jni_compiler_test.cc +++ b/compiler/jni/jni_compiler_test.cc @@ -219,7 +219,8 @@ void JniCompilerTest::CompileAndRunIntMethodThroughStubImpl() { // calling through stub will link with &Java_MyClassNatives_bar std::string reason; - ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(env_, "", class_loader_, &reason)) + ASSERT_TRUE(Runtime::Current()->GetJavaVM()-> + LoadNativeLibrary(env_, "", class_loader_, nullptr, &reason)) << reason; jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24); @@ -233,7 +234,8 @@ void JniCompilerTest::CompileAndRunStaticIntMethodThroughStubImpl() { // calling through stub will link with &Java_MyClassNatives_sbar std::string reason; - ASSERT_TRUE(Runtime::Current()->GetJavaVM()->LoadNativeLibrary(env_, "", class_loader_, &reason)) + ASSERT_TRUE(Runtime::Current()->GetJavaVM()-> + LoadNativeLibrary(env_, "", class_loader_, nullptr, &reason)) << reason; jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42); diff --git a/runtime/Android.mk b/runtime/Android.mk index 36c81fb078..68433c1667 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -491,9 +491,19 @@ $$(ENUM_OPERATOR_OUT_GEN): $$(GENERATED_SRC_DIR)/%_operator_out.cc : $(LOCAL_PAT LOCAL_C_INCLUDES += art ifeq ($$(art_static_or_shared),static) - LOCAL_STATIC_LIBRARIES := libnativehelper libnativebridge libsigchain_dummy libbacktrace liblz4 + LOCAL_STATIC_LIBRARIES := libnativehelper + LOCAL_STATIC_LIBRARIES += libnativebridge + LOCAL_STATIC_LIBRARIES += libnativeloader + LOCAL_STATIC_LIBRARIES += libsigchain_dummy + LOCAL_STATIC_LIBRARIES += libbacktrace + LOCAL_STATIC_LIBRARIES += liblz4 else - LOCAL_SHARED_LIBRARIES := libnativehelper libnativebridge libsigchain libbacktrace liblz4 + LOCAL_SHARED_LIBRARIES := libnativehelper + LOCAL_SHARED_LIBRARIES += libnativebridge + LOCAL_SHARED_LIBRARIES += libnativeloader + LOCAL_SHARED_LIBRARIES += libsigchain + LOCAL_SHARED_LIBRARIES += libbacktrace + LOCAL_SHARED_LIBRARIES += liblz4 endif ifeq ($$(art_target_or_host),target) diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index 7cc05f7cd4..15f51220e4 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -17,6 +17,7 @@ #include "jni_internal.h" #define ATRACE_TAG ATRACE_TAG_DALVIK + #include <cutils/trace.h> #include <dlfcn.h> @@ -31,6 +32,7 @@ #include "mirror/class-inl.h" #include "mirror/class_loader.h" #include "nativebridge/native_bridge.h" +#include "nativeloader/native_loader.h" #include "java_vm_ext.h" #include "parsed_options.h" #include "runtime-inl.h" @@ -715,6 +717,7 @@ void JavaVMExt::UnloadNativeLibraries() { } bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader, + jstring library_path, jstring permitted_path, std::string* error_msg) { error_msg->clear(); @@ -774,7 +777,8 @@ bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject Locks::mutator_lock_->AssertNotHeld(self); const char* path_str = path.empty() ? nullptr : path.c_str(); - void* handle = dlopen(path_str, RTLD_NOW); + void* handle = android::OpenNativeLibrary(env, runtime_->GetTargetSdkVersion(), + path_str, class_loader, library_path, permitted_path); bool needs_native_bridge = false; if (handle == nullptr) { if (android::NativeBridgeIsSupported(path_str)) { diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h index 618f6faad5..85597695af 100644 --- a/runtime/java_vm_ext.h +++ b/runtime/java_vm_ext.h @@ -82,11 +82,11 @@ class JavaVMExt : public JavaVM { /** * Loads the given shared library. 'path' is an absolute pathname. * - * Returns 'true' on success. On failure, sets 'detail' to a + * Returns 'true' on success. On failure, sets 'error_msg' to a * human-readable description of the error. */ bool LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject javaLoader, - std::string* error_msg); + jstring library_path, jstring permitted_path, std::string* error_msg); // Unload native libraries with cleared class loaders. void UnloadNativeLibraries() diff --git a/runtime/native/java_lang_Runtime.cc b/runtime/native/java_lang_Runtime.cc index 856a3e7d01..ff82772171 100644 --- a/runtime/native/java_lang_Runtime.cc +++ b/runtime/native/java_lang_Runtime.cc @@ -52,10 +52,10 @@ NO_RETURN static void Runtime_nativeExit(JNIEnv*, jclass, jint status) { exit(status); } -static void SetLdLibraryPath(JNIEnv* env, jstring javaLdLibraryPathJstr) { +static void SetLdLibraryPath(JNIEnv* env, jstring javaLdLibraryPath) { #ifdef __ANDROID__ - if (javaLdLibraryPathJstr != nullptr) { - ScopedUtfChars ldLibraryPath(env, javaLdLibraryPathJstr); + if (javaLdLibraryPath != nullptr) { + ScopedUtfChars ldLibraryPath(env, javaLdLibraryPath); if (ldLibraryPath.c_str() != nullptr) { android_update_LD_LIBRARY_PATH(ldLibraryPath.c_str()); } @@ -63,23 +63,31 @@ static void SetLdLibraryPath(JNIEnv* env, jstring javaLdLibraryPathJstr) { #else LOG(WARNING) << "android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!"; - UNUSED(javaLdLibraryPathJstr, env); + UNUSED(javaLdLibraryPath, env); #endif } static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader, - jstring javaLdLibraryPathJstr) { + jstring javaLdLibraryPath, jstring javaIsolationPath) { ScopedUtfChars filename(env, javaFilename); if (filename.c_str() == nullptr) { return nullptr; } - SetLdLibraryPath(env, javaLdLibraryPathJstr); + int32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion(); + + // Starting with N nativeLoad uses classloader local + // linker namespace instead of global LD_LIBRARY_PATH + // (23 is Marshmallow) + if (target_sdk_version == 0) { + SetLdLibraryPath(env, javaLdLibraryPath); + } std::string error_msg; { JavaVMExt* vm = Runtime::Current()->GetJavaVM(); - bool success = vm->LoadNativeLibrary(env, filename.c_str(), javaLoader, &error_msg); + bool success = vm->LoadNativeLibrary(env, filename.c_str(), javaLoader, + javaLdLibraryPath, javaIsolationPath, &error_msg); if (success) { return nullptr; } @@ -107,7 +115,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Runtime, gc, "()V"), NATIVE_METHOD(Runtime, maxMemory, "!()J"), NATIVE_METHOD(Runtime, nativeExit, "(I)V"), - NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;"), + NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(Runtime, totalMemory, "!()J"), }; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index dedc110b00..7e5598bd82 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1220,9 +1220,9 @@ void Runtime::InitNativeMethods() { // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's // the library that implements System.loadLibrary! { - std::string reason; - if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr, &reason)) { - LOG(FATAL) << "LoadNativeLibrary failed for \"libjavacore.so\": " << reason; + std::string error_msg; + if (!java_vm_->LoadNativeLibrary(env, "libjavacore.so", nullptr, nullptr, nullptr, &error_msg)) { + LOG(FATAL) << "LoadNativeLibrary failed for \"libjavacore.so\": " << error_msg; } } diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index e2c3afbcbc..2b778d9b22 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -379,7 +379,10 @@ void WellKnownClasses::Init(JNIEnv* env) { void WellKnownClasses::LateInit(JNIEnv* env) { ScopedLocalRef<jclass> java_lang_Runtime(env, env->FindClass("java/lang/Runtime")); - java_lang_Runtime_nativeLoad = CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad", "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;"); + java_lang_Runtime_nativeLoad = + CacheMethod(env, java_lang_Runtime.get(), true, "nativeLoad", + "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)" + "Ljava/lang/String;"); } mirror::Class* WellKnownClasses::ToClass(jclass global_jclass) { |