Loading libnativeloader/include/nativeloader/dlext_namespaces.h +12 −14 Original line number Diff line number Diff line Loading @@ -22,18 +22,6 @@ __BEGIN_DECLS /* * Initializes anonymous namespaces. The shared_libs_sonames is the list of sonames * to be shared by default namespace separated by colon. Example: "libc.so:libm.so:libdl.so". * * The library_search_path is the search path for anonymous namespace. The anonymous namespace * is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens * for the code not loaded by dynamic linker; for example calls from the mono-compiled code. */ extern bool android_init_anonymous_namespace(const char* shared_libs_sonames, const char* library_search_path); enum { /* A regular namespace is the namespace with a custom search path that does * not impose any restrictions on the location of native libraries. Loading Loading @@ -62,8 +50,18 @@ enum { */ ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000, ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED, /* This flag instructs linker to use this namespace as the anonymous * namespace. The anonymous namespace is used in the case when linker cannot * identify the caller of dlopen/dlsym. This happens for the code not loaded * by dynamic linker; for example calls from the mono-compiled code. There can * be only one anonymous namespace in a process. If there already is an * anonymous namespace in the process, using this flag when creating a new * namespace causes an error. */ ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000, ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED, }; /* Loading libnativeloader/library_namespaces.cpp +16 −37 Original line number Diff line number Diff line Loading @@ -159,13 +159,6 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t } } // Initialize the anonymous namespace with the first non-empty library path. Result<void> ret; if (!library_path.empty() && !initialized_ && !(ret = InitPublicNamespace(library_path.c_str()))) { return ret.error(); } LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr, "There is already a namespace associated with this classloader"); Loading Loading @@ -215,13 +208,22 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t // Create the app namespace NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader); auto app_ns = NativeLoaderNamespace::Create(namespace_name, library_path, permitted_path, parent_ns, is_shared, target_sdk_version < 24 /* is_greylist_enabled */); // Heuristic: the first classloader with non-empty library_path is assumed to // be the main classloader for app // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its // friends) and then passing it down to here. bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty(); // Policy: the namespace for the main classloader is also used as the // anonymous namespace. bool also_used_as_anonymous = is_main_classloader; // Note: this function is executed with g_namespaces_mutex held, thus no // racing here. auto app_ns = NativeLoaderNamespace::Create( namespace_name, library_path, permitted_path, parent_ns, is_shared, target_sdk_version < 24 /* is_greylist_enabled */, also_used_as_anonymous); if (!app_ns) { return app_ns.error(); } // ... and link to other namespaces to allow access to some public libraries bool is_bridged = app_ns->IsBridged(); Loading Loading @@ -278,6 +280,9 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t } namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns)); if (is_main_classloader) { app_main_namespace_ = &(*app_ns); } return &(namespaces_.back().second); } Loading @@ -295,32 +300,6 @@ NativeLoaderNamespace* LibraryNamespaces::FindNamespaceByClassLoader(JNIEnv* env return nullptr; } Result<void> LibraryNamespaces::InitPublicNamespace(const char* library_path) { // Ask native bride if this apps library path should be handled by it bool is_native_bridge = NativeBridgeIsPathSupported(library_path); // (http://b/25844435) - Some apps call dlopen from generated code (mono jited // code is one example) unknown to linker in which case linker uses anonymous // namespace. The second argument specifies the search path for the anonymous // namespace which is the library_path of the classloader. initialized_ = android_init_anonymous_namespace(default_public_libraries().c_str(), is_native_bridge ? nullptr : library_path); if (!initialized_) { return Error() << dlerror(); } // and now initialize native bridge namespaces if necessary. if (NativeBridgeInitialized()) { initialized_ = NativeBridgeInitAnonymousNamespace(default_public_libraries().c_str(), is_native_bridge ? library_path : nullptr); if (!initialized_) { return Error() << NativeBridgeGetError(); } } return {}; } NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) { jobject parent_class_loader = GetParentClassLoader(env, class_loader); Loading libnativeloader/library_namespaces.h +2 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ class LibraryNamespaces { void Reset() { namespaces_.clear(); initialized_ = false; app_main_namespace_ = nullptr; } Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path, Loading @@ -59,6 +60,7 @@ class LibraryNamespaces { NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader); bool initialized_; NativeLoaderNamespace* app_main_namespace_; std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_; }; Loading libnativeloader/native_loader_namespace.cpp +12 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,8 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::GetPlatformNamespace(bool i Result<NativeLoaderNamespace> NativeLoaderNamespace::Create( const std::string& name, const std::string& search_paths, const std::string& permitted_paths, const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled) { const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled, bool also_used_as_anonymous) { bool is_bridged = false; if (parent != nullptr) { is_bridged = parent->IsBridged(); Loading @@ -100,7 +101,17 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::Create( } const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns; // All namespaces for apps are isolated uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED; // The namespace is also used as the anonymous namespace // which is used when the linker fails to determine the caller address if (also_used_as_anonymous) { type |= ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS; } // Bundled apps have access to all system libraries that are currently loaded // in the default namespace if (is_shared) { type |= ANDROID_NAMESPACE_TYPE_SHARED; } Loading libnativeloader/native_loader_namespace.h +2 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,8 @@ struct NativeLoaderNamespace { const std::string& search_paths, const std::string& permitted_paths, const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled); bool is_greylist_enabled, bool also_used_as_anonymous); NativeLoaderNamespace(NativeLoaderNamespace&&) = default; NativeLoaderNamespace(const NativeLoaderNamespace&) = default; Loading Loading
libnativeloader/include/nativeloader/dlext_namespaces.h +12 −14 Original line number Diff line number Diff line Loading @@ -22,18 +22,6 @@ __BEGIN_DECLS /* * Initializes anonymous namespaces. The shared_libs_sonames is the list of sonames * to be shared by default namespace separated by colon. Example: "libc.so:libm.so:libdl.so". * * The library_search_path is the search path for anonymous namespace. The anonymous namespace * is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens * for the code not loaded by dynamic linker; for example calls from the mono-compiled code. */ extern bool android_init_anonymous_namespace(const char* shared_libs_sonames, const char* library_search_path); enum { /* A regular namespace is the namespace with a custom search path that does * not impose any restrictions on the location of native libraries. Loading Loading @@ -62,8 +50,18 @@ enum { */ ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000, ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED, /* This flag instructs linker to use this namespace as the anonymous * namespace. The anonymous namespace is used in the case when linker cannot * identify the caller of dlopen/dlsym. This happens for the code not loaded * by dynamic linker; for example calls from the mono-compiled code. There can * be only one anonymous namespace in a process. If there already is an * anonymous namespace in the process, using this flag when creating a new * namespace causes an error. */ ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000, ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED, }; /* Loading
libnativeloader/library_namespaces.cpp +16 −37 Original line number Diff line number Diff line Loading @@ -159,13 +159,6 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t } } // Initialize the anonymous namespace with the first non-empty library path. Result<void> ret; if (!library_path.empty() && !initialized_ && !(ret = InitPublicNamespace(library_path.c_str()))) { return ret.error(); } LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr, "There is already a namespace associated with this classloader"); Loading Loading @@ -215,13 +208,22 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t // Create the app namespace NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader); auto app_ns = NativeLoaderNamespace::Create(namespace_name, library_path, permitted_path, parent_ns, is_shared, target_sdk_version < 24 /* is_greylist_enabled */); // Heuristic: the first classloader with non-empty library_path is assumed to // be the main classloader for app // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its // friends) and then passing it down to here. bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty(); // Policy: the namespace for the main classloader is also used as the // anonymous namespace. bool also_used_as_anonymous = is_main_classloader; // Note: this function is executed with g_namespaces_mutex held, thus no // racing here. auto app_ns = NativeLoaderNamespace::Create( namespace_name, library_path, permitted_path, parent_ns, is_shared, target_sdk_version < 24 /* is_greylist_enabled */, also_used_as_anonymous); if (!app_ns) { return app_ns.error(); } // ... and link to other namespaces to allow access to some public libraries bool is_bridged = app_ns->IsBridged(); Loading Loading @@ -278,6 +280,9 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t } namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns)); if (is_main_classloader) { app_main_namespace_ = &(*app_ns); } return &(namespaces_.back().second); } Loading @@ -295,32 +300,6 @@ NativeLoaderNamespace* LibraryNamespaces::FindNamespaceByClassLoader(JNIEnv* env return nullptr; } Result<void> LibraryNamespaces::InitPublicNamespace(const char* library_path) { // Ask native bride if this apps library path should be handled by it bool is_native_bridge = NativeBridgeIsPathSupported(library_path); // (http://b/25844435) - Some apps call dlopen from generated code (mono jited // code is one example) unknown to linker in which case linker uses anonymous // namespace. The second argument specifies the search path for the anonymous // namespace which is the library_path of the classloader. initialized_ = android_init_anonymous_namespace(default_public_libraries().c_str(), is_native_bridge ? nullptr : library_path); if (!initialized_) { return Error() << dlerror(); } // and now initialize native bridge namespaces if necessary. if (NativeBridgeInitialized()) { initialized_ = NativeBridgeInitAnonymousNamespace(default_public_libraries().c_str(), is_native_bridge ? library_path : nullptr); if (!initialized_) { return Error() << NativeBridgeGetError(); } } return {}; } NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) { jobject parent_class_loader = GetParentClassLoader(env, class_loader); Loading
libnativeloader/library_namespaces.h +2 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ class LibraryNamespaces { void Reset() { namespaces_.clear(); initialized_ = false; app_main_namespace_ = nullptr; } Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path, Loading @@ -59,6 +60,7 @@ class LibraryNamespaces { NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader); bool initialized_; NativeLoaderNamespace* app_main_namespace_; std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_; }; Loading
libnativeloader/native_loader_namespace.cpp +12 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,8 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::GetPlatformNamespace(bool i Result<NativeLoaderNamespace> NativeLoaderNamespace::Create( const std::string& name, const std::string& search_paths, const std::string& permitted_paths, const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled) { const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled, bool also_used_as_anonymous) { bool is_bridged = false; if (parent != nullptr) { is_bridged = parent->IsBridged(); Loading @@ -100,7 +101,17 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::Create( } const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns; // All namespaces for apps are isolated uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED; // The namespace is also used as the anonymous namespace // which is used when the linker fails to determine the caller address if (also_used_as_anonymous) { type |= ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS; } // Bundled apps have access to all system libraries that are currently loaded // in the default namespace if (is_shared) { type |= ANDROID_NAMESPACE_TYPE_SHARED; } Loading
libnativeloader/native_loader_namespace.h +2 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,8 @@ struct NativeLoaderNamespace { const std::string& search_paths, const std::string& permitted_paths, const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled); bool is_greylist_enabled, bool also_used_as_anonymous); NativeLoaderNamespace(NativeLoaderNamespace&&) = default; NativeLoaderNamespace(const NativeLoaderNamespace&) = default; Loading