From 4043137cd74a282d9ab0e4a403d0a8f104a7fe70 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Thu, 19 Aug 2021 12:31:42 +0200 Subject: [PATCH] zdump: Fix handling of PT_LOAD segments with p_filesz < p_memsz in ELF DFI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the ELF specification, the file size of a PT_LOAD memory segment might be less than its memory size. In that case, the remaining bytes must be filled with zeros. The ELF DFI implementation didn't handle this case correctly. Such ELF core files might be produced by the makedumpfile tool. From elf.5 man page: ------------------------------------------------------ PT_LOAD The array element specifies a loadable segment, described by p_filesz and p_memsz. The bytes from the file are mapped to the beginning of the memory segment. If the segment's memory size p_memsz is larger than the file size p_filesz, the "extra" bytes are defined to hold the value 0 and to follow the segment's initialized area. The file size may not be larger than the memory size. Loadable segment entries in the program header table appear in ascending order, sorted on the p_vaddr member. Signed-off-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- zdump/dfi_elf.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/zdump/dfi_elf.c b/zdump/dfi_elf.c index f9a42511..18c8eb13 100644 --- a/zdump/dfi_elf.c +++ b/zdump/dfi_elf.c @@ -47,16 +47,20 @@ static int pt_load_add(Elf64_Phdr *phdr) return -EINVAL; if (phdr->p_offset + phdr->p_filesz > zg_size(g.fh)) return -EINVAL; - if (phdr->p_filesz == 0) { - /* Add zero memory chunk */ - dfi_mem_chunk_add(phdr->p_paddr, phdr->p_memsz, NULL, - dfi_mem_chunk_read_zero, NULL); - } else { + if (phdr->p_filesz > phdr->p_memsz) + return -EINVAL; + if (phdr->p_filesz > 0) { off_ptr = zg_alloc(sizeof(*off_ptr)); *off_ptr = phdr->p_offset; - dfi_mem_chunk_add(phdr->p_paddr, phdr->p_memsz, off_ptr, + dfi_mem_chunk_add(phdr->p_paddr, phdr->p_filesz, off_ptr, dfi_elf_mem_chunk_read_fn, zg_free); } + if (phdr->p_memsz - phdr->p_filesz > 0) { + /* Add zero memory chunk */ + dfi_mem_chunk_add(phdr->p_paddr + phdr->p_filesz, + phdr->p_memsz - phdr->p_filesz, NULL, + dfi_mem_chunk_read_zero, NULL); + } return 0; }