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
This commit is contained in:
Dmitriy Ivanov 2014-10-21 12:09:18 -07:00
parent 8f41d3d3bc
commit a6c1279098
4 changed files with 29 additions and 26 deletions

View file

@ -54,11 +54,11 @@ enum {
*/ */
ANDROID_DLEXT_USE_LIBRARY_FD = 0x10, 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. * 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 */ /* Mask of valid bits */
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
@ -66,7 +66,7 @@ enum {
ANDROID_DLEXT_WRITE_RELRO | ANDROID_DLEXT_WRITE_RELRO |
ANDROID_DLEXT_USE_RELRO | ANDROID_DLEXT_USE_RELRO |
ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD |
ANDROID_DLEXT_USE_LIBRARY_OFFSET, ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET,
}; };
typedef struct { typedef struct {
@ -75,7 +75,7 @@ typedef struct {
size_t reserved_size; size_t reserved_size;
int relro_fd; int relro_fd;
int library_fd; int library_fd;
off64_t library_offset; off64_t library_fd_offset;
} android_dlextinfo; } android_dlextinfo;
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo); extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);

View file

@ -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) { if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
fd = extinfo->library_fd; fd = extinfo->library_fd;
if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) { if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
file_offset = extinfo->library_offset; file_offset = extinfo->library_fd_offset;
} }
} else { } else {
// Open the file. // 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) { 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; return nullptr;
} }
struct stat file_stat; struct stat file_stat;
if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) { 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; return nullptr;
} }
@ -1060,8 +1060,8 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
return nullptr; return nullptr;
} }
if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 && if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
(extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_OFFSET) != 0) { (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags); DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
return nullptr; return nullptr;
} }
} }

View file

@ -142,18 +142,12 @@ bool ElfReader::Load(const android_dlextinfo* extinfo) {
} }
bool ElfReader::ReadElfHeader() { bool ElfReader::ReadElfHeader() {
off64_t actual_offset = lseek64(fd_, file_offset_, SEEK_SET); ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
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_)));
if (rc < 0) { if (rc < 0) {
DL_ERR("can't read file \"%s\": %s", name_, strerror(errno)); DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
return false; return false;
} }
if (rc != sizeof(header_)) { if (rc != sizeof(header_)) {
DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_, DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_,
static_cast<size_t>(rc)); static_cast<size_t>(rc));

View file

@ -121,9 +121,9 @@ TEST_F(DlExtTest, ExtInfoUseFdWithOffset) {
snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data); snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data);
android_dlextinfo extinfo; 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_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); handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo);
ASSERT_DL_NOTNULL(handle_); ASSERT_DL_NOTNULL(handle_);
@ -141,23 +141,32 @@ TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data); snprintf(lib_path, sizeof(lib_path), LIBZIPPATH, android_data);
android_dlextinfo extinfo; 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_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); handle_ = android_dlopen_ext("libname_placeholder", RTLD_NOW, &extinfo);
ASSERT_TRUE(handle_ == nullptr); 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) { TEST_F(DlExtTest, ExtInfoUseOffsetWihtoutFd) {
android_dlextinfo extinfo; android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_OFFSET; extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
extinfo.library_offset = LIBZIP_OFFSET; extinfo.library_fd_offset = LIBZIP_OFFSET;
handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo); handle_ = android_dlopen_ext("/some/lib/that/does_not_exist", RTLD_NOW, &extinfo);
ASSERT_TRUE(handle_ == nullptr); 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) { TEST_F(DlExtTest, Reserved) {