:: commit b0152c9a67d1beb52aa4f70a819e8112370e9474

Mintsuki <mintsuki@protonmail.com> — 2026-04-02 19:00

parents: 35ade5f557

lib/elf: Validate section header bounds in elf_section_hdr_info functions

diff --git a/common/lib/elf.c b/common/lib/elf.c
index 43cd6d47..200d8dde 100644
--- a/common/lib/elf.c
+++ b/common/lib/elf.c
@@ -208,13 +208,18 @@ int elf_bits(uint8_t *elf, size_t file_size) {
     }
 }
 
-struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf) {
+struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf, size_t file_size) {
     struct elf_section_hdr_info info = {0};
 
     struct elf64_hdr *hdr = (void *)elf;
 
     elf64_validate(hdr);
 
+    if (CHECKED_ADD(CHECKED_MUL(hdr->sh_num, hdr->shdr_size, return info),
+            hdr->shoff, return info) > file_size) {
+        return info;
+    }
+
     info.num = hdr->sh_num;
     info.section_entry_size = hdr->shdr_size;
     info.str_section_idx = hdr->shstrndx;
@@ -223,13 +228,18 @@ struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf) {
     return info;
 }
 
-struct elf_section_hdr_info elf32_section_hdr_info(uint8_t *elf) {
+struct elf_section_hdr_info elf32_section_hdr_info(uint8_t *elf, size_t file_size) {
     struct elf_section_hdr_info info = {0};
 
     struct elf32_hdr *hdr = (void *)elf;
 
     elf32_validate(hdr);
 
+    if (CHECKED_ADD(CHECKED_MUL(hdr->sh_num, hdr->shdr_size, return info),
+            hdr->shoff, return info) > file_size) {
+        return info;
+    }
+
     info.num = hdr->sh_num;
     info.section_entry_size = hdr->shdr_size;
     info.str_section_idx = hdr->shstrndx;
diff --git a/common/lib/elf.h b/common/lib/elf.h
index 1b9b5888..080694d3 100644
--- a/common/lib/elf.h
+++ b/common/lib/elf.h
@@ -21,8 +21,8 @@ struct elf_section_hdr_info {
 
 int elf_bits(uint8_t *elf, size_t file_size);
 
-struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf);
-struct elf_section_hdr_info elf32_section_hdr_info(uint8_t *elf);
+struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf, size_t file_size);
+struct elf_section_hdr_info elf32_section_hdr_info(uint8_t *elf, size_t file_size);
 
 bool elf64_load_section(uint8_t *elf, size_t file_size, void *buffer, const char *name, size_t limit, uint64_t slide);
 bool elf64_load(uint8_t *elf, size_t file_size, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct mem_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *image_size, uint64_t *image_size_before_bss, bool *is_reloc);
diff --git a/common/protos/multiboot1.c b/common/protos/multiboot1.c
index eed18d81..707fc422 100644
--- a/common/protos/multiboot1.c
+++ b/common/protos/multiboot1.c
@@ -166,14 +166,14 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
                 if (!elf32_load_elsewhere(kernel, kernel_file_size, &entry_point, &ranges))
                     panic(true, "multiboot1: ELF32 load failure");
 
-                section_hdr_info = elf32_section_hdr_info(kernel);
+                section_hdr_info = elf32_section_hdr_info(kernel, kernel_file_size);
                 section_hdr_info_valid = true;
                 break;
             case 64: {
                 if (!elf64_load_elsewhere(kernel, kernel_file_size, &entry_point, &ranges))
                     panic(true, "multiboot1: ELF64 load failure");
 
-                section_hdr_info = elf64_section_hdr_info(kernel);
+                section_hdr_info = elf64_section_hdr_info(kernel, kernel_file_size);
                 section_hdr_info_valid = true;
                 break;
             }
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index 088f095e..a0c072b1 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -362,14 +362,14 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
                 if (!elf32_load_elsewhere(kernel, kernel_file_size, &e, &ranges))
                     panic(true, "multiboot2: ELF32 load failure");
 
-                section_hdr_info = elf32_section_hdr_info(kernel);
+                section_hdr_info = elf32_section_hdr_info(kernel, kernel_file_size);
                 section_hdr_info_valid = true;
                 break;
             case 64: {
                 if (!elf64_load_elsewhere(kernel, kernel_file_size, &e, &ranges))
                     panic(true, "multiboot2: ELF64 load failure");
 
-                section_hdr_info = elf64_section_hdr_info(kernel);
+                section_hdr_info = elf64_section_hdr_info(kernel, kernel_file_size);
                 section_hdr_info_valid = true;
                 break;
             }
tab: 248 wrap: offon