lib/elf: reject empty load images
The Multiboot elsewhere loader needs at least one non-empty PT_LOAD segment to construct a meaningful target range. Reject malformed ELF32 and ELF64 images before min/max address arithmetic can produce a bogus range.
diff --git a/common/lib/elf.c b/common/lib/elf.c
index 996c98dc..66fc1e60 100644
--- a/common/lib/elf.c
+++ b/common/lib/elf.c
@@ -1071,12 +1071,15 @@ bool elf32_load_elsewhere(uint8_t *elf, size_t file_size, uint64_t *entry_point,
uint64_t min_paddr = (uint64_t)-1;
uint64_t max_paddr = 0;
+ bool has_loadable = false;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
struct elf32_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
if (phdr->p_type != PT_LOAD || phdr->p_memsz == 0)
continue;
+ has_loadable = true;
+
if (phdr->p_paddr < min_paddr) {
min_paddr = phdr->p_paddr;
}
@@ -1087,6 +1090,9 @@ bool elf32_load_elsewhere(uint8_t *elf, size_t file_size, uint64_t *entry_point,
max_paddr = top;
}
}
+ if (!has_loadable) {
+ panic(true, "elf: No loadable segments");
+ }
uint64_t image_size_64 = max_paddr - min_paddr;
if (image_size_64 > SIZE_MAX) {
panic(true, "elf: Image size exceeds address space");
@@ -1155,12 +1161,15 @@ bool elf64_load_elsewhere(uint8_t *elf, size_t file_size, uint64_t *entry_point,
uint64_t min_paddr = (uint64_t)-1;
uint64_t max_paddr = 0;
+ bool has_loadable = false;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
struct elf64_phdr *phdr = (void *)elf + (hdr->phoff + i * hdr->phdr_size);
if (phdr->p_type != PT_LOAD || phdr->p_memsz == 0)
continue;
+ has_loadable = true;
+
if (phdr->p_paddr < min_paddr) {
min_paddr = phdr->p_paddr;
}
@@ -1171,6 +1180,9 @@ bool elf64_load_elsewhere(uint8_t *elf, size_t file_size, uint64_t *entry_point,
max_paddr = top;
}
}
+ if (!has_loadable) {
+ panic(true, "elf: No loadable segments");
+ }
uint64_t image_size = max_paddr - min_paddr;
if (image_size > SIZE_MAX) {
panic(true, "elf: Image size exceeds address space");
