Merge "Be permissive about badly formed elf files."
This commit is contained in:
commit
c7815d675a
4 changed files with 127 additions and 37 deletions
|
@ -167,15 +167,10 @@ bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We could still potentially unwind without the section header
|
||||
// information, so ignore any errors.
|
||||
if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) {
|
||||
log(0, "Malformed section header found, ignoring...");
|
||||
}
|
||||
// If we have enough information that this is an elf file, then allow
|
||||
// malformed program and section headers.
|
||||
ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias);
|
||||
ReadSectionHeaders<EhdrType, ShdrType>(ehdr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -200,14 +195,12 @@ uint64_t ElfInterface::GetLoadBias(Memory* memory) {
|
|||
}
|
||||
|
||||
template <typename EhdrType, typename PhdrType>
|
||||
bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
|
||||
void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
|
||||
uint64_t offset = ehdr.e_phoff;
|
||||
for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
|
||||
PhdrType phdr;
|
||||
if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
|
||||
last_error_.code = ERROR_MEMORY_INVALID;
|
||||
last_error_.address = offset;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (phdr.p_type) {
|
||||
|
@ -242,11 +235,10 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
|
|||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename EhdrType, typename ShdrType>
|
||||
bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
||||
void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
||||
uint64_t offset = ehdr.e_shoff;
|
||||
uint64_t sec_offset = 0;
|
||||
uint64_t sec_size = 0;
|
||||
|
@ -267,9 +259,7 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
|||
offset += ehdr.e_shentsize;
|
||||
for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
|
||||
if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
|
||||
last_error_.code = ERROR_MEMORY_INVALID;
|
||||
last_error_.address = offset;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
|
||||
|
@ -277,18 +267,14 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
|||
// the string terminated names.
|
||||
ShdrType str_shdr;
|
||||
if (shdr.sh_link >= ehdr.e_shnum) {
|
||||
last_error_.code = ERROR_UNWIND_INFO;
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
|
||||
if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
|
||||
last_error_.code = ERROR_MEMORY_INVALID;
|
||||
last_error_.address = str_offset;
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
if (str_shdr.sh_type != SHT_STRTAB) {
|
||||
last_error_.code = ERROR_UNWIND_INFO;
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
|
||||
str_shdr.sh_offset, str_shdr.sh_size));
|
||||
|
@ -324,7 +310,6 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
|||
static_cast<uint64_t>(shdr.sh_offset)));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename DynType>
|
||||
|
@ -499,11 +484,13 @@ template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
|
|||
template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
|
||||
template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
|
||||
|
||||
template bool ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, uint64_t*);
|
||||
template bool ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, uint64_t*);
|
||||
template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&,
|
||||
uint64_t*);
|
||||
template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&,
|
||||
uint64_t*);
|
||||
|
||||
template bool ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
|
||||
template bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
|
||||
template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
|
||||
template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
|
||||
|
||||
template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
|
||||
template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
|
||||
|
|
|
@ -104,10 +104,10 @@ class ElfInterface {
|
|||
bool ReadAllHeaders(uint64_t* load_bias);
|
||||
|
||||
template <typename EhdrType, typename PhdrType>
|
||||
bool ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias);
|
||||
void ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias);
|
||||
|
||||
template <typename EhdrType, typename ShdrType>
|
||||
bool ReadSectionHeaders(const EhdrType& ehdr);
|
||||
void ReadSectionHeaders(const EhdrType& ehdr);
|
||||
|
||||
template <typename DynType>
|
||||
bool GetSonameWithTemplate(std::string* soname);
|
||||
|
|
|
@ -97,9 +97,15 @@ class ElfInterfaceTest : public ::testing::Test {
|
|||
template <typename ElfType>
|
||||
void InitHeadersDebugFrameFail();
|
||||
|
||||
template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
|
||||
void InitProgramHeadersMalformed();
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
|
||||
void InitSectionHeadersMalformed();
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
|
||||
void InitSectionHeadersMalformedSymData();
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename Sym, typename ElfInterfaceType>
|
||||
void InitSectionHeaders(uint64_t entry_size);
|
||||
|
||||
|
@ -677,6 +683,29 @@ TEST_F(ElfInterfaceTest, init_headers_debug_frame64) {
|
|||
InitHeadersDebugFrame<ElfInterface64Fake>();
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::InitProgramHeadersMalformed() {
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
|
||||
Ehdr ehdr = {};
|
||||
ehdr.e_phoff = 0x100;
|
||||
ehdr.e_phnum = 3;
|
||||
ehdr.e_phentsize = sizeof(Phdr);
|
||||
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
|
||||
|
||||
uint64_t load_bias = 0;
|
||||
ASSERT_TRUE(elf->Init(&load_bias));
|
||||
EXPECT_EQ(0U, load_bias);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_program_headers_malformed32) {
|
||||
InitProgramHeadersMalformed<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>();
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_program_headers_malformed64) {
|
||||
InitProgramHeadersMalformed<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>();
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::InitSectionHeadersMalformed() {
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
|
@ -700,6 +729,80 @@ TEST_F(ElfInterfaceTest, init_section_headers_malformed64) {
|
|||
InitSectionHeadersMalformed<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::InitSectionHeadersMalformedSymData() {
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
|
||||
uint64_t offset = 0x1000;
|
||||
|
||||
Ehdr ehdr = {};
|
||||
ehdr.e_shoff = offset;
|
||||
ehdr.e_shnum = 5;
|
||||
ehdr.e_shentsize = sizeof(Shdr);
|
||||
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
|
||||
|
||||
offset += ehdr.e_shentsize;
|
||||
|
||||
Shdr shdr = {};
|
||||
shdr.sh_type = SHT_SYMTAB;
|
||||
shdr.sh_link = 4;
|
||||
shdr.sh_addr = 0x5000;
|
||||
shdr.sh_offset = 0x5000;
|
||||
shdr.sh_entsize = 0x100;
|
||||
shdr.sh_size = shdr.sh_entsize * 10;
|
||||
memory_.SetMemory(offset, &shdr, sizeof(shdr));
|
||||
offset += ehdr.e_shentsize;
|
||||
|
||||
memset(&shdr, 0, sizeof(shdr));
|
||||
shdr.sh_type = SHT_DYNSYM;
|
||||
shdr.sh_link = 10;
|
||||
shdr.sh_addr = 0x6000;
|
||||
shdr.sh_offset = 0x6000;
|
||||
shdr.sh_entsize = 0x100;
|
||||
shdr.sh_size = shdr.sh_entsize * 10;
|
||||
memory_.SetMemory(offset, &shdr, sizeof(shdr));
|
||||
offset += ehdr.e_shentsize;
|
||||
|
||||
memset(&shdr, 0, sizeof(shdr));
|
||||
shdr.sh_type = SHT_DYNSYM;
|
||||
shdr.sh_link = 2;
|
||||
shdr.sh_addr = 0x6000;
|
||||
shdr.sh_offset = 0x6000;
|
||||
shdr.sh_entsize = 0x100;
|
||||
shdr.sh_size = shdr.sh_entsize * 10;
|
||||
memory_.SetMemory(offset, &shdr, sizeof(shdr));
|
||||
offset += ehdr.e_shentsize;
|
||||
|
||||
// The string data for the entries.
|
||||
memset(&shdr, 0, sizeof(shdr));
|
||||
shdr.sh_type = SHT_STRTAB;
|
||||
shdr.sh_name = 0x20000;
|
||||
shdr.sh_offset = 0xf000;
|
||||
shdr.sh_size = 0x1000;
|
||||
memory_.SetMemory(offset, &shdr, sizeof(shdr));
|
||||
offset += ehdr.e_shentsize;
|
||||
|
||||
uint64_t load_bias = 0;
|
||||
ASSERT_TRUE(elf->Init(&load_bias));
|
||||
EXPECT_EQ(0U, load_bias);
|
||||
EXPECT_EQ(0U, elf->debug_frame_offset());
|
||||
EXPECT_EQ(0U, elf->debug_frame_size());
|
||||
EXPECT_EQ(0U, elf->gnu_debugdata_offset());
|
||||
EXPECT_EQ(0U, elf->gnu_debugdata_size());
|
||||
|
||||
std::string name;
|
||||
uint64_t name_offset;
|
||||
ASSERT_FALSE(elf->GetFunctionName(0x90010, &name, &name_offset));
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata32) {
|
||||
InitSectionHeadersMalformedSymData<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata64) {
|
||||
InitSectionHeadersMalformedSymData<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename Sym, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) {
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
|
@ -708,7 +811,7 @@ void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) {
|
|||
|
||||
Ehdr ehdr = {};
|
||||
ehdr.e_shoff = offset;
|
||||
ehdr.e_shnum = 10;
|
||||
ehdr.e_shnum = 5;
|
||||
ehdr.e_shentsize = entry_size;
|
||||
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
|
||||
|
||||
|
@ -795,7 +898,7 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() {
|
|||
|
||||
Ehdr ehdr = {};
|
||||
ehdr.e_shoff = offset;
|
||||
ehdr.e_shnum = 10;
|
||||
ehdr.e_shnum = 6;
|
||||
ehdr.e_shentsize = sizeof(Shdr);
|
||||
ehdr.e_shstrndx = 2;
|
||||
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
|
||||
|
|
|
@ -319,7 +319,7 @@ TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
|
|||
TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
|
||||
ehdr.e_shoff = 0x2000;
|
||||
ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
|
||||
ehdr.e_shnum = 4;
|
||||
ehdr.e_shnum = 0;
|
||||
memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
|
||||
|
||||
Elf* elf = info.GetElf(process_memory_, false);
|
||||
|
@ -341,7 +341,7 @@ TEST_F(MapInfoGetElfTest, check_device_maps) {
|
|||
TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
|
||||
ehdr.e_shoff = 0x2000;
|
||||
ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
|
||||
ehdr.e_shnum = 4;
|
||||
ehdr.e_shnum = 0;
|
||||
memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
|
||||
|
||||
Elf* elf = info.GetElf(process_memory_, false);
|
||||
|
@ -368,7 +368,7 @@ TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) {
|
|||
TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
|
||||
ehdr.e_shoff = 0x2000;
|
||||
ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
|
||||
ehdr.e_shnum = 4;
|
||||
ehdr.e_shnum = 0;
|
||||
memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
|
||||
|
||||
Elf* elf_in_threads[kNumConcurrentThreads];
|
||||
|
|
Loading…
Reference in a new issue