From 9257a0fc79af4868ef160affe0533179d4cae351 Mon Sep 17 00:00:00 2001 From: "Seva Alekseyev (he/him)" Date: Tue, 16 Apr 2024 23:28:48 -0400 Subject: [PATCH] Exceptions on malformed ELF header contents (#552) * Exceptions on malformed ELF header contents * Code cleanup * Min table entry size retrieved from struct --- elftools/elf/elffile.py | 42 ++++++++++++++---- test/test_bogus_entry_size.py | 17 +++++++ test/test_section_self_link.py | 16 +++++++ .../section_header_bogus_size.elf | Bin 0 -> 130 bytes .../section_link_to_self.elf | Bin 0 -> 143 bytes 5 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 test/test_bogus_entry_size.py create mode 100644 test/test_section_self_link.py create mode 100644 test/testfiles_for_unittests/section_header_bogus_size.elf create mode 100644 test/testfiles_for_unittests/section_link_to_self.elf diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index 0ddd615a..8f646c79 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -139,6 +139,26 @@ def get_section(self, n): """ section_header = self._get_section_header(n) return self._make_section(section_header) + + def _get_linked_symtab_section(self, n): + """ Get the section at index #n from the file, throws + if it's not a SYMTAB/DYNTAB. + Used for resolving section links with target type validation. + """ + section_header = self._get_section_header(n) + if section_header['sh_type'] not in ('SHT_SYMTAB', 'SHT_DYNSYM'): + raise ELFError("Section points at section %d of type %s, expected SHT_SYMTAB/SHT_DYNSYM" % (n, section_header['sh_type'])) + return self._make_section(section_header) + + def _get_linked_strtab_section(self, n): + """ Get the section at index #n from the file, throws + if it's not a STRTAB. + Used for resolving section links with target type validation. + """ + section_header = self._get_section_header(n) + if section_header['sh_type'] != 'SHT_STRTAB': + raise ELFError("SHT_SYMTAB section points at section %d of type %s, expected SHT_STRTAB" % (n, section_header['sh_type'])) + return self._make_section(section_header) def get_section_by_name(self, name): """ Get a section from the file, by name. Return None if no such @@ -588,12 +608,18 @@ def _identify_file(self): def _section_offset(self, n): """ Compute the offset of section #n in the file """ - return self['e_shoff'] + n * self['e_shentsize'] + shentsize = self['e_shentsize'] + if self['e_shoff'] > 0 and shentsize < self.structs.Elf_Shdr.sizeof(): + raise ELFError('Too small e_shentsize: %s' % shentsize) + return self['e_shoff'] + n * shentsize def _segment_offset(self, n): """ Compute the offset of segment #n in the file """ - return self['e_phoff'] + n * self['e_phentsize'] + phentsize = self['e_phentsize'] + if self['e_phoff'] > 0 and phentsize < self.structs.Elf_Phdr.sizeof(): + raise ELFError('Too small e_phentsize: %s' % phentsize) + return self['e_phoff'] + n * phentsize def _make_segment(self, segment_header): """ Create a Segment object of the appropriate type @@ -683,7 +709,7 @@ def _make_symbol_table_section(self, section_header, name): """ Create a SymbolTableSection """ linked_strtab_index = section_header['sh_link'] - strtab_section = self.get_section(linked_strtab_index) + strtab_section = self._get_linked_strtab_section(linked_strtab_index) return SymbolTableSection( section_header, name, elffile=self, @@ -701,7 +727,7 @@ def _make_sunwsyminfo_table_section(self, section_header, name): """ Create a SUNWSyminfoTableSection """ linked_strtab_index = section_header['sh_link'] - strtab_section = self.get_section(linked_strtab_index) + strtab_section = self._get_linked_symtab_section(linked_strtab_index) return SUNWSyminfoTableSection( section_header, name, elffile=self, @@ -711,7 +737,7 @@ def _make_gnu_verneed_section(self, section_header, name): """ Create a GNUVerNeedSection """ linked_strtab_index = section_header['sh_link'] - strtab_section = self.get_section(linked_strtab_index) + strtab_section = self._get_linked_strtab_section(linked_strtab_index) return GNUVerNeedSection( section_header, name, elffile=self, @@ -721,7 +747,7 @@ def _make_gnu_verdef_section(self, section_header, name): """ Create a GNUVerDefSection """ linked_strtab_index = section_header['sh_link'] - strtab_section = self.get_section(linked_strtab_index) + strtab_section = self._get_linked_strtab_section(linked_strtab_index) return GNUVerDefSection( section_header, name, elffile=self, @@ -739,14 +765,14 @@ def _make_gnu_versym_section(self, section_header, name): def _make_elf_hash_section(self, section_header, name): linked_symtab_index = section_header['sh_link'] - symtab_section = self.get_section(linked_symtab_index) + symtab_section = self._get_linked_symtab_section(linked_symtab_index) return ELFHashSection( section_header, name, self, symtab_section ) def _make_gnu_hash_section(self, section_header, name): linked_symtab_index = section_header['sh_link'] - symtab_section = self.get_section(linked_symtab_index) + symtab_section = self._get_linked_symtab_section(linked_symtab_index) return GNUHashSection( section_header, name, self, symtab_section ) diff --git a/test/test_bogus_entry_size.py b/test/test_bogus_entry_size.py new file mode 100644 index 00000000..bd68c0fa --- /dev/null +++ b/test/test_bogus_entry_size.py @@ -0,0 +1,17 @@ +import unittest +import os +from elftools.common.exceptions import ELFError +from elftools.elf.elffile import ELFFile + +class TestSectionHeaderEntrySizeCheck(unittest.TestCase): + def test_size_check(self): + test_file = os.path.join('test', 'testfiles_for_unittests', 'section_header_bogus_size.elf') + with open(test_file, 'rb') as f: + # This file contains a nonblank section header table and + # claims header table entry size is zero. + with self.assertRaises(ELFError): + elffile = ELFFile(f) + elffile.has_dwarf_info() + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_section_self_link.py b/test/test_section_self_link.py new file mode 100644 index 00000000..93e3230e --- /dev/null +++ b/test/test_section_self_link.py @@ -0,0 +1,16 @@ +import unittest +import os +from elftools.common.exceptions import ELFError +from elftools.elf.elffile import ELFFile + +class TestSectionSelfLink(unittest.TestCase): + def test_self_link(self): + test_file = os.path.join('test', 'testfiles_for_unittests', 'section_link_to_self.elf') + with open(test_file, 'rb') as f: + # This file contains a SHT_HASH section with sh_link pointing at self. + # The spec says SHT_hash should point at a symtab-type section. + with self.assertRaises(ELFError): + ELFFile(f).has_dwarf_info() + +if __name__ == '__main__': + unittest.main() diff --git a/test/testfiles_for_unittests/section_header_bogus_size.elf b/test/testfiles_for_unittests/section_header_bogus_size.elf new file mode 100644 index 0000000000000000000000000000000000000000..cf6cf2fe56396c0f394172782f3a8ae6f28960f3 GIT binary patch literal 130 zcmb<-^>JfjWaMN(0riqTZgvceNMa61Y!DM7_y4~Th{?!M4>1N!5rnIJfjWaMP%U_b^e40a5RZ~xuQ8W2V?{AFO^WMFXhjra5S Ua|LSr4+IPhybSvt9M~Bc06rTGhX4Qo literal 0 HcmV?d00001