multiboot1: Add bounds validation for ELF section headers
diff --git a/common/protos/multiboot1.c b/common/protos/multiboot1.c
index 791fc0cb..b31fe9a2 100644
--- a/common/protos/multiboot1.c
+++ b/common/protos/multiboot1.c
@@ -216,16 +216,21 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
mb1_info_alloc(&mb1_info_raw, sizeof(struct multiboot1_info));
if (section_hdr_info_valid == true) {
+ size_t section_table_size = (size_t)section_hdr_info.section_entry_size * section_hdr_info.num;
+ if (section_hdr_info.section_offset > kernel_file_size ||
+ section_table_size > kernel_file_size - section_hdr_info.section_offset) {
+ panic(true, "multiboot1: ELF section headers out of bounds");
+ }
+
multiboot1_info->elf_sect.num = section_hdr_info.num;
multiboot1_info->elf_sect.size = section_hdr_info.section_entry_size;
multiboot1_info->elf_sect.shndx = section_hdr_info.str_section_idx;
- void *sections = mb1_info_alloc(&mb1_info_raw,
- section_hdr_info.section_entry_size * section_hdr_info.num);
+ void *sections = mb1_info_alloc(&mb1_info_raw, section_table_size);
multiboot1_info->elf_sect.addr = (uintptr_t)sections - mb1_info_slide;
- memcpy(sections, kernel + section_hdr_info.section_offset, section_hdr_info.section_entry_size * section_hdr_info.num);
+ memcpy(sections, kernel + section_hdr_info.section_offset, section_table_size);
int bits = elf_bits(kernel);
@@ -237,6 +242,11 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
continue;
}
+ if (shdr->sh_offset > kernel_file_size ||
+ shdr->sh_size > kernel_file_size - shdr->sh_offset) {
+ continue;
+ }
+
uint64_t section = (uint64_t)-1; /* no target preference, use top */
if (!elsewhere_append(true /* flexible target */,
@@ -253,6 +263,11 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
continue;
}
+ if (shdr->sh_offset > kernel_file_size ||
+ shdr->sh_size > kernel_file_size - shdr->sh_offset) {
+ continue;
+ }
+
uint64_t section = (uint64_t)-1; /* no target preference, use top */
if (!elsewhere_append(true /* flexible target */,
@@ -260,7 +275,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
kernel + shdr->sh_offset, §ion, shdr->sh_size)) {
panic(true, "multiboot1: Cannot allocate elf sections");
}
-
+
shdr->sh_addr = section;
}
}
