Validate ELF file segment lengths against file length when loading
Bug: 11152153
Change-Id: I31047b9bb607aac478b79dea4ed9a72abe1bd775
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 2140334..dfb6819 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -71,8 +71,9 @@
}
if (file_length < sizeof(llvm::ELF::Elf32_Ehdr)) {
if (writable) {
- LOG(WARNING) << "File size " << file_length
- << " not large enough to contain ELF header: " << file_->GetPath();
+ LOG(WARNING) << "File size of " << file_length
+ << " bytes not large enough to contain ELF header of "
+ << sizeof(llvm::ELF::Elf32_Ehdr) << " bytes: " << file_->GetPath();
}
return false;
}
@@ -85,6 +86,12 @@
}
// then remap to cover program header
size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
+ if (file_length < program_header_size) {
+ LOG(WARNING) << "File size of " << file_length
+ << " bytes not large enough to contain ELF program header of "
+ << program_header_size << " bytes: " << file_->GetPath();
+ return false;
+ }
if (!SetMap(MemMap::MapFile(program_header_size, prot, flags, file_->Fd(), 0))) {
LOG(WARNING) << "Failed to map ELF program headers: " << file_->GetPath();
return false;
@@ -617,6 +624,7 @@
// non-zero, the segments require the specific address specified,
// which either was specified in the file because we already set
// base_address_ after the first zero segment).
+ int64_t file_length = file_->GetLength();
if (program_header.p_vaddr == 0) {
std::string reservation_name("ElfFile reservation for ");
reservation_name += file_->GetPath();
@@ -648,6 +656,13 @@
} else {
flags |= MAP_PRIVATE;
}
+ if (file_length < (program_header.p_offset + program_header.p_memsz)) {
+ LOG(WARNING) << "File size of " << file_length
+ << " bytes not large enough to contain ELF segment " << i
+ << " of " << (program_header.p_offset + program_header.p_memsz)
+ << " bytes: " << file_->GetPath();
+ return false;
+ }
UniquePtr<MemMap> segment(MemMap::MapFileAtAddress(p_vaddr,
program_header.p_memsz,
prot, flags, file_->Fd(),