Check for unknown flags passed to dlopen(3).
Change-Id: I56f4aab0e5a1487bc32d2c4d231e8bd15c4ac8da
This commit is contained in:
parent
4c4b08a32e
commit
e66190d2a9
6 changed files with 46 additions and 21 deletions
|
@ -8,21 +8,21 @@ else
|
|||
endif
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
arch/$(TARGET_ARCH)/begin.$(linker_begin_extension) \
|
||||
debugger.cpp \
|
||||
dlfcn.cpp \
|
||||
linker.cpp \
|
||||
linker_environ.cpp \
|
||||
linker_format.cpp \
|
||||
linker_phdr.cpp \
|
||||
rt.cpp
|
||||
arch/$(TARGET_ARCH)/begin.$(linker_begin_extension) \
|
||||
debugger.cpp \
|
||||
dlfcn.cpp \
|
||||
linker.cpp \
|
||||
linker_environ.cpp \
|
||||
linker_format.cpp \
|
||||
linker_phdr.cpp \
|
||||
rt.cpp
|
||||
|
||||
LOCAL_LDFLAGS := -shared
|
||||
|
||||
LOCAL_CFLAGS += -fno-stack-protector \
|
||||
-Wstrict-overflow=5 \
|
||||
-fvisibility=hidden \
|
||||
-Wall -Wextra
|
||||
-Wall -Wextra -Werror
|
||||
|
||||
# We need to access Bionic private headers in the linker...
|
||||
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/
|
||||
|
|
|
@ -55,9 +55,9 @@ const char* dlerror() {
|
|||
return old_value;
|
||||
}
|
||||
|
||||
void* dlopen(const char* filename, int flag) {
|
||||
void* dlopen(const char* filename, int flags) {
|
||||
ScopedPthreadMutexLocker locker(&gDlMutex);
|
||||
soinfo* result = do_dlopen(filename);
|
||||
soinfo* result = do_dlopen(filename, flags);
|
||||
if (result == NULL) {
|
||||
__bionic_format_dlerror("dlopen failed", linker_get_error());
|
||||
return NULL;
|
||||
|
|
|
@ -966,7 +966,11 @@ static int soinfo_unload(soinfo* si) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
soinfo* do_dlopen(const char* name) {
|
||||
soinfo* do_dlopen(const char* name, int flags) {
|
||||
if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL)) != 0) {
|
||||
DL_ERR("invalid flags to dlopen: %x", flags);
|
||||
return NULL;
|
||||
}
|
||||
set_soinfo_pool_protection(PROT_READ | PROT_WRITE);
|
||||
soinfo* si = find_library(name);
|
||||
if (si != NULL) {
|
||||
|
|
|
@ -207,7 +207,7 @@ extern soinfo libdl_info;
|
|||
#define DT_PREINIT_ARRAYSZ 33
|
||||
#endif
|
||||
|
||||
soinfo* do_dlopen(const char* name);
|
||||
soinfo* do_dlopen(const char* name, int flags);
|
||||
int do_dlclose(soinfo* si);
|
||||
|
||||
Elf32_Sym* lookup(const char* name, soinfo** found, soinfo* start);
|
||||
|
|
|
@ -68,7 +68,7 @@ test_src_files = \
|
|||
|
||||
test_dynamic_ldflags = -Wl,--export-dynamic -Wl,-u,DlSymTestFunction
|
||||
test_dynamic_src_files = \
|
||||
dlopen_test.cpp \
|
||||
dlfcn_test.cpp \
|
||||
|
||||
# Build tests for the device (with bionic's .so). Run with:
|
||||
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
|
||||
|
|
|
@ -32,7 +32,7 @@ extern "C" void DlSymTestFunction() {
|
|||
gCalled = true;
|
||||
}
|
||||
|
||||
TEST(dlopen, dlsym_in_self) {
|
||||
TEST(dlfcn, dlsym_in_self) {
|
||||
dlerror(); // Clear any pending errors.
|
||||
void* self = dlopen(NULL, RTLD_NOW);
|
||||
ASSERT_TRUE(self != NULL);
|
||||
|
@ -50,7 +50,7 @@ TEST(dlopen, dlsym_in_self) {
|
|||
ASSERT_EQ(0, dlclose(self));
|
||||
}
|
||||
|
||||
TEST(dlopen, dlopen_failure) {
|
||||
TEST(dlfcn, dlopen_failure) {
|
||||
void* self = dlopen("/does/not/exist", RTLD_NOW);
|
||||
ASSERT_TRUE(self == NULL);
|
||||
#if __BIONIC__
|
||||
|
@ -65,7 +65,7 @@ static void* ConcurrentDlErrorFn(void*) {
|
|||
return reinterpret_cast<void*>(strdup(dlerror()));
|
||||
}
|
||||
|
||||
TEST(dlopen, dlerror_concurrent) {
|
||||
TEST(dlfcn, dlerror_concurrent) {
|
||||
dlopen("/main/thread", RTLD_NOW);
|
||||
const char* main_thread_error = dlerror();
|
||||
ASSERT_SUBSTR("/main/thread", main_thread_error);
|
||||
|
@ -81,7 +81,7 @@ TEST(dlopen, dlerror_concurrent) {
|
|||
ASSERT_SUBSTR("/main/thread", main_thread_error);
|
||||
}
|
||||
|
||||
TEST(dlopen, dlsym_failures) {
|
||||
TEST(dlfcn, dlsym_failures) {
|
||||
dlerror(); // Clear any pending errors.
|
||||
void* self = dlopen(NULL, RTLD_NOW);
|
||||
ASSERT_TRUE(self != NULL);
|
||||
|
@ -114,7 +114,7 @@ TEST(dlopen, dlsym_failures) {
|
|||
ASSERT_EQ(0, dlclose(self));
|
||||
}
|
||||
|
||||
TEST(dlopen, dladdr) {
|
||||
TEST(dlfcn, dladdr) {
|
||||
dlerror(); // Clear any pending errors.
|
||||
void* self = dlopen(NULL, RTLD_NOW);
|
||||
ASSERT_TRUE(self != NULL);
|
||||
|
@ -174,7 +174,7 @@ TEST(dlopen, dladdr) {
|
|||
ASSERT_EQ(0, dlclose(self));
|
||||
}
|
||||
|
||||
TEST(dlopen, dladdr_invalid) {
|
||||
TEST(dlfcn, dladdr_invalid) {
|
||||
Dl_info info;
|
||||
|
||||
dlerror(); // Clear any pending errors.
|
||||
|
@ -190,10 +190,31 @@ TEST(dlopen, dladdr_invalid) {
|
|||
|
||||
#if __BIONIC__
|
||||
// Our dynamic linker doesn't support GNU hash tables.
|
||||
TEST(dlopen, library_with_only_gnu_hash) {
|
||||
TEST(dlfcn, dlopen_library_with_only_gnu_hash) {
|
||||
dlerror(); // Clear any pending errors.
|
||||
void* handle = dlopen("no-elf-hash-table-library.so", RTLD_NOW);
|
||||
ASSERT_TRUE(handle == NULL);
|
||||
ASSERT_STREQ("dlopen failed: empty/missing DT_HASH in \"no-elf-hash-table-library.so\" (built with --hash-style=gnu?)", dlerror());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(dlfcn, dlopen_bad_flags) {
|
||||
dlerror(); // Clear any pending errors.
|
||||
void* handle;
|
||||
|
||||
#ifdef __GLIBC__
|
||||
// glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags.
|
||||
handle = dlopen(NULL, 0);
|
||||
ASSERT_TRUE(handle == NULL);
|
||||
ASSERT_SUBSTR("invalid", dlerror());
|
||||
#endif
|
||||
|
||||
handle = dlopen(NULL, 0xffffffff);
|
||||
ASSERT_TRUE(handle == NULL);
|
||||
ASSERT_SUBSTR("invalid", dlerror());
|
||||
|
||||
// glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we.
|
||||
handle = dlopen(NULL, RTLD_NOW|RTLD_LAZY);
|
||||
ASSERT_TRUE(handle != NULL);
|
||||
ASSERT_SUBSTR(NULL, dlerror());
|
||||
}
|
Loading…
Reference in a new issue