From 69c68c46ac18a440bf1c0447d8343a6dbad595f1 Mon Sep 17 00:00:00 2001 From: dimitry Date: Wed, 9 May 2018 15:22:38 +0200 Subject: [PATCH] vdso should be available in all namespaces vdso should be available in all namespaces when present. This bug went undetected because the way libc currently uses vdso (it does all the lookups itself). This makes it available for the programs that want to take advantage by dlopening it. Bug: http://b/73105445 Bug: http://b/79561555 Test: adb shell /data/nativetest/arm/bionic-unit-tests/bionic-unit-tests --gtest_filter=dl.exec_with_ld_config_file Test: adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests --gtest_filter=dl* Change-Id: I8eae0c9848f256190d1c9ec85d10dc6ce383a8bc --- linker/linker.cpp | 6 ++++++ linker/linker_main.cpp | 11 +++++++++-- linker/linker_main.h | 1 + tests/libs/ld_config_test_helper.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/linker/linker.cpp b/linker/linker.cpp index 32df9113d..a0205dc3c 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -3826,8 +3826,14 @@ std::vector init_default_namespaces(const char* executable // we can no longer rely on the fact that libdl.so is part of default namespace // this is why we want to add ld-android.so to all namespaces from ld.config.txt soinfo* ld_android_so = solist_get_head(); + + // we also need vdso to be available for all namespaces (if present) + soinfo* vdso = solist_get_vdso(); for (auto it : namespaces) { it.second->add_soinfo(ld_android_so); + if (vdso != nullptr) { + it.second->add_soinfo(vdso); + } // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked } diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index dc1fa7550..00c72d02a 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -64,6 +64,7 @@ static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf); static soinfo* solist; static soinfo* sonext; static soinfo* somain; // main process, always the one after libdl_info +static soinfo* vdso; // vdso if present void solist_add_soinfo(soinfo* si) { sonext->next = si; @@ -104,6 +105,10 @@ soinfo* solist_get_somain() { return somain; } +soinfo* solist_get_vdso() { + return vdso; +} + int g_ld_debug_verbosity; abort_msg_t* g_abort_message = nullptr; // For debuggerd. @@ -158,6 +163,8 @@ static void add_vdso(KernelArgumentBlock& args) { si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_NODELETE); si->set_linked(); si->call_constructors(); + + vdso = si; } /* gdb expects the linker to be in the debug shared object list. @@ -280,6 +287,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { } } + add_vdso(args); + struct stat file_stat; // Stat "/proc/self/exe" instead of executable_path because // the executable could be unlinked by this point and it should @@ -366,8 +375,6 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { } } - add_vdso(args); - // Load ld_preloads and dependencies. std::vector needed_library_name_list; size_t ld_preloads_count = 0; diff --git a/linker/linker_main.h b/linker/linker_main.h index 8d486e846..b37b9472f 100644 --- a/linker/linker_main.h +++ b/linker/linker_main.h @@ -70,3 +70,4 @@ void solist_add_soinfo(soinfo* si); bool solist_remove_soinfo(soinfo* si); soinfo* solist_get_head(); soinfo* solist_get_somain(); +soinfo* solist_get_vdso(); diff --git a/tests/libs/ld_config_test_helper.cpp b/tests/libs/ld_config_test_helper.cpp index 592e8c0b1..87e512eff 100644 --- a/tests/libs/ld_config_test_helper.cpp +++ b/tests/libs/ld_config_test_helper.cpp @@ -14,13 +14,37 @@ * limitations under the License. */ +#include #include #include +#if __has_include() +#include +#endif #include extern int get_value_from_lib(); int main() { + bool skip_vdso_check = false; +#if __has_include() + if (getauxval(AT_SYSINFO_EHDR) == 0) { + skip_vdso_check = true; + } +#endif + + if (!skip_vdso_check) { + const char* vdso_name = "linux-vdso.so.1"; +#if defined(__i386__) + vdso_name = "linux-gate.so.1"; +#endif + void* handle = dlopen(vdso_name, RTLD_NOW); + if (handle == nullptr) { + printf("%s", dlerror()); + return 1; + } + dlclose(handle); + } + printf("%d", get_value_from_lib()); return 0; }