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
(cherry picked from commit 69c68c46ac)
This commit is contained in:
dimitry 2018-05-09 15:22:38 +02:00
parent e0906d8f55
commit 8b142566e3
4 changed files with 40 additions and 2 deletions

View File

@ -3822,8 +3822,14 @@ std::vector<android_namespace_t*> 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
}

View File

@ -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<const char*> needed_library_name_list;
size_t ld_preloads_count = 0;

View File

@ -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();

View File

@ -14,13 +14,37 @@
* limitations under the License.
*/
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#if __has_include(<sys/auxv.h>)
#include <sys/auxv.h>
#endif
#include <unistd.h>
extern int get_value_from_lib();
int main() {
bool skip_vdso_check = false;
#if __has_include(<sys/auxv.h>)
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;
}