diff options
| -rw-r--r-- | include/nativebridge/native_bridge.h | 106 | ||||
| -rw-r--r-- | libnativebridge/native_bridge.cc | 19 | ||||
| -rw-r--r-- | libnativebridge/tests/Android.mk | 2 | ||||
| -rw-r--r-- | libnativebridge/tests/DummyNativeBridge3.cpp | 50 | ||||
| -rw-r--r-- | libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp (renamed from libnativebridge/tests/NativeBridge3InitNamespace_test.cpp) | 24 | ||||
| -rw-r--r-- | libnativeloader/native_loader.cpp | 9 |
6 files changed, 137 insertions, 73 deletions
diff --git a/include/nativebridge/native_bridge.h b/include/nativebridge/native_bridge.h index 45266dedf..929b8aec4 100644 --- a/include/nativebridge/native_bridge.h +++ b/include/nativebridge/native_bridge.h @@ -116,14 +116,25 @@ struct native_bridge_namespace_t; // Use NativeBridgeIsSupported() instead in non-namespace scenario. bool NativeBridgeIsPathSupported(const char* path); -// Initializes public and anonymous namespace at native bridge side. +// Initializes anonymous namespace. +// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker. +// +// The anonymous namespace is used in the case when a NativeBridge implementation +// cannot identify the caller of dlopen/dlsym which happens for the code not loaded +// by dynamic linker; for example calls from the mono-compiled code. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. -bool NativeBridgeInitNamespace(const char* public_ns_sonames, - const char* anon_ns_library_path); +bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames, + const char* anon_ns_library_path); -// Create a namespace and pass the key of related namespaces to native bridge. +// Create new namespace in which native libraries will be loaded. +// NativeBridge's peer of android_create_namespace() of dynamic linker. +// +// The libraries in the namespace are searched by folowing order: +// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH) +// 2. In directories specified by DT_RUNPATH of the "needed by" binary. +// 3. deault_library_path (This of this as namespace-local default library path) // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. @@ -134,7 +145,17 @@ native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns); +// Creates a link which shares some libraries from one namespace to another. +// NativeBridge's peer of android_link_namespaces() of dynamic linker. +// +// Starting with v3, NativeBridge has two scenarios: with/without namespace. +// Should not use in non-namespace scenario. +bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to, + const char* shared_libs_sonames); + // Load a shared library with namespace key that is supported by the native bridge. +// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace +// extension. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Use NativeBridgeLoadLibrary() instead in non-namespace scenario. @@ -152,7 +173,7 @@ struct NativeBridgeCallbacks { // Parameters: // runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks. // Returns: - // true iff initialization was successful. + // true if initialization was successful. bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir, const char* instruction_set); @@ -194,10 +215,10 @@ struct NativeBridgeCallbacks { // instruction set. // // Parameters: - // instruction_set [IN] the instruction set of the app + // instruction_set [IN] the instruction set of the app // Returns: - // NULL if not supported by native bridge. - // Otherwise, return all environment values to be set after fork. + // NULL if not supported by native bridge. + // Otherwise, return all environment values to be set after fork. const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set); // Added callbacks in version 2. @@ -206,9 +227,9 @@ struct NativeBridgeCallbacks { // forwards- or backwards-compatible, and libnativebridge will then stop using it. // // Parameters: - // bridge_version [IN] the version of libnativebridge. + // bridge_version [IN] the version of libnativebridge. // Returns: - // true iff the native bridge supports the given version of libnativebridge. + // true if the native bridge supports the given version of libnativebridge. bool (*isCompatibleWith)(uint32_t bridge_version); // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime @@ -217,12 +238,12 @@ struct NativeBridgeCallbacks { // that will potentially lead to cycles. // // Parameters: - // signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is + // signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is // supported by the runtime. // Returns: - // NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the - // runtime. - // Otherwise, a pointer to the signal handler. + // NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the + // runtime. + // Otherwise, a pointer to the signal handler. NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal); // Added callbacks in version 3. @@ -231,7 +252,7 @@ struct NativeBridgeCallbacks { // to zero then the dynamic library is unloaded. // // Parameters: - // handle [IN] the handler of a dynamic library. + // handle [IN] the handler of a dynamic library. // // Returns: // 0 on success, and nonzero on error. @@ -257,33 +278,36 @@ struct NativeBridgeCallbacks { // Use isSupported instead in non-namespace scenario. bool (*isPathSupported)(const char* library_path); - // Initializes anonymous namespace at native bridge side and pass the key of - // two namespaces(default and anonymous) owned by dynamic linker to native bridge. + // Initializes anonymous namespace at native bridge side. + // NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker. + // + // The anonymous namespace is used in the case when a NativeBridge implementation + // cannot identify the caller of dlopen/dlsym which happens for the code not loaded + // by dynamic linker; for example calls from the mono-compiled code. // // Parameters: - // public_ns_sonames [IN] the name of "public" libraries. - // anon_ns_library_path [IN] the library search path of (anonymous) namespace. + // public_ns_sonames [IN] the name of "public" libraries. + // anon_ns_library_path [IN] the library search path of (anonymous) namespace. // Returns: - // true if the pass is ok. - // Otherwise, false. + // true if the pass is ok. + // Otherwise, false. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. - bool (*initNamespace)(const char* public_ns_sonames, - const char* anon_ns_library_path); - + bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path); - // Create a namespace and pass the key of releated namespaces to native bridge. + // Create new namespace in which native libraries will be loaded. + // NativeBridge's peer of android_create_namespace() of dynamic linker. // // Parameters: - // name [IN] the name of the namespace. - // ld_library_path [IN] the first set of library search paths of the namespace. - // default_library_path [IN] the second set of library search path of the namespace. - // type [IN] the attribute of the namespace. - // permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is). - // parent_ns [IN] the pointer of the parent namespace to be inherited from. + // name [IN] the name of the namespace. + // ld_library_path [IN] the first set of library search paths of the namespace. + // default_library_path [IN] the second set of library search path of the namespace. + // type [IN] the attribute of the namespace. + // permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is). + // parent_ns [IN] the pointer of the parent namespace to be inherited from. // Returns: - // native_bridge_namespace_t* for created namespace or nullptr in the case of error. + // native_bridge_namespace_t* for created namespace or nullptr in the case of error. // // Starting with v3, NativeBridge has two scenarios: with/without namespace. // Should not use in non-namespace scenario. @@ -294,7 +318,25 @@ struct NativeBridgeCallbacks { const char* permitted_when_isolated_path, native_bridge_namespace_t* parent_ns); + // Creates a link which shares some libraries from one namespace to another. + // NativeBridge's peer of android_link_namespaces() of dynamic linker. + // + // Parameters: + // from [IN] the namespace where libraries are accessed. + // to [IN] the namespace where libraries are loaded. + // shared_libs_sonames [IN] the libraries to be shared. + // + // Returns: + // Whether successed or not. + // + // Starting with v3, NativeBridge has two scenarios: with/without namespace. + // Should not use in non-namespace scenario. + bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to, + const char* shared_libs_sonames); + // Load a shared library within a namespace. + // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace + // extension. // // Parameters: // libpath [IN] path to the shared library diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc index 83f35b1e8..050373ae5 100644 --- a/libnativebridge/native_bridge.cc +++ b/libnativebridge/native_bridge.cc @@ -573,11 +573,11 @@ bool NativeBridgeIsPathSupported(const char* path) { return false; } -bool NativeBridgeInitNamespace(const char* public_ns_sonames, - const char* anon_ns_library_path) { +bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames, + const char* anon_ns_library_path) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { - return callbacks->initNamespace(public_ns_sonames, anon_ns_library_path); + return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path); } else { ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); } @@ -608,6 +608,19 @@ native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, return nullptr; } +bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to, + const char* shared_libs_sonames) { + if (NativeBridgeInitialized()) { + if (isCompatibleWith(NAMESPACE_VERSION)) { + return callbacks->linkNamespaces(from, to, shared_libs_sonames); + } else { + ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); + } + } + + return false; +} + void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) { if (NativeBridgeInitialized()) { if (isCompatibleWith(NAMESPACE_VERSION)) { diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk index 4c3e86298..c9468f033 100644 --- a/libnativebridge/tests/Android.mk +++ b/libnativebridge/tests/Android.mk @@ -24,7 +24,7 @@ test_src_files := \ NativeBridge3UnloadLibrary_test.cpp \ NativeBridge3GetError_test.cpp \ NativeBridge3IsPathSupported_test.cpp \ - NativeBridge3InitNamespace_test.cpp \ + NativeBridge3InitAnonymousNamespace_test.cpp \ NativeBridge3CreateNamespace_test.cpp \ NativeBridge3LoadLibraryExt_test.cpp diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp index 13fce8599..4ef1c8273 100644 --- a/libnativebridge/tests/DummyNativeBridge3.cpp +++ b/libnativebridge/tests/DummyNativeBridge3.cpp @@ -76,8 +76,8 @@ extern "C" bool native_bridge3_isPathSupported(const char* /* path */) { return true; } -extern "C" bool native_bridge3_initNamespace(const char* /* public_ns_sonames */, - const char* /* anon_ns_library_path */) { +extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */, + const char* /* anon_ns_library_path */) { return true; } @@ -91,30 +91,34 @@ native_bridge3_createNamespace(const char* /* name */, return nullptr; } +extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */, + android::native_bridge_namespace_t* /* to */, + const char* /* shared_libs_soname */) { + return true; +} + extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */, int /* flag */, android::native_bridge_namespace_t* /* ns */) { return nullptr; } - -android::NativeBridgeCallbacks NativeBridgeItf { - // v1 - .version = 3, - .initialize = &native_bridge3_initialize, - .loadLibrary = &native_bridge3_loadLibrary, - .getTrampoline = &native_bridge3_getTrampoline, - .isSupported = &native_bridge3_isSupported, - .getAppEnv = &native_bridge3_getAppEnv, - // v2 - .isCompatibleWith = &native_bridge3_isCompatibleWith, - .getSignalHandler = &native_bridge3_getSignalHandler, - // v3 - .unloadLibrary = &native_bridge3_unloadLibrary, - .getError = &native_bridge3_getError, - .isPathSupported = &native_bridge3_isPathSupported, - .initNamespace = &native_bridge3_initNamespace, - .createNamespace = &native_bridge3_createNamespace, - .loadLibraryExt = &native_bridge3_loadLibraryExt -}; - +android::NativeBridgeCallbacks NativeBridgeItf{ + // v1 + .version = 3, + .initialize = &native_bridge3_initialize, + .loadLibrary = &native_bridge3_loadLibrary, + .getTrampoline = &native_bridge3_getTrampoline, + .isSupported = &native_bridge3_isSupported, + .getAppEnv = &native_bridge3_getAppEnv, + // v2 + .isCompatibleWith = &native_bridge3_isCompatibleWith, + .getSignalHandler = &native_bridge3_getSignalHandler, + // v3 + .unloadLibrary = &native_bridge3_unloadLibrary, + .getError = &native_bridge3_getError, + .isPathSupported = &native_bridge3_isPathSupported, + .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace, + .createNamespace = &native_bridge3_createNamespace, + .linkNamespaces = &native_bridge3_linkNamespaces, + .loadLibraryExt = &native_bridge3_loadLibraryExt}; diff --git a/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp index ae0fd2b02..b0d6b09d1 100644 --- a/libnativebridge/tests/NativeBridge3InitNamespace_test.cpp +++ b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp @@ -20,20 +20,20 @@ namespace android { constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so"; -TEST_F(NativeBridgeTest, V3_InitNamespace) { - // Init - ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr)); - ASSERT_TRUE(NativeBridgeAvailable()); - ASSERT_TRUE(PreInitializeNativeBridge(".", "isa")); - ASSERT_TRUE(NativeBridgeAvailable()); - ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr)); - ASSERT_TRUE(NativeBridgeAvailable()); +TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) { + // Init + ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr)); + ASSERT_TRUE(NativeBridgeAvailable()); + ASSERT_TRUE(PreInitializeNativeBridge(".", "isa")); + ASSERT_TRUE(NativeBridgeAvailable()); + ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr)); + ASSERT_TRUE(NativeBridgeAvailable()); - ASSERT_EQ(3U, NativeBridgeGetVersion()); - ASSERT_EQ(true, NativeBridgeInitNamespace(nullptr, nullptr)); + ASSERT_EQ(3U, NativeBridgeGetVersion()); + ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr)); - // Clean-up code_cache - ASSERT_EQ(0, rmdir(kCodeCache)); + // Clean-up code_cache + ASSERT_EQ(0, rmdir(kCodeCache)); } } // namespace android diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp index 74f2f1d31..f3391d1be 100644 --- a/libnativeloader/native_loader.cpp +++ b/libnativeloader/native_loader.cpp @@ -183,6 +183,11 @@ class LibraryNamespaces { return false; } + if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) { + *error_msg = NativeBridgeGetError(); + return false; + } + native_loader_ns = NativeLoaderNamespace(ns); } @@ -324,8 +329,8 @@ class LibraryNamespaces { // and now initialize native bridge namespaces if necessary. if (NativeBridgeInitialized()) { - initialized_ = NativeBridgeInitNamespace(public_libraries_.c_str(), - is_native_bridge ? library_path : nullptr); + initialized_ = NativeBridgeInitAnonymousNamespace(public_libraries_.c_str(), + is_native_bridge ? library_path : nullptr); if (!initialized_) { *error_msg = NativeBridgeGetError(); } |
