:: commit ca253330a8f36742790d6732ced86558d5d779a8

Mintsuki <mintsuki@protonmail.com> — 2026-04-01 19:13

parents: 7041ea96c0

lib/elsewhere: Add bounds check to elsewhere_append

diff --git a/common/lib/elsewhere.c b/common/lib/elsewhere.c
index 69c7ae61..f6aead32 100644
--- a/common/lib/elsewhere.c
+++ b/common/lib/elsewhere.c
@@ -13,6 +13,7 @@ static bool elsewhere_overlap_check(uint64_t base1, uint64_t top1,
 bool elsewhere_append(
         bool flexible_target,
         struct elsewhere_range *ranges, uint64_t *ranges_count,
+        uint64_t ranges_max,
         void *elsewhere, uint64_t *target, size_t t_length) {
     // original target of -1 means "allocate after top of all ranges"
     // flexible target is ignored
@@ -91,6 +92,9 @@ retry:
     }
 
     // Add the elsewhere range
+    if (*ranges_count >= ranges_max) {
+        panic(false, "elsewhere: ranges array overflow");
+    }
     ranges[*ranges_count].elsewhere = (uintptr_t)elsewhere;
     ranges[*ranges_count].target = *target;
     ranges[*ranges_count].length = t_length;
diff --git a/common/lib/elsewhere.h b/common/lib/elsewhere.h
index 99e14329..7ef3ff52 100644
--- a/common/lib/elsewhere.h
+++ b/common/lib/elsewhere.h
@@ -14,6 +14,7 @@ struct elsewhere_range {
 bool elsewhere_append(
         bool flexible_target,
         struct elsewhere_range *ranges, uint64_t *ranges_count,
+        uint64_t ranges_max,
         void *elsewhere, uint64_t *target, size_t t_length);
 
 #endif
diff --git a/common/protos/multiboot1.c b/common/protos/multiboot1.c
index ce78dfd1..d5940f85 100644
--- a/common/protos/multiboot1.c
+++ b/common/protos/multiboot1.c
@@ -202,11 +202,11 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
     );
 
     // Realloc elsewhere ranges to include mb1 info, modules, and elf sections
-    struct elsewhere_range *new_ranges = ext_mem_alloc(sizeof(struct elsewhere_range) *
-        (ranges_count
+    uint64_t ranges_max = ranges_count
        + 1 /* mb1 info range */
        + n_modules
-       + (section_hdr_info_valid ? section_hdr_info.num : 0)));
+       + (section_hdr_info_valid ? section_hdr_info.num : 0);
+    struct elsewhere_range *new_ranges = ext_mem_alloc_counted(ranges_max, sizeof(struct elsewhere_range));
 
     memcpy(new_ranges, ranges, sizeof(struct elsewhere_range) * ranges_count);
     pmm_free(ranges, sizeof(struct elsewhere_range) * ranges_count);
@@ -223,7 +223,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
     uint64_t mb1_info_final_loc = 0x10000;
 
     if (!elsewhere_append(true /* flexible target */,
-            ranges, &ranges_count,
+            ranges, &ranges_count, ranges_max,
             mb1_info_raw, &mb1_info_final_loc, mb1_info_size)) {
         panic(true, "multiboot1: Cannot allocate mb1 info");
     }
@@ -269,7 +269,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
                 uint64_t section = (uint64_t)-1; /* no target preference, use top */
 
                 if (!elsewhere_append(true /* flexible target */,
-                        ranges, &ranges_count,
+                        ranges, &ranges_count, ranges_max,
                         kernel + shdr->sh_offset, &section, shdr->sh_size)) {
                     panic(true, "multiboot1: Cannot allocate elf sections");
                 }
@@ -290,7 +290,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
                 uint64_t section = (uint64_t)-1; /* no target preference, use top */
 
                 if (!elsewhere_append(true /* flexible target */,
-                        ranges, &ranges_count,
+                        ranges, &ranges_count, ranges_max,
                         kernel + shdr->sh_offset, &section, shdr->sh_size)) {
                     panic(true, "multiboot1: Cannot allocate elf sections");
                 }
@@ -334,7 +334,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
             uint64_t module_target = (uint64_t)-1; /* no target preference, use top */
 
             if (!elsewhere_append(true /* flexible target */,
-                    ranges, &ranges_count,
+                    ranges, &ranges_count, ranges_max,
                     module_addr, &module_target, f->size)) {
                 panic(true, "multiboot1: Cannot allocate module");
             }
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index 48746e3f..5bd0bb10 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -468,11 +468,11 @@ reloc_fail:
     size_t info_idx = 0;
 
     // Realloc elsewhere ranges to include mb2 info, modules, and elf sections
-    struct elsewhere_range *new_ranges = ext_mem_alloc(sizeof(struct elsewhere_range) *
-        (ranges_count
+    uint64_t ranges_max = ranges_count
        + 1 /* mb2 info range */
        + n_modules
-       + (section_hdr_info_valid ? section_hdr_info.num : 0)));
+       + (section_hdr_info_valid ? section_hdr_info.num : 0);
+    struct elsewhere_range *new_ranges = ext_mem_alloc_counted(ranges_max, sizeof(struct elsewhere_range));
 
     memcpy(new_ranges, ranges, sizeof(struct elsewhere_range) * ranges_count);
     pmm_free(ranges, sizeof(struct elsewhere_range) * ranges_count);
@@ -489,7 +489,7 @@ reloc_fail:
     uint64_t mb2_info_final_loc = 0x10000;
 
     if (!elsewhere_append(true /* flexible target */,
-            ranges, &ranges_count,
+            ranges, &ranges_count, ranges_max,
             mb2_info, &mb2_info_final_loc, mb2_info_size)) {
         panic(true, "multiboot2: Cannot allocate mb2 info");
     }
@@ -551,7 +551,7 @@ reloc_fail:
                 uint64_t section = (uint64_t)-1; /* no target preference, use top */
 
                 if (!elsewhere_append(true /* flexible target */,
-                        ranges, &ranges_count,
+                        ranges, &ranges_count, ranges_max,
                         kernel + shdr->sh_offset, &section, shdr->sh_size)) {
                     panic(true, "multiboot2: Cannot allocate elf sections");
                 }
@@ -576,7 +576,7 @@ reloc_fail:
                 uint64_t section = (uint64_t)-1; /* no target preference, use top */
 
                 if (!elsewhere_append(true /* flexible target */,
-                        ranges, &ranges_count,
+                        ranges, &ranges_count, ranges_max,
                         kernel + shdr->sh_offset, &section, shdr->sh_size)) {
                     panic(true, "multiboot2: Cannot allocate elf sections");
                 }
@@ -626,7 +626,7 @@ reloc_fail:
         uint64_t module_target = (uint64_t)-1;
 
         if (!elsewhere_append(true /* flexible target */,
-                ranges, &ranges_count,
+                ranges, &ranges_count, ranges_max,
                 module_addr, &module_target, f->size)) {
             panic(true, "multiboot2: Cannot allocate module");
         }
tab: 248 wrap: offon