aboutsummaryrefslogtreecommitdiff
path: root/linker/linker_phdr.cpp
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2015-06-25 15:51:41 -0700
committerDmitriy Ivanov <dimitry@google.com>2015-06-25 20:05:50 -0700
commit3f987f5b3eeb2e0e94c0d826429dfb418fce945f (patch)
tree332cbe9dbced4189cd59fcae74a81b72506dfd83 /linker/linker_phdr.cpp
parentd19c271599a4b8881213c7bfbb81f87d8e56a101 (diff)
downloadbionic-3f987f5b3eeb2e0e94c0d826429dfb418fce945f.tar.gz
Fix crash when trying to load invalid ELF file.
Bug: http://b/22047255 Bug: http://b/22091640 Change-Id: I6c51cff43287a6ac4b25fa9ce6a6fc3d232fd047 (cherry picked from commit 06700b2b5e92a365505b15d0d05e2d5b0706c511)
Diffstat (limited to 'linker/linker_phdr.cpp')
-rw-r--r--linker/linker_phdr.cpp18
1 files changed, 16 insertions, 2 deletions
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index f586b08b5..30118e363 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,