diff options
author | Dmitriy Ivanov <dimitry@google.com> | 2015-06-25 15:51:41 -0700 |
---|---|---|
committer | The Android Automerger <android-build@google.com> | 2015-06-25 19:58:03 -0700 |
commit | e89c2048d67884894560237fc81bec83d609b9b0 (patch) | |
tree | 5a87677b9410084999068396360f892ef8d837b2 | |
parent | 2fdf2ea2b169caccf12b794952b3d99da04ce9bd (diff) | |
download | bionic-e89c2048d67884894560237fc81bec83d609b9b0.zip bionic-e89c2048d67884894560237fc81bec83d609b9b0.tar.gz bionic-e89c2048d67884894560237fc81bec83d609b9b0.tar.bz2 |
Fix crash when trying to load invalid ELF file.
Bug: http://b/22047255
Bug: http://b/22091640
Change-Id: I6c51cff43287a6ac4b25fa9ce6a6fc3d232fd047
-rw-r--r-- | linker/linker.cpp | 2 | ||||
-rw-r--r-- | linker/linker_phdr.cpp | 18 | ||||
-rw-r--r-- | linker/linker_phdr.h | 3 |
3 files changed, 19 insertions, 4 deletions
diff --git a/linker/linker.cpp b/linker/linker.cpp index e147a13..e1b8ca9 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -1293,7 +1293,7 @@ static soinfo* load_library(int fd, off64_t file_offset, } // Read the ELF header and load the segments. - ElfReader elf_reader(realpath.c_str(), fd, file_offset); + ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size); if (!elf_reader.Load(extinfo)) { return nullptr; } diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index f586b08..30118e3 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -133,8 +133,8 @@ static int GetTargetElfMachine() { MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) -ElfReader::ElfReader(const char* name, int fd, off64_t file_offset) - : name_(name), fd_(fd), file_offset_(file_offset), +ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size) + : name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size), phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0), load_start_(nullptr), load_size_(0), load_bias_(0), loaded_phdr_(nullptr) { @@ -377,6 +377,20 @@ bool ElfReader::LoadSegments() { ElfW(Addr) file_page_start = PAGE_START(file_start); ElfW(Addr) file_length = file_end - file_page_start; + if (file_size_ <= 0) { + DL_ERR("\"%s\" invalid file size: %" PRId64, name_, file_size_); + return false; + } + + if (file_end >= static_cast<size_t>(file_size_)) { + DL_ERR("invalid ELF file \"%s\" load segment[%zd]:" + " p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")", + name_, i, reinterpret_cast<void*>(phdr->p_offset), + reinterpret_cast<void*>(phdr->p_filesz), + reinterpret_cast<void*>(file_end), file_size_); + return false; + } + if (file_length != 0) { void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start), file_length, diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h index 50f2117..3affa66 100644 --- a/linker/linker_phdr.h +++ b/linker/linker_phdr.h @@ -39,7 +39,7 @@ class ElfReader { public: - ElfReader(const char* name, int fd, off64_t file_offset); + ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size); ~ElfReader(); bool Load(const android_dlextinfo* extinfo); @@ -62,6 +62,7 @@ class ElfReader { const char* name_; int fd_; off64_t file_offset_; + off64_t file_size_; ElfW(Ehdr) header_; size_t phdr_num_; |