If a buildroot enviorment does not provide libzstd and kexec_file_load a zstd compressed kernel, it will suffer from coredump.
The following is observed from the coredump Core was generated by `/sbin/kexec -s -p --command-line=BOOT_IMAGE=\(hd0,gpt2\)/vmlinuz-6.15.0-0.rc5.250509g9c69f8884904.47.fc43.aarch64\ ro\ rootflags=subvol=root\ irqpoll\ nr_cpus=1\ reset_devices\ cgroup_disable=memory\ udev.children-max=2\ panic=10\ swiotlb=noforce\ novmcoredd\ cma=0\ hugetlb_cma=0\ sbsa_gwdt.pretimeout=0 --initrd=/boot/initramfs-6.15.0-0.rc5.250509g9c69f8884904.47.fc43.aarch64kdump.img /boot/vmlinuz-6.15.0-0.rc5.250509g9c69f8884904.47.fc43.aarch64'. Program terminated with signal SIGSEGV, Segmentation fault. 143 if (!!memcmp(buf, "PE\0\0", 4)) { (gdb) Instead of coredump, it is better to exit elegantly by adding checkout on the PE header offset. Signed-off-by: Pingfan Liu <pi...@redhat.com> --- include/pe.h | 4 ++++ kexec/kexec-pe-zboot.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/pe.h b/include/pe.h index a1aa91e..9ab3e79 100644 --- a/include/pe.h +++ b/include/pe.h @@ -139,6 +139,10 @@ static int get_pehdr_offset(const char *buf) int pe_hdr_offset; pe_hdr_offset = *((int *)(buf + 0x3c)); + if (pe_hdr_offset < 0 || pe_hdr_offset > 4096) { + printf("PE header offset is not a reasonable value\n"); + return -1; + } buf += pe_hdr_offset; if (!!memcmp(buf, "PE\0\0", 4)) { printf("Not a PE file\n"); diff --git a/kexec/kexec-pe-zboot.c b/kexec/kexec-pe-zboot.c index 8e17b4e..c09f2ae 100644 --- a/kexec/kexec-pe-zboot.c +++ b/kexec/kexec-pe-zboot.c @@ -100,7 +100,10 @@ int pez_prepare(const char *crude_buf, off_t buf_sz, int *kernel_fd, dbgprintf("%s: decompressed size %ld\n", __func__, decompressed_size); /* Makefile.zboot pads Image with zero, but the trailing zero is not part of PE file */ - parse = kernel_uncompressed_buf + get_pehdr_offset(kernel_uncompressed_buf); + ret = get_pehdr_offset(kernel_uncompressed_buf); + if (ret < 0) + goto fail_bad_header; + parse = kernel_uncompressed_buf + ret; parse += sizeof(struct pe_hdr); opt_hdr = (struct pe32plus_opt_hdr*)parse; parse += sizeof(struct pe32plus_opt_hdr); -- 2.49.0