diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index 3862d8ca3..a5ccd0f27 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -154,6 +154,10 @@ static void add_vdso(KernelArgumentBlock& args) { si->prelink_image(); si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr); + // prevents accidental unloads... + si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_NODELETE); + si->set_linked(); + si->call_constructors(); } /* gdb expects the linker to be in the debug shared object list. @@ -352,6 +356,8 @@ 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; @@ -393,8 +399,6 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { si->increment_ref_count(); } - add_vdso(args); - if (!get_cfi_shadow()->InitialLinkDone(solist)) __linker_cannot_link(g_argv[0]); si->call_pre_init_constructors(); diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index 1e2b6c99c..66ea0f962 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -245,6 +245,12 @@ TEST(dlfcn, dlopen_by_soname) { dlclose(handle); } +TEST(dlfcn, dlopen_vdso) { + void* handle = dlopen("linux-vdso.so.1", RTLD_NOW); + ASSERT_TRUE(handle != nullptr) << dlerror(); + dlclose(handle); +} + // mips doesn't support ifuncs #if !defined(__mips__) TEST(dlfcn, ifunc_variable) {