:: commit 91e5e5668f23db7fae432d8291e7c6a037d4759d

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

parents: f1814a42d9

lib/elf: Add file_size parameter to elf_bits for bounds checking

diff --git a/common/lib/elf.c b/common/lib/elf.c
index a9c6e7d3..6d762f9e 100644
--- a/common/lib/elf.c
+++ b/common/lib/elf.c
@@ -181,7 +181,11 @@ static bool elf64_validate(struct elf64_hdr *hdr) {
     return true;
 }
 
-int elf_bits(uint8_t *elf) {
+int elf_bits(uint8_t *elf, size_t file_size) {
+    if (file_size < sizeof(struct elf64_hdr)) {
+        return -1;
+    }
+
     struct elf64_hdr *hdr = (void *)elf;
 
     if (strncmp((char *)hdr->ident, "\177ELF", 4)) {
diff --git a/common/lib/elf.h b/common/lib/elf.h
index e8d5b280..1b9b5888 100644
--- a/common/lib/elf.h
+++ b/common/lib/elf.h
@@ -19,7 +19,7 @@ struct elf_section_hdr_info {
     uint64_t section_offset;
 };
 
-int elf_bits(uint8_t *elf);
+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);
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 060a235e..b8767436 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -42,7 +42,7 @@ enum executable_format {
 };
 
 static enum executable_format detect_kernel_format(uint8_t *kernel, size_t kernel_size) {
-    if (elf_bits(kernel) != -1) {
+    if (elf_bits(kernel, kernel_size) != -1) {
         return EXECUTABLE_FORMAT_ELF;
     } else if (pe_bits(kernel, kernel_size) != -1) {
         return EXECUTABLE_FORMAT_PE;
diff --git a/common/protos/multiboot1.c b/common/protos/multiboot1.c
index d5940f85..06f761d6 100644
--- a/common/protos/multiboot1.c
+++ b/common/protos/multiboot1.c
@@ -158,7 +158,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
         ranges->target = header.load_addr;
         ranges->length = full_size;
     } else {
-        int bits = elf_bits(kernel);
+        int bits = elf_bits(kernel, kernel_file_size);
 
         switch (bits) {
             case 32:
@@ -251,7 +251,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
 
         memcpy(sections, kernel + section_hdr_info.section_offset, section_table_size);
 
-        int bits = elf_bits(kernel);
+        int bits = elf_bits(kernel, kernel_file_size);
 
         for (size_t i = 0; i < section_hdr_info.num; i++) {
             if (bits == 64) {
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index 734fbf8f..7b46462a 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -344,7 +344,7 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
         ranges->length = full_size;
     } else {
         uint64_t e;
-        int bits = elf_bits(kernel);
+        int bits = elf_bits(kernel, kernel_file_size);
 
         switch (bits) {
             case 32:
@@ -526,7 +526,7 @@ reloc_fail:
 
         memcpy(tag->sections, kernel + section_hdr_info.section_offset, section_table_size);
 
-        int bits = elf_bits(kernel);
+        int bits = elf_bits(kernel, kernel_file_size);
 
         if ((bits == 64 && section_hdr_info.section_entry_size < sizeof(struct elf64_shdr)) ||
             (bits == 32 && section_hdr_info.section_entry_size < sizeof(struct elf32_shdr))) {
tab: 248 wrap: offon