From a6c1279098f24a675d0df74ce1946f5d534b425e Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Tue, 21 Oct 2014 12:09:18 -0700 Subject: [PATCH] Rename library_offset to library_fd_offset replace lseek() and use pread() instead add test for library_fd_offset > file_size case Bug: 17762003 Change-Id: I4555f0be635124efe849c1f226985bcba72ffcbd --- libc/include/android/dlext.h | 8 ++++---- linker/linker.cpp | 12 ++++++------ linker/linker_phdr.cpp | 10 ++-------- tests/dlext_test.cpp | 25 +++++++++++++++++-------- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h index f81ec70d5..f27e4e5ab 100644 --- a/libc/include/android/dlext.h +++ b/libc/include/android/dlext.h @@ -54,11 +54,11 @@ enum { */ ANDROID_DLEXT_USE_LIBRARY_FD = 0x10, - /* When opening library using library_fd read it starting with library_offset + /* If opening a library using library_fd read it starting at library_fd_offset. * This flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set. */ - ANDROID_DLEXT_USE_LIBRARY_OFFSET = 0x20, + ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET = 0x20, /* Mask of valid bits */ ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS | @@ -66,7 +66,7 @@ enum { ANDROID_DLEXT_WRITE_RELRO | ANDROID_DLEXT_USE_RELRO | ANDROID_DLEXT_USE_LIBRARY_FD | - ANDROID_DLEXT_USE_LIBRARY_OFFSET, + ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET, }; typedef struct { @@ -75,7 +75,7 @@ typedef struct { size_t reserved_size; int relro_fd; int library_fd; - off64_t library_offset; + off64_t library_fd_offset; } android_dlextinfo; extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo); diff --git a/linker/linker.cpp b/linker/linker.cpp index cd691afce..41557e231 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -787,8 +787,8 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) { fd = extinfo->library_fd; - if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) { - file_offset = extinfo->library_offset; + if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) { + file_offset = extinfo->library_fd_offset; } } else { // Open the file. @@ -802,13 +802,13 @@ static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int rtld } if ((file_offset % PAGE_SIZE) != 0) { - DL_ERR("file offset for the library %s is not page-aligned: %" PRId64, name, file_offset); + DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset); return nullptr; } struct stat file_stat; if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) { - DL_ERR("unable to stat file for the library %s: %s", name, strerror(errno)); + DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno)); return nullptr; } @@ -1060,8 +1060,8 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) return nullptr; } if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 && - (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) { - DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags); + (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) { + DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags); return nullptr; } } diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index 6856405de..61ae5ab28 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -142,18 +142,12 @@ bool ElfReader::Load(const android_dlextinfo* extinfo) { } bool ElfReader::ReadElfHeader() { - off64_t actual_offset = lseek64(fd_, file_offset_, SEEK_SET); - - if (actual_offset != file_offset_) { - DL_ERR("seek to %" PRId64 " failed: %s", file_offset_, strerror(errno)); - return false; - } - - ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, &header_, sizeof(header_))); + ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_)); if (rc < 0) { DL_ERR("can't read file \"%s\": %s", name_, strerror(errno)); return false; } + if (rc != sizeof(header_)) { DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_, static_cast(rc)); diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp index c5443a8c6..58add6b95 100644 --- a/tests/dlext_test.cpp +++ b/tests/dlext_test.cpp @@ -121,9 +121,9 @@ TEST_F(DlExtTest, ExtInfoUseFdWithOffset) { snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data); android_dlextinfo extinfo; - extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_OFFSET; + 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_offset = LIBZIP_OFFSET; + extinfo.library_fd_offset = LIBZIP_OFFSET; handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo); ASSERT_DL_NOTNULL(handle_); @@ -141,23 +141,32 @@ TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) { snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data); android_dlextinfo extinfo; - extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_OFFSET; + 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_offset = 17; + 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()); + 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_OFFSET; - extinfo.library_offset = LIBZIP_OFFSET; + 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_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror()); + 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) {