:: commit 28d8cc300258804ddc09c4c53915821f43f950b7

Kamila Szewczyk <k@iczelia.net> — 2026-04-26 11:35

parents: b0dbc8396a

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");
tab: 248 wrap: offon