Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7815d67 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Be permissive about badly formed elf files."

parents e0f6dc46 5acf069a
Loading
Loading
Loading
Loading
+17 −30
Original line number Diff line number Diff line
@@ -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*);
+2 −2
Original line number Diff line number Diff line
@@ -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);
+105 −2
Original line number Diff line number Diff line
@@ -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));
+3 −3
Original line number Diff line number Diff line
@@ -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];