A workaround for apps using custom classloaders
Allow custom classloaders to load native libraries
from anywhere under /data
Bug: http://b/27588281
Change-Id: Idb87b33361903f52b734ddd0ceaabe1ff9c281eb
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index e6b37ed..5fc3475 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -21,6 +21,7 @@
#ifdef __ANDROID__
#include <android/dlext.h>
#include "cutils/properties.h"
+#define LOG_TAG "libnativeloader"
#include "log/log.h"
#endif
@@ -38,6 +39,11 @@
#if defined(__ANDROID__)
static constexpr const char* kPublicNativeLibrariesConfig = "/system/etc/public.libraries.txt";
+static bool namespace_workaround_enabled(int32_t target_sdk_version) {
+ // target_sdk_version = 0 is another way of saying "target current sdk level"
+ return target_sdk_version != 0 && target_sdk_version <= 23;
+}
+
class LibraryNamespaces {
public:
LibraryNamespaces() : initialized_(false) { }
@@ -54,6 +60,14 @@
if (java_permitted_path != nullptr) {
ScopedUtfChars path(env, java_permitted_path);
permitted_path = path.c_str();
+ } else {
+ // (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.
+ //
+ // This part effectively allows such a classloader to access anything
+ // under /data
+ permitted_path = "/data";
}
if (!initialized_ && !InitPublicNamespace(library_path.c_str(), target_sdk_version)) {
@@ -74,7 +88,7 @@
nullptr,
library_path.c_str(),
namespace_type,
- java_permitted_path != nullptr ?
+ !permitted_path.empty() ?
permitted_path.c_str() :
nullptr);
@@ -128,7 +142,7 @@
// TODO (dimitry): This is a workaround for http://b/26436837
// will be removed before the release.
- if (target_sdk_version <= 23) {
+ if (namespace_workaround_enabled(target_sdk_version)) {
// check if libart.so is loaded.
void* handle = dlopen("libart.so", RTLD_NOW | RTLD_NOLOAD);
if (handle != nullptr) {