diff options
-rw-r--r-- | linker/linker.cpp | 2 | ||||
-rw-r--r-- | linker/linker_globals.h | 14 | ||||
-rw-r--r-- | tests/dlext_test.cpp | 48 | ||||
-rw-r--r-- | tests/libs/Android.bp | 10 |
4 files changed, 73 insertions, 1 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index ec92c9205..5f906c87a 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -1433,6 +1433,8 @@ static bool find_library_internal(android_namespace_t* ns, if (search_linked_namespaces) { // if a library was not found - look into linked namespaces + // preserve current dlerror in the case it fails. + DlErrorRestorer dlerror_restorer; for (auto& linked_namespace : ns->linked_namespaces()) { if (find_library_in_linked_namespace(linked_namespace, task)) { diff --git a/linker/linker_globals.h b/linker/linker_globals.h index d8134afc4..11ccbd54a 100644 --- a/linker/linker_globals.h +++ b/linker/linker_globals.h @@ -32,6 +32,7 @@ #include <link.h> #include <stddef.h> +#include <string> #include <unordered_map> #include <async_safe/log.h> @@ -39,7 +40,6 @@ #define DL_ERR(fmt, x...) \ do { \ async_safe_format_buffer(linker_get_error_buffer(), linker_get_error_buffer_size(), fmt, ##x); \ - /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \ } while (false) #define DL_WARN(fmt, x...) \ @@ -75,4 +75,16 @@ extern std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map; char* linker_get_error_buffer(); size_t linker_get_error_buffer_size(); +class DlErrorRestorer { + public: + DlErrorRestorer() { + saved_error_msg_ = linker_get_error_buffer(); + } + ~DlErrorRestorer() { + strlcpy(linker_get_error_buffer(), saved_error_msg_.c_str(), linker_get_error_buffer_size()); + } + private: + std::string saved_error_msg_; +}; + #endif /* __LINKER_GLOBALS_H */ diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp index 7028ca77e..3f6da59ca 100644 --- a/tests/dlext_test.cpp +++ b/tests/dlext_test.cpp @@ -1589,6 +1589,54 @@ TEST(dlext, ns_isolated_rtld_global) { ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror()); } +TEST(dlext, ns_inaccessible_error_message) { + // We set up 2 namespaces (a and b) and link a->b with a shared library + // libtestshared.so. Then try to dlopen different library with the same + // name from in namespace a. Note that library should not be accessible + // in either namespace but since it's soname is in the list of shared libs + // the linker will attempt to find it in linked namespace. + // + // Check the error message and make sure it mentions correct namespace name. + ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr)); + + android_namespace_t* ns_a = + android_create_namespace("ns_a", + nullptr, + (get_testlib_root() + "/private_namespace_libs").c_str(), + ANDROID_NAMESPACE_TYPE_ISOLATED, + nullptr, + nullptr); + ASSERT_TRUE(ns_a != nullptr) << dlerror(); + ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror(); + + android_namespace_t* ns_b = + android_create_namespace("ns_b", + nullptr, + get_testlib_root().c_str(), + ANDROID_NAMESPACE_TYPE_ISOLATED, + nullptr, + nullptr); + ASSERT_TRUE(ns_b != nullptr) << dlerror(); + ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror(); + + ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror(); + + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; + extinfo.library_namespace = ns_a; + + std::string library_path = get_testlib_root() + "/inaccessible_libs/libtestshared.so"; + + void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo); + ASSERT_TRUE(handle == nullptr); + std::string expected_dlerror = + android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\"" + " is not accessible for the namespace \"ns_a\"", + library_path.c_str(), + get_executable_path().c_str()); + ASSERT_EQ(expected_dlerror, dlerror()); +} + TEST(dlext, ns_anonymous) { static const char* root_lib = "libnstest_root.so"; std::string shared_libs = g_core_shared_libs + ":" + g_public_lib; diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp index ba0b1aaf7..5f2738794 100644 --- a/tests/libs/Android.bp +++ b/tests/libs/Android.bp @@ -440,6 +440,16 @@ cc_test_library { } // ----------------------------------------------------------------------------- +// Library for inaccessible shared library test +// ----------------------------------------------------------------------------- +cc_test_library { + name: "libtestshared", + defaults: ["bionic_testlib_defaults"], + srcs: ["empty.cpp"], + relative_install_path: "/inaccessible_libs", +} + +// ----------------------------------------------------------------------------- // Library with weak undefined function // ----------------------------------------------------------------------------- cc_test_library { |