* commit 'b9b75697fa6c58a85f48d7f31113814385a709bd': Handle empty relro segment or incorrectly sized file.
This commit is contained in:
commit
e0a8474adf
@ -591,9 +591,12 @@ int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, El
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
off_t file_size = file_stat.st_size;
|
off_t file_size = file_stat.st_size;
|
||||||
void* temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
void* temp_mapping = NULL;
|
||||||
if (temp_mapping == MAP_FAILED) {
|
if (file_size > 0) {
|
||||||
return -1;
|
temp_mapping = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (temp_mapping == MAP_FAILED) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
size_t file_offset = 0;
|
size_t file_offset = 0;
|
||||||
|
|
||||||
@ -614,6 +617,13 @@ int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, El
|
|||||||
size_t match_offset = 0;
|
size_t match_offset = 0;
|
||||||
size_t size = seg_page_end - seg_page_start;
|
size_t size = seg_page_end - seg_page_start;
|
||||||
|
|
||||||
|
if (file_size - file_offset < size) {
|
||||||
|
// File is too short to compare to this segment. The contents are likely
|
||||||
|
// different as well (it's probably for a different library version) so
|
||||||
|
// just don't bother checking.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
while (match_offset < size) {
|
while (match_offset < size) {
|
||||||
// Skip over dissimilar pages.
|
// Skip over dissimilar pages.
|
||||||
while (match_offset < size &&
|
while (match_offset < size &&
|
||||||
|
@ -198,17 +198,32 @@ include $(LOCAL_PATH)/Android.build.mk
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Library used by dlext tests.
|
# Library used by dlext tests - with/without GNU RELRO program header
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
libdlext_test_src_files := \
|
libdlext_test_src_files := \
|
||||||
dlext_test_library.cpp \
|
dlext_test_library.cpp \
|
||||||
|
|
||||||
|
libdlext_test_ldflags := \
|
||||||
|
-Wl,-z,relro \
|
||||||
|
|
||||||
module := libdlext_test
|
module := libdlext_test
|
||||||
module_tag := optional
|
module_tag := optional
|
||||||
build_type := target
|
build_type := target
|
||||||
build_target := SHARED_LIBRARY
|
build_target := SHARED_LIBRARY
|
||||||
include $(LOCAL_PATH)/Android.build.mk
|
include $(LOCAL_PATH)/Android.build.mk
|
||||||
|
|
||||||
|
libdlext_test_norelro_src_files := \
|
||||||
|
dlext_test_library.cpp \
|
||||||
|
|
||||||
|
libdlext_test_norelro_ldflags := \
|
||||||
|
-Wl,-z,norelro \
|
||||||
|
|
||||||
|
module := libdlext_test_norelro
|
||||||
|
module_tag := optional
|
||||||
|
build_type := target
|
||||||
|
build_target := SHARED_LIBRARY
|
||||||
|
include $(LOCAL_PATH)/Android.build.mk
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# This library used by atexit tests
|
# This library used by atexit tests
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
typedef int (*fn)(void);
|
typedef int (*fn)(void);
|
||||||
#define LIBNAME "libdlext_test.so"
|
#define LIBNAME "libdlext_test.so"
|
||||||
|
#define LIBNAME_NORELRO "libdlext_test_norelro.so"
|
||||||
#define LIBSIZE 1024*1024 // how much address space to reserve for it
|
#define LIBSIZE 1024*1024 // how much address space to reserve for it
|
||||||
|
|
||||||
|
|
||||||
@ -144,52 +145,88 @@ TEST_F(DlExtTest, ReservedHintTooSmall) {
|
|||||||
EXPECT_EQ(4, f());
|
EXPECT_EQ(4, f());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DlExtTest, RelroShareChildWrites) {
|
class DlExtRelroSharingTest : public DlExtTest {
|
||||||
void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
|
protected:
|
||||||
-1, 0);
|
virtual void SetUp() {
|
||||||
ASSERT_TRUE(start != MAP_FAILED);
|
DlExtTest::SetUp();
|
||||||
android_dlextinfo extinfo;
|
void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
|
||||||
extinfo.reserved_addr = start;
|
-1, 0);
|
||||||
extinfo.reserved_size = LIBSIZE;
|
ASSERT_TRUE(start != MAP_FAILED);
|
||||||
|
extinfo_.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
|
||||||
|
extinfo_.reserved_addr = start;
|
||||||
|
extinfo_.reserved_size = LIBSIZE;
|
||||||
|
extinfo_.relro_fd = -1;
|
||||||
|
|
||||||
int relro_fd;
|
const char* android_data = getenv("ANDROID_DATA");
|
||||||
char relro_file[PATH_MAX];
|
ASSERT_TRUE(android_data != NULL);
|
||||||
const char* android_data = getenv("ANDROID_DATA");
|
snprintf(relro_file_, sizeof(relro_file_), "%s/local/tmp/libdlext_test.relro", android_data);
|
||||||
ASSERT_TRUE(android_data != NULL);
|
|
||||||
snprintf(relro_file, sizeof(relro_file), "%s/local/tmp/libdlext_test.relro", android_data);
|
|
||||||
relro_fd = open(relro_file, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
|
||||||
extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO;
|
|
||||||
ASSERT_NOERROR(relro_fd);
|
|
||||||
extinfo.relro_fd = relro_fd;
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
// child process
|
|
||||||
void* handle = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
|
|
||||||
if (handle == NULL) {
|
|
||||||
fprintf(stderr, "in child: %s\n", dlerror());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// continuing in parent
|
virtual void TearDown() {
|
||||||
ASSERT_NOERROR(close(relro_fd));
|
DlExtTest::TearDown();
|
||||||
ASSERT_NOERROR(pid);
|
if (extinfo_.relro_fd != -1) {
|
||||||
int status;
|
ASSERT_NOERROR(close(extinfo_.relro_fd));
|
||||||
ASSERT_EQ(pid, waitpid(pid, &status, 0));
|
}
|
||||||
ASSERT_TRUE(WIFEXITED(status));
|
}
|
||||||
ASSERT_EQ(0, WEXITSTATUS(status));
|
|
||||||
|
|
||||||
relro_fd = open(relro_file, O_RDONLY);
|
void CreateRelroFile(const char* lib) {
|
||||||
ASSERT_NOERROR(relro_fd);
|
int relro_fd = open(relro_file_, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||||
extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_USE_RELRO;
|
ASSERT_NOERROR(relro_fd);
|
||||||
extinfo.relro_fd = relro_fd;
|
|
||||||
handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
|
|
||||||
ASSERT_NOERROR(close(relro_fd));
|
|
||||||
|
|
||||||
ASSERT_DL_NOTNULL(handle_);
|
pid_t pid = fork();
|
||||||
fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
|
if (pid == 0) {
|
||||||
ASSERT_DL_NOTNULL(f);
|
// child process
|
||||||
EXPECT_EQ(4, f());
|
extinfo_.flags |= ANDROID_DLEXT_WRITE_RELRO;
|
||||||
|
extinfo_.relro_fd = relro_fd;
|
||||||
|
void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
|
||||||
|
if (handle == NULL) {
|
||||||
|
fprintf(stderr, "in child: %s\n", dlerror());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// continuing in parent
|
||||||
|
ASSERT_NOERROR(close(relro_fd));
|
||||||
|
ASSERT_NOERROR(pid);
|
||||||
|
int status;
|
||||||
|
ASSERT_EQ(pid, waitpid(pid, &status, 0));
|
||||||
|
ASSERT_TRUE(WIFEXITED(status));
|
||||||
|
ASSERT_EQ(0, WEXITSTATUS(status));
|
||||||
|
|
||||||
|
// reopen file for reading so it can be used
|
||||||
|
relro_fd = open(relro_file_, O_RDONLY);
|
||||||
|
ASSERT_NOERROR(relro_fd);
|
||||||
|
extinfo_.flags |= ANDROID_DLEXT_USE_RELRO;
|
||||||
|
extinfo_.relro_fd = relro_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryUsingRelro(const char* lib) {
|
||||||
|
handle_ = android_dlopen_ext(lib, RTLD_NOW, &extinfo_);
|
||||||
|
ASSERT_DL_NOTNULL(handle_);
|
||||||
|
fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
|
||||||
|
ASSERT_DL_NOTNULL(f);
|
||||||
|
EXPECT_EQ(4, f());
|
||||||
|
}
|
||||||
|
|
||||||
|
android_dlextinfo extinfo_;
|
||||||
|
char relro_file_[PATH_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(DlExtRelroSharingTest, ChildWritesGoodData) {
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CreateRelroFile(LIBNAME));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(TryUsingRelro(LIBNAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DlExtRelroSharingTest, ChildWritesNoRelro) {
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CreateRelroFile(LIBNAME_NORELRO));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(TryUsingRelro(LIBNAME_NORELRO));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DlExtRelroSharingTest, RelroFileEmpty) {
|
||||||
|
int relro_fd = open(relro_file_, O_CREAT | O_RDWR | O_TRUNC, 0644);
|
||||||
|
ASSERT_NOERROR(relro_fd);
|
||||||
|
ASSERT_NOERROR(close(relro_fd));
|
||||||
|
|
||||||
|
ASSERT_NO_FATAL_FAILURE(TryUsingRelro(LIBNAME));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user