Loading libnativeloader/Android.bp +16 −0 Original line number Diff line number Diff line Loading @@ -23,4 +23,20 @@ cc_library { "llndk.libraries.txt", "vndksp.libraries.txt", ], target: { android: { version_script: "libnativeloader.map.txt", }, }, stubs: { symbol_file: "libnativeloader.map.txt", versions: ["1"], }, } cc_library_headers { name: "libnativeloader-dummy-headers", host_supported: true, export_include_dirs: ["include"], } libnativeloader/include/nativeloader/dlext_namespaces.h +7 −9 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define __ANDROID_DLEXT_NAMESPACES_H__ #include <android/dlext.h> #include <stdbool.h> __BEGIN_DECLS Loading Loading @@ -84,12 +85,9 @@ enum { * If a library or any of its dependencies are outside of the permitted_when_isolated_path * and search_path, and it is not part of the public namespace dlopen will fail. */ extern struct android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, android_namespace_t* parent); extern struct android_namespace_t* android_create_namespace( const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, struct android_namespace_t* parent); /* * Creates a link between namespaces. Every link has list of sonames of Loading @@ -107,8 +105,8 @@ extern struct android_namespace_t* android_create_namespace(const char* name, * step will not go deeper into linked namespaces for this library but * will do so for DT_NEEDED libraries. */ extern bool android_link_namespaces(android_namespace_t* from, android_namespace_t* to, extern bool android_link_namespaces(struct android_namespace_t* from, struct android_namespace_t* to, const char* shared_libs_sonames); /* Loading @@ -124,7 +122,7 @@ extern bool android_link_namespaces(android_namespace_t* from, */ extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size); extern android_namespace_t* android_get_exported_namespace(const char* name); extern struct android_namespace_t* android_get_exported_namespace(const char* name); __END_DECLS Loading libnativeloader/include/nativeloader/native_loader.h +27 −23 Original line number Diff line number Diff line Loading @@ -17,14 +17,21 @@ #ifndef NATIVE_LOADER_H_ #define NATIVE_LOADER_H_ #include "jni.h" #include <stdbool.h> #include <stdint.h> #include <string> #include "jni.h" #if defined(__ANDROID__) #include <android/dlext.h> #endif #ifdef __cplusplus namespace android { extern "C" { #endif // __cplusplus // README: the char** error message parameter being passed // to the methods below need to be freed through calling NativeLoaderFreeErrorMessage. // It's the caller's responsibility to call that method. __attribute__((visibility("default"))) void InitializeNativeLoader(); Loading @@ -38,42 +45,39 @@ jstring CreateClassLoaderNamespace(JNIEnv* env, 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, bool* needs_native_bridge, std::string* error_msg); __attribute__((visibility("default"))) void* OpenNativeLibrary( JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader, jstring library_path, bool* needs_native_bridge, char** error_msg); __attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, std::string* error_msg); char** error_msg); __attribute__((visibility("default"))) void NativeLoaderFreeErrorMessage(char* msg); #if defined(__ANDROID__) // Look up linker namespace by class_loader. Returns nullptr if // there is no namespace associated with the class_loader. // TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function. __attribute__((visibility("default"))) android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader); // That version works with native bridge namespaces, but requires use of OpenNativeLibrary. class NativeLoaderNamespace; __attribute__((visibility("default"))) NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader( __attribute__((visibility("default"))) struct android_namespace_t* FindNamespaceByClassLoader( JNIEnv* env, jobject class_loader); // That version works with native bridge namespaces, but requires use of OpenNativeLibrary. struct NativeLoaderNamespace; __attribute__((visibility("default"))) struct NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader); // Load library. Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does // not require access to JNIEnv either. __attribute__((visibility("default"))) void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, std::string* error_msg); __attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace( struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, char** error_msg); #endif __attribute__((visibility("default"))) void ResetNativeLoader(); }; // namespace android #ifdef __cplusplus } // extern "C" } // namespace android #endif // __cplusplus #endif // NATIVE_BRIDGE_H_ libnativeloader/libnativeloader.map.txt 0 → 100644 +31 −0 Original line number Diff line number Diff line # # Copyright (C) 2019 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # TODO(b/122710865): Prune these uses once the runtime APEX is complete. LIBNATIVELOADER_1 { global: OpenNativeLibrary; InitializeNativeLoader; ResetNativeLoader; CloseNativeLibrary; OpenNativeLibraryInNamespace; FindNamespaceByClassLoader; FindNativeLoaderNamespaceByClassLoader; CreateClassLoaderNamespace; NativeLoaderFreeErrorMessage; local: *; }; libnativeloader/native_loader.cpp +27 −34 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ using namespace std::string_literals; namespace android { #if defined(__ANDROID__) class NativeLoaderNamespace { struct NativeLoaderNamespace { public: NativeLoaderNamespace() : android_ns_(nullptr), native_bridge_ns_(nullptr) { } Loading Loading @@ -151,14 +151,9 @@ class LibraryNamespaces { public: LibraryNamespaces() : initialized_(false) { } NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, bool is_for_vendor, jstring java_library_path, jstring java_permitted_path, std::string* error_msg) { NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, bool is_for_vendor, jstring java_library_path, jstring java_permitted_path, std::string* error_msg) { std::string library_path; // empty string by default. if (java_library_path != nullptr) { Loading Loading @@ -628,13 +623,9 @@ jstring CreateClassLoaderNamespace(JNIEnv* env, return nullptr; } void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader, jstring library_path, bool* needs_native_bridge, std::string* error_msg) { void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader, jstring library_path, bool* needs_native_bridge, char** error_msg) { #if defined(__ANDROID__) UNUSED(target_sdk_version); if (class_loader == nullptr) { Loading @@ -652,19 +643,16 @@ void* OpenNativeLibrary(JNIEnv* env, if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == 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. if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, false /* is_for_vendor */, library_path, nullptr, error_msg)) == nullptr) { std::string create_error_msg; if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, false /* is_for_vendor */, library_path, nullptr, &create_error_msg)) == nullptr) { *error_msg = strdup(create_error_msg.c_str()); return nullptr; } } return OpenNativeLibrary(ns, path, needs_native_bridge, error_msg); return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg); #else UNUSED(env, target_sdk_version, class_loader); Loading Loading @@ -705,35 +693,40 @@ void* OpenNativeLibrary(JNIEnv* env, if (handle != nullptr) { return handle; } *error_msg = NativeBridgeGetError(); *error_msg = strdup(NativeBridgeGetError()); } else { *error_msg = dlerror(); *error_msg = strdup(dlerror()); } } return nullptr; #endif } bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, std::string* error_msg) { bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) { bool success; if (needs_native_bridge) { success = (NativeBridgeUnloadLibrary(handle) == 0); if (!success) { *error_msg = NativeBridgeGetError(); *error_msg = strdup(NativeBridgeGetError()); } } else { success = (dlclose(handle) == 0); if (!success) { *error_msg = dlerror(); *error_msg = strdup(dlerror()); } } return success; } void NativeLoaderFreeErrorMessage(char* msg) { // The error messages get allocated through strdup, so we must call free on them. free(msg); } #if defined(__ANDROID__) void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, std::string* error_msg) { void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, char** error_msg) { if (ns->is_android_namespace()) { android_dlextinfo extinfo; extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; Loading @@ -741,14 +734,14 @@ void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo); if (handle == nullptr) { *error_msg = dlerror(); *error_msg = strdup(dlerror()); } *needs_native_bridge = false; return handle; } else { void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns()); if (handle == nullptr) { *error_msg = NativeBridgeGetError(); *error_msg = strdup(NativeBridgeGetError()); } *needs_native_bridge = true; return handle; Loading Loading
libnativeloader/Android.bp +16 −0 Original line number Diff line number Diff line Loading @@ -23,4 +23,20 @@ cc_library { "llndk.libraries.txt", "vndksp.libraries.txt", ], target: { android: { version_script: "libnativeloader.map.txt", }, }, stubs: { symbol_file: "libnativeloader.map.txt", versions: ["1"], }, } cc_library_headers { name: "libnativeloader-dummy-headers", host_supported: true, export_include_dirs: ["include"], }
libnativeloader/include/nativeloader/dlext_namespaces.h +7 −9 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define __ANDROID_DLEXT_NAMESPACES_H__ #include <android/dlext.h> #include <stdbool.h> __BEGIN_DECLS Loading Loading @@ -84,12 +85,9 @@ enum { * If a library or any of its dependencies are outside of the permitted_when_isolated_path * and search_path, and it is not part of the public namespace dlopen will fail. */ extern struct android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, android_namespace_t* parent); extern struct android_namespace_t* android_create_namespace( const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type, const char* permitted_when_isolated_path, struct android_namespace_t* parent); /* * Creates a link between namespaces. Every link has list of sonames of Loading @@ -107,8 +105,8 @@ extern struct android_namespace_t* android_create_namespace(const char* name, * step will not go deeper into linked namespaces for this library but * will do so for DT_NEEDED libraries. */ extern bool android_link_namespaces(android_namespace_t* from, android_namespace_t* to, extern bool android_link_namespaces(struct android_namespace_t* from, struct android_namespace_t* to, const char* shared_libs_sonames); /* Loading @@ -124,7 +122,7 @@ extern bool android_link_namespaces(android_namespace_t* from, */ extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size); extern android_namespace_t* android_get_exported_namespace(const char* name); extern struct android_namespace_t* android_get_exported_namespace(const char* name); __END_DECLS Loading
libnativeloader/include/nativeloader/native_loader.h +27 −23 Original line number Diff line number Diff line Loading @@ -17,14 +17,21 @@ #ifndef NATIVE_LOADER_H_ #define NATIVE_LOADER_H_ #include "jni.h" #include <stdbool.h> #include <stdint.h> #include <string> #include "jni.h" #if defined(__ANDROID__) #include <android/dlext.h> #endif #ifdef __cplusplus namespace android { extern "C" { #endif // __cplusplus // README: the char** error message parameter being passed // to the methods below need to be freed through calling NativeLoaderFreeErrorMessage. // It's the caller's responsibility to call that method. __attribute__((visibility("default"))) void InitializeNativeLoader(); Loading @@ -38,42 +45,39 @@ jstring CreateClassLoaderNamespace(JNIEnv* env, 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, bool* needs_native_bridge, std::string* error_msg); __attribute__((visibility("default"))) void* OpenNativeLibrary( JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader, jstring library_path, bool* needs_native_bridge, char** error_msg); __attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, std::string* error_msg); char** error_msg); __attribute__((visibility("default"))) void NativeLoaderFreeErrorMessage(char* msg); #if defined(__ANDROID__) // Look up linker namespace by class_loader. Returns nullptr if // there is no namespace associated with the class_loader. // TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function. __attribute__((visibility("default"))) android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader); // That version works with native bridge namespaces, but requires use of OpenNativeLibrary. class NativeLoaderNamespace; __attribute__((visibility("default"))) NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader( __attribute__((visibility("default"))) struct android_namespace_t* FindNamespaceByClassLoader( JNIEnv* env, jobject class_loader); // That version works with native bridge namespaces, but requires use of OpenNativeLibrary. struct NativeLoaderNamespace; __attribute__((visibility("default"))) struct NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader); // Load library. Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does // not require access to JNIEnv either. __attribute__((visibility("default"))) void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, std::string* error_msg); __attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace( struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, char** error_msg); #endif __attribute__((visibility("default"))) void ResetNativeLoader(); }; // namespace android #ifdef __cplusplus } // extern "C" } // namespace android #endif // __cplusplus #endif // NATIVE_BRIDGE_H_
libnativeloader/libnativeloader.map.txt 0 → 100644 +31 −0 Original line number Diff line number Diff line # # Copyright (C) 2019 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # TODO(b/122710865): Prune these uses once the runtime APEX is complete. LIBNATIVELOADER_1 { global: OpenNativeLibrary; InitializeNativeLoader; ResetNativeLoader; CloseNativeLibrary; OpenNativeLibraryInNamespace; FindNamespaceByClassLoader; FindNativeLoaderNamespaceByClassLoader; CreateClassLoaderNamespace; NativeLoaderFreeErrorMessage; local: *; };
libnativeloader/native_loader.cpp +27 −34 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ using namespace std::string_literals; namespace android { #if defined(__ANDROID__) class NativeLoaderNamespace { struct NativeLoaderNamespace { public: NativeLoaderNamespace() : android_ns_(nullptr), native_bridge_ns_(nullptr) { } Loading Loading @@ -151,14 +151,9 @@ class LibraryNamespaces { public: LibraryNamespaces() : initialized_(false) { } NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, bool is_for_vendor, jstring java_library_path, jstring java_permitted_path, std::string* error_msg) { NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader, bool is_shared, bool is_for_vendor, jstring java_library_path, jstring java_permitted_path, std::string* error_msg) { std::string library_path; // empty string by default. if (java_library_path != nullptr) { Loading Loading @@ -628,13 +623,9 @@ jstring CreateClassLoaderNamespace(JNIEnv* env, return nullptr; } void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader, jstring library_path, bool* needs_native_bridge, std::string* error_msg) { void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader, jstring library_path, bool* needs_native_bridge, char** error_msg) { #if defined(__ANDROID__) UNUSED(target_sdk_version); if (class_loader == nullptr) { Loading @@ -652,19 +643,16 @@ void* OpenNativeLibrary(JNIEnv* env, if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == 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. if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, false /* is_for_vendor */, library_path, nullptr, error_msg)) == nullptr) { std::string create_error_msg; if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */, false /* is_for_vendor */, library_path, nullptr, &create_error_msg)) == nullptr) { *error_msg = strdup(create_error_msg.c_str()); return nullptr; } } return OpenNativeLibrary(ns, path, needs_native_bridge, error_msg); return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg); #else UNUSED(env, target_sdk_version, class_loader); Loading Loading @@ -705,35 +693,40 @@ void* OpenNativeLibrary(JNIEnv* env, if (handle != nullptr) { return handle; } *error_msg = NativeBridgeGetError(); *error_msg = strdup(NativeBridgeGetError()); } else { *error_msg = dlerror(); *error_msg = strdup(dlerror()); } } return nullptr; #endif } bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, std::string* error_msg) { bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) { bool success; if (needs_native_bridge) { success = (NativeBridgeUnloadLibrary(handle) == 0); if (!success) { *error_msg = NativeBridgeGetError(); *error_msg = strdup(NativeBridgeGetError()); } } else { success = (dlclose(handle) == 0); if (!success) { *error_msg = dlerror(); *error_msg = strdup(dlerror()); } } return success; } void NativeLoaderFreeErrorMessage(char* msg) { // The error messages get allocated through strdup, so we must call free on them. free(msg); } #if defined(__ANDROID__) void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, std::string* error_msg) { void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, char** error_msg) { if (ns->is_android_namespace()) { android_dlextinfo extinfo; extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; Loading @@ -741,14 +734,14 @@ void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo); if (handle == nullptr) { *error_msg = dlerror(); *error_msg = strdup(dlerror()); } *needs_native_bridge = false; return handle; } else { void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns()); if (handle == nullptr) { *error_msg = NativeBridgeGetError(); *error_msg = strdup(NativeBridgeGetError()); } *needs_native_bridge = true; return handle; Loading