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, §ion, 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, §ion, 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, §ion, 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, §ion, 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");
}
