From 9a4133e1eeab492cca252438bd81bb7a145bf7ed Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 20 Jul 2015 13:35:33 +0000 Subject: [PATCH] Simplify iterating over program headers and detect corrupt ones. We now use a simple pointer and have range loops. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242669 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 39 ++++++++---------- .../corrupt-invalid-phentsize.elf.x86-64 | Bin 0 -> 1720 bytes test/Object/corrupt.test | 6 +++ tools/llvm-objdump/ELFDump.cpp | 32 ++++++-------- tools/llvm-readobj/ELFDumper.cpp | 24 +++++------ 5 files changed, 47 insertions(+), 54 deletions(-) create mode 100755 test/Object/Inputs/corrupt-invalid-phentsize.elf.x86-64 diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index cc271851e6b..160b12d607e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -349,18 +349,20 @@ public: } /// \brief Iterate over program header table. - typedef ELFEntityIterator Elf_Phdr_Iter; - - Elf_Phdr_Iter program_header_begin() const { - return Elf_Phdr_Iter(Header->e_phentsize, - (const char*)base() + Header->e_phoff); + const Elf_Phdr *program_header_begin() const { + if (Header->e_phnum && Header->e_phentsize != sizeof(Elf_Phdr)) + report_fatal_error("Invalid program header size"); + return reinterpret_cast(base() + Header->e_phoff); } - Elf_Phdr_Iter program_header_end() const { - return Elf_Phdr_Iter(Header->e_phentsize, - (const char*)base() + - Header->e_phoff + - (Header->e_phnum * Header->e_phentsize)); + const Elf_Phdr *program_header_end() const { + return program_header_begin() + Header->e_phnum; + } + + typedef iterator_range Elf_Phdr_Range; + + const Elf_Phdr_Range program_headers() const { + return make_range(program_header_begin(), program_header_end()); } uint64_t getNumSections() const; @@ -735,21 +737,16 @@ void ELFFile::scanDynamicTable() { // stack doesn't get realigned despite LoadMap having alignment 8 (PR24113). std::unique_ptr LoadMap(new LoadMapT(Alloc)); - for (Elf_Phdr_Iter PhdrI = program_header_begin(), - PhdrE = program_header_end(); - PhdrI != PhdrE; ++PhdrI) { - if (PhdrI->p_type == ELF::PT_DYNAMIC) { - DynamicRegion.Addr = base() + PhdrI->p_offset; - DynamicRegion.Size = PhdrI->p_filesz; + for (const Elf_Phdr &Phdr : program_headers()) { + if (Phdr.p_type == ELF::PT_DYNAMIC) { + DynamicRegion.Addr = base() + Phdr.p_offset; + DynamicRegion.Size = Phdr.p_filesz; DynamicRegion.EntSize = sizeof(Elf_Dyn); continue; } - if (PhdrI->p_type != ELF::PT_LOAD) + if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) continue; - if (PhdrI->p_filesz == 0) - continue; - LoadMap->insert(PhdrI->p_vaddr, PhdrI->p_vaddr + PhdrI->p_filesz, - PhdrI->p_offset); + LoadMap->insert(Phdr.p_vaddr, Phdr.p_vaddr + Phdr.p_filesz, Phdr.p_offset); } auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { diff --git a/test/Object/Inputs/corrupt-invalid-phentsize.elf.x86-64 b/test/Object/Inputs/corrupt-invalid-phentsize.elf.x86-64 new file mode 100755 index 0000000000000000000000000000000000000000..148d4c5fd64ba19ec75928c9d25f22bd75efb4dc GIT binary patch literal 1720 zcmcIk&1w@-6h8UW+GY_;7Ybcu(M3hP5L|U5X{!|>4G8U`P>2%~l7N{&W|U;rJc3J? zc?1_O`T$wvG5QKVfu1jOzUg#2K~Ov}`R@JB{qDKHS6E|#*7$qBL!NLwfluEP;G-8rpJdSwck7z1H>hh*r z+P+KE5x<*`$a5Nf53o%|e*T(l-*rKk#qX@)rPb|tp(m|YI|y1q=#4|A{0?`;v*Udc z4`bXT%kUQrm4R{KN9 z=y=6A|6GoD&*e*!&L`5Gl@Gj27QeTK7v|>mMf33V-SPUoxv)D4#c4Xlb*6q0j>Y+- zuRjKF+|J|PJ7N`-{ z6YGZf!9u`~H|PI>^;A|aS&uWT8zSqJRLqh4U(@v-jX zen0^hC5$>!2ReY3ZH;xq{=h!K^YQ-HhU8MU2t_^nz=Q(zB`qEQp*peW-|Ep%ut(Y$ ze>dew$3Ihl)=|G1`PKC36F4L9&-^!xw`DQx+l8LROf*QR&1 | FileCheck --check-prefix=STRTAB %s STRTAB: Invalid dynamic string table reference + +RUN: not llvm-readobj -program-headers \ +RUN: %p/Inputs/corrupt-invalid-phentsize.elf.x86-64 2>&1 | \ +RUN: FileCheck --check-prefix=PHENTSIZE %s + +PHENTSIZE: Invalid program header size diff --git a/tools/llvm-objdump/ELFDump.cpp b/tools/llvm-objdump/ELFDump.cpp index 2d0d7d7db0f..7b44e3916c4 100644 --- a/tools/llvm-objdump/ELFDump.cpp +++ b/tools/llvm-objdump/ELFDump.cpp @@ -24,10 +24,8 @@ using namespace llvm::object; template void printProgramHeaders(const ELFFile *o) { typedef ELFFile ELFO; outs() << "Program Header:\n"; - for (typename ELFO::Elf_Phdr_Iter pi = o->program_header_begin(), - pe = o->program_header_end(); - pi != pe; ++pi) { - switch (pi->p_type) { + for (const typename ELFO::Elf_Phdr &Phdr : o->program_headers()) { + switch (Phdr.p_type) { case ELF::PT_LOAD: outs() << " LOAD "; break; @@ -55,22 +53,16 @@ template void printProgramHeaders(const ELFFile *o) { const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; - outs() << "off " - << format(Fmt, (uint64_t)pi->p_offset) - << "vaddr " - << format(Fmt, (uint64_t)pi->p_vaddr) - << "paddr " - << format(Fmt, (uint64_t)pi->p_paddr) - << format("align 2**%u\n", countTrailingZeros(pi->p_align)) - << " filesz " - << format(Fmt, (uint64_t)pi->p_filesz) - << "memsz " - << format(Fmt, (uint64_t)pi->p_memsz) - << "flags " - << ((pi->p_flags & ELF::PF_R) ? "r" : "-") - << ((pi->p_flags & ELF::PF_W) ? "w" : "-") - << ((pi->p_flags & ELF::PF_X) ? "x" : "-") - << "\n"; + outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr " + << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr " + << format(Fmt, (uint64_t)Phdr.p_paddr) + << format("align 2**%u\n", + countTrailingZeros(Phdr.p_align)) + << " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz) + << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags " + << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-") + << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-") + << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n"; } outs() << "\n"; } diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 045f4dfc636..1cd638c5415 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -1109,20 +1109,18 @@ template void ELFDumper::printProgramHeaders() { ListScope L(W, "ProgramHeaders"); - for (typename ELFO::Elf_Phdr_Iter PI = Obj->program_header_begin(), - PE = Obj->program_header_end(); - PI != PE; ++PI) { + for (const typename ELFO::Elf_Phdr &Phdr : Obj->program_headers()) { DictScope P(W, "ProgramHeader"); - W.printHex ("Type", - getElfSegmentType(Obj->getHeader()->e_machine, PI->p_type), - PI->p_type); - W.printHex ("Offset", PI->p_offset); - W.printHex ("VirtualAddress", PI->p_vaddr); - W.printHex ("PhysicalAddress", PI->p_paddr); - W.printNumber("FileSize", PI->p_filesz); - W.printNumber("MemSize", PI->p_memsz); - W.printFlags ("Flags", PI->p_flags, makeArrayRef(ElfSegmentFlags)); - W.printNumber("Alignment", PI->p_align); + W.printHex("Type", + getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), + Phdr.p_type); + W.printHex("Offset", Phdr.p_offset); + W.printHex("VirtualAddress", Phdr.p_vaddr); + W.printHex("PhysicalAddress", Phdr.p_paddr); + W.printNumber("FileSize", Phdr.p_filesz); + W.printNumber("MemSize", Phdr.p_memsz); + W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags)); + W.printNumber("Alignment", Phdr.p_align); } }