diff options
Diffstat (limited to 'tests/dlext_test.cpp')
-rw-r--r-- | tests/dlext_test.cpp | 100 |
1 files changed, 82 insertions, 18 deletions
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp index da63046..7f706c1 100644 --- a/tests/dlext_test.cpp +++ b/tests/dlext_test.cpp @@ -31,7 +31,7 @@ #define ASSERT_DL_NOTNULL(ptr) \ - ASSERT_TRUE(ptr != NULL) << "dlerror: " << dlerror() + ASSERT_TRUE(ptr != nullptr) << "dlerror: " << dlerror() #define ASSERT_DL_ZERO(i) \ ASSERT_EQ(0, i) << "dlerror: " << dlerror() @@ -46,23 +46,31 @@ typedef int (*fn)(void); #define LIBSIZE 1024*1024 // how much address space to reserve for it #if defined(__LP64__) -#define LIBPATH "%s/nativetest64/libdlext_test_fd/libdlext_test_fd.so" +#define LIBPATH_PREFIX "%s/nativetest64/libdlext_test_fd/" #else -#define LIBPATH "%s/nativetest/libdlext_test_fd/libdlext_test_fd.so" +#define LIBPATH_PREFIX "%s/nativetest/libdlext_test_fd/" #endif +#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd.so" +#define LIBZIPPATH LIBPATH_PREFIX "libdlext_test_fd_zipaligned.zip" + +#define LIBZIP_OFFSET 2*PAGE_SIZE + class DlExtTest : public ::testing::Test { protected: virtual void SetUp() { - handle_ = NULL; + handle_ = nullptr; // verify that we don't have the library loaded already - ASSERT_EQ(NULL, dlsym(RTLD_DEFAULT, "getRandomNumber")); + void* h = dlopen(LIBNAME, RTLD_NOW | RTLD_NOLOAD); + ASSERT_TRUE(h == nullptr); + h = dlopen(LIBNAME_NORELRO, RTLD_NOW | RTLD_NOLOAD); + ASSERT_TRUE(h == nullptr); // call dlerror() to swallow the error, and check it was the one we wanted - ASSERT_STREQ("undefined symbol: getRandomNumber", dlerror()); + ASSERT_STREQ("dlopen failed: library \"" LIBNAME_NORELRO "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror()); } virtual void TearDown() { - if (handle_ != NULL) { + if (handle_ != nullptr) { ASSERT_DL_ZERO(dlclose(handle_)); } } @@ -71,7 +79,7 @@ protected: }; TEST_F(DlExtTest, ExtInfoNull) { - handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, NULL); + handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, nullptr); ASSERT_DL_NOTNULL(handle_); fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); ASSERT_DL_NOTNULL(f); @@ -90,7 +98,7 @@ TEST_F(DlExtTest, ExtInfoNoFlags) { TEST_F(DlExtTest, ExtInfoUseFd) { const char* android_data = getenv("ANDROID_DATA"); - ASSERT_TRUE(android_data != NULL); + ASSERT_TRUE(android_data != nullptr); char lib_path[PATH_MAX]; snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data); @@ -105,8 +113,64 @@ TEST_F(DlExtTest, ExtInfoUseFd) { EXPECT_EQ(4, f()); } +TEST_F(DlExtTest, ExtInfoUseFdWithOffset) { + const char* android_data = getenv("ANDROID_DATA"); + ASSERT_TRUE(android_data != nullptr); + + char lib_path[PATH_MAX]; + snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data); + + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET; + extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC)); + extinfo.library_fd_offset = LIBZIP_OFFSET; + + handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo); + ASSERT_DL_NOTNULL(handle_); + + fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber")); + ASSERT_DL_NOTNULL(f); + EXPECT_EQ(4, f()); +} + +TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) { + const char* android_data = getenv("ANDROID_DATA"); + ASSERT_TRUE(android_data != nullptr); + + char lib_path[PATH_MAX]; + snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data); + + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET; + extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC)); + extinfo.library_fd_offset = 17; + + handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo); + ASSERT_TRUE(handle_ == nullptr); + ASSERT_STREQ("dlopen failed: file offset for the library \"libname_placeholder\" is not page-aligned: 17", dlerror()); + + extinfo.library_fd_offset = (5LL<<58) + PAGE_SIZE; + handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo); + + ASSERT_TRUE(handle_ == nullptr); + // TODO: Better error message when reading with offset > file_size + ASSERT_STREQ("dlopen failed: \"libname_placeholder\" has bad ELF magic", dlerror()); + + close(extinfo.library_fd); +} + +TEST_F(DlExtTest, ExtInfoUseOffsetWihtoutFd) { + android_dlextinfo extinfo; + extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET; + extinfo.library_fd_offset = LIBZIP_OFFSET; + + handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo); + ASSERT_TRUE(handle_ == nullptr); + ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror()); +} + TEST_F(DlExtTest, Reserved) { - void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_TRUE(start != MAP_FAILED); android_dlextinfo extinfo; @@ -124,7 +188,7 @@ TEST_F(DlExtTest, Reserved) { } TEST_F(DlExtTest, ReservedTooSmall) { - void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_TRUE(start != MAP_FAILED); android_dlextinfo extinfo; @@ -132,11 +196,11 @@ TEST_F(DlExtTest, ReservedTooSmall) { extinfo.reserved_addr = start; extinfo.reserved_size = PAGE_SIZE; handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo); - EXPECT_EQ(NULL, handle_); + EXPECT_EQ(nullptr, handle_); } TEST_F(DlExtTest, ReservedHint) { - void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_TRUE(start != MAP_FAILED); android_dlextinfo extinfo; @@ -154,7 +218,7 @@ TEST_F(DlExtTest, ReservedHint) { } TEST_F(DlExtTest, ReservedHintTooSmall) { - void* start = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + void* start = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_TRUE(start != MAP_FAILED); android_dlextinfo extinfo; @@ -174,7 +238,7 @@ class DlExtRelroSharingTest : public DlExtTest { protected: virtual void SetUp() { DlExtTest::SetUp(); - void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, + void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_TRUE(start != MAP_FAILED); extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS; @@ -183,7 +247,7 @@ protected: extinfo_.relro_fd = -1; const char* android_data = getenv("ANDROID_DATA"); - ASSERT_TRUE(android_data != NULL); + ASSERT_TRUE(android_data != nullptr); snprintf(relro_file_, sizeof(relro_file_), "%s/local/tmp/libdlext_test.relro", android_data); } @@ -204,7 +268,7 @@ protected: extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO; extinfo_.relro_fd = relro_fd; void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_); - if (handle == NULL) { + if (handle == nullptr) { fprintf(stderr, "in child: %s\n", dlerror()); exit(1); } @@ -327,7 +391,7 @@ void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool sha } else { handle = dlopen(lib, RTLD_NOW); } - if (handle == NULL) { + if (handle == nullptr) { fprintf(stderr, "in child: %s\n", dlerror()); exit(1); } |