Skip to content

Commit

Permalink
Merge branch 'bugfix/espcoredump_elf_sha256_check_v4.4' into 'release…
Browse files Browse the repository at this point in the history
…/v4.4'

elf: Fix for mismatched app ELF file not detected (v4.4)

See merge request espressif/esp-idf!23209
  • Loading branch information
dobairoland committed Jun 25, 2023
2 parents b1480d9 + e13e3bf commit 76122fb
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 15 deletions.
24 changes: 15 additions & 9 deletions components/espcoredump/corefile/elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ def __init__(self, elf_path=None, e_type=None, e_machine=None):
self.load_segments = [] # type: list[ElfSegment]
self.note_segments = [] # type: list[ElfNoteSegment]

self.sha256 = b'' # type: bytes

if elf_path and os.path.isfile(elf_path):
self.read_elf(elf_path)

Expand Down Expand Up @@ -156,6 +158,12 @@ def read_elf(self, elf_path): # type: (str) -> None
sec.data,
sec.sh.sh_flags) for sec in self._model.sections]

# calculate sha256 of the input bytes (note: this may not be the same as the sha256 of any generated
# output struct, as the ELF parser may change some details.)
sha256 = hashlib.sha256()
sha256.update(elf_bytes)
self.sha256 = sha256.digest()

@staticmethod
def _parse_string_table(byte_str, offset): # type: (bytes, int) -> str
section_name_str = byte_str[offset:]
Expand Down Expand Up @@ -215,15 +223,6 @@ def _generate_struct_from_headers(self, header_tables): # type: (Container) ->

return Struct(*args)

@property
def sha256(self): # type: () -> bytes
"""
:return: SHA256 hash of the input ELF file
"""
sha256 = hashlib.sha256()
sha256.update(self._struct.build(self._model)) # type: ignore
return sha256.digest()


class ElfSection(object):
SHF_WRITE = 0x01
Expand Down Expand Up @@ -284,6 +283,13 @@ def __init__(self, addr, data, flags): # type: (int, bytes, int) -> None
super(ElfNoteSegment, self).__init__(addr, data, flags)
self.type = ElfFile.PT_NOTE
self.note_secs = NoteSections.parse(self.data)
for note in self.note_secs:
# note.name should include a terminating NUL byte, plus possible
# padding
#
# (note: construct.PaddingString can't parse this if there
# are non-zero padding bytes after the NUL, it also parses those.)
note.name = note.name.split(b'\x00')[0]

@staticmethod
def _type_str(): # type: () -> str
Expand Down
22 changes: 16 additions & 6 deletions components/espcoredump/corefile/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class EspCoreDumpVersion(object):

COREDUMP_SUPPORTED_TARGETS = XTENSA_CHIPS + RISCV_CHIPS

def __init__(self, version=None): # type: (int) -> None
def __init__(self, version=None): # type: (Optional[int]) -> None
"""Constructor for core dump version
"""
super(EspCoreDumpVersion, self).__init__()
Expand Down Expand Up @@ -248,7 +248,7 @@ def create_corefile(self, exe_name=None, e_machine=ESPCoreDumpElfFile.EM_XTENSA)
else:
raise NotImplementedError

def _extract_elf_corefile(self, exe_name=None, e_machine=ESPCoreDumpElfFile.EM_XTENSA): # type: (str, int) -> None
def _extract_elf_corefile(self, exe_name=None, e_machine=ESPCoreDumpElfFile.EM_XTENSA): # type: (Optional[str], int) -> None
"""
Reads the ELF formatted core dump image and parse it
"""
Expand All @@ -261,7 +261,7 @@ def _extract_elf_corefile(self, exe_name=None, e_machine=ESPCoreDumpElfFile.EM_X
for seg in core_elf.note_segments:
for note_sec in seg.note_secs:
# Check for version info note
if note_sec.name == 'ESP_CORE_DUMP_INFO' \
if note_sec.name == b'ESP_CORE_DUMP_INFO' \
and note_sec.type == ESPCoreDumpElfFile.PT_INFO \
and exe_name:
exe_elf = ElfFile(exe_name)
Expand All @@ -271,10 +271,20 @@ def _extract_elf_corefile(self, exe_name=None, e_machine=ESPCoreDumpElfFile.EM_X
'sha256' / Bytes(64) # SHA256 as hex string
)
coredump_sha256 = coredump_sha256_struct.parse(note_sec.desc[:coredump_sha256_struct.sizeof()])
if coredump_sha256.sha256 != app_sha256:

logging.debug('App SHA256: {!r}'.format(app_sha256))
logging.debug('Core dump SHA256: {!r}'.format(coredump_sha256))

# Actual coredump SHA may be shorter than a full SHA256 hash
# with NUL byte padding, according to the app's APP_RETRIEVE_LEN_ELF_SHA
# length
core_sha_trimmed = coredump_sha256.sha256.rstrip(b'\x00').decode()
app_sha_trimmed = app_sha256[:len(core_sha_trimmed)].decode()

if core_sha_trimmed != app_sha_trimmed:
raise ESPCoreDumpLoaderError(
'Invalid application image for coredump: coredump SHA256({!r}) != app SHA256({!r}).'
.format(coredump_sha256, app_sha256))
'Invalid application image for coredump: coredump SHA256({}) != app SHA256({}).'
.format(core_sha_trimmed, app_sha_trimmed))
if coredump_sha256.ver != self.version:
raise ESPCoreDumpLoaderError(
'Invalid application image for coredump: coredump SHA256 version({}) != app SHA256 version({}).'
Expand Down

0 comments on commit 76122fb

Please sign in to comment.