Check alignment along with range of mapped file fragments
Improve sanity-checks of elf-file by adding alignment check
of mapped sections and section headers.
Bug: http://b/30687964
Change-Id: I7f06ddaa56a13989ce7be847b3a73c352e32c008
(cherry picked from commit 7e2d49ae3e
)
This commit is contained in:
parent
f5042cab10
commit
bd90675111
3 changed files with 33 additions and 19 deletions
|
@ -49,6 +49,12 @@
|
|||
__libc_format_fd(2, "\n"); \
|
||||
} while (false)
|
||||
|
||||
#define DL_ERR_AND_LOG(fmt, x...) \
|
||||
do { \
|
||||
DL_ERR(fmt, x); \
|
||||
PRINT(fmt, x); \
|
||||
} while (false)
|
||||
|
||||
constexpr ElfW(Versym) kVersymNotNeeded = 0;
|
||||
constexpr ElfW(Versym) kVersymGlobal = 1;
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ bool ElfReader::VerifyElfHeader() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size) {
|
||||
bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment) {
|
||||
off64_t range_start;
|
||||
off64_t range_end;
|
||||
|
||||
|
@ -271,8 +271,9 @@ bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size) {
|
|||
return offset > 0 &&
|
||||
safe_add(&range_start, file_offset_, offset) &&
|
||||
safe_add(&range_end, range_start, size) &&
|
||||
range_start < file_size_ &&
|
||||
range_end <= file_size_;
|
||||
(range_start < file_size_) &&
|
||||
(range_end <= file_size_) &&
|
||||
((offset % alignment) == 0);
|
||||
}
|
||||
|
||||
// Loads the program header table from an ELF file into a read-only private
|
||||
|
@ -289,8 +290,11 @@ bool ElfReader::ReadProgramHeaders() {
|
|||
|
||||
// Boundary checks
|
||||
size_t size = phdr_num_ * sizeof(ElfW(Phdr));
|
||||
if (!CheckFileRange(header_.e_phoff, size)) {
|
||||
DL_ERR("\"%s\" has invalid phdr offset/size", name_.c_str());
|
||||
if (!CheckFileRange(header_.e_phoff, size, alignof(ElfW(Phdr)))) {
|
||||
DL_ERR_AND_LOG("\"%s\" has invalid phdr offset/size: %zu/%zu",
|
||||
name_.c_str(),
|
||||
static_cast<size_t>(header_.e_phoff),
|
||||
size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -307,13 +311,16 @@ bool ElfReader::ReadSectionHeaders() {
|
|||
shdr_num_ = header_.e_shnum;
|
||||
|
||||
if (shdr_num_ == 0) {
|
||||
DL_ERR("\"%s\" has no section headers", name_.c_str());
|
||||
DL_ERR_AND_LOG("\"%s\" has no section headers", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = shdr_num_ * sizeof(ElfW(Shdr));
|
||||
if (!CheckFileRange(header_.e_shoff, size)) {
|
||||
DL_ERR("\"%s\" has invalid shdr offset/size", name_.c_str());
|
||||
if (!CheckFileRange(header_.e_shoff, size, alignof(const ElfW(Shdr)))) {
|
||||
DL_ERR_AND_LOG("\"%s\" has invalid shdr offset/size: %zu/%zu",
|
||||
name_.c_str(),
|
||||
static_cast<size_t>(header_.e_shoff),
|
||||
size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -337,7 +344,7 @@ bool ElfReader::ReadDynamicSection() {
|
|||
}
|
||||
|
||||
if (dynamic_shdr == nullptr) {
|
||||
DL_ERR("\"%s\" .dynamic section header was not found", name_.c_str());
|
||||
DL_ERR_AND_LOG("\"%s\" .dynamic section header was not found", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -371,21 +378,22 @@ bool ElfReader::ReadDynamicSection() {
|
|||
}
|
||||
|
||||
if (dynamic_shdr->sh_link >= shdr_num_) {
|
||||
DL_ERR("\"%s\" .dynamic section has invalid sh_link: %d", name_.c_str(), dynamic_shdr->sh_link);
|
||||
DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid sh_link: %d",
|
||||
name_.c_str(),
|
||||
dynamic_shdr->sh_link);
|
||||
return false;
|
||||
}
|
||||
|
||||
const ElfW(Shdr)* strtab_shdr = &shdr_table_[dynamic_shdr->sh_link];
|
||||
|
||||
if (strtab_shdr->sh_type != SHT_STRTAB) {
|
||||
DL_ERR("\"%s\" .dynamic section has invalid link(%d) sh_type: %d (expected SHT_STRTAB)",
|
||||
name_.c_str(), dynamic_shdr->sh_link, strtab_shdr->sh_type);
|
||||
DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid link(%d) sh_type: %d (expected SHT_STRTAB)",
|
||||
name_.c_str(), dynamic_shdr->sh_link, strtab_shdr->sh_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckFileRange(dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
|
||||
DL_ERR("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
|
||||
PRINT("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
|
||||
if (!CheckFileRange(dynamic_shdr->sh_offset, dynamic_shdr->sh_size, alignof(const ElfW(Dyn)))) {
|
||||
DL_ERR_AND_LOG("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -396,9 +404,9 @@ bool ElfReader::ReadDynamicSection() {
|
|||
|
||||
dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_fragment_.data());
|
||||
|
||||
if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
|
||||
DL_ERR("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
|
||||
name_.c_str());
|
||||
if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size, alignof(const char))) {
|
||||
DL_ERR_AND_LOG("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
|
||||
name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ class ElfReader {
|
|||
bool LoadSegments();
|
||||
bool FindPhdr();
|
||||
bool CheckPhdr(ElfW(Addr));
|
||||
bool CheckFileRange(ElfW(Addr) offset, size_t size);
|
||||
bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
|
||||
|
||||
bool did_read_;
|
||||
bool did_load_;
|
||||
|
|
Loading…
Reference in a new issue