:: commit aa7f2871fe6f9df4f9a6bc1c78c51bf638ad00dd

Mintsuki <mintsuki@protonmail.com> — 2026-03-06 04:12

parents: ba45ebed49

protos/linux_risc: Validate kernel header before trusting image_size for allocation

diff --git a/common/protos/linux_risc.c b/common/protos/linux_risc.c
index 5b1951d8..c1c09567 100644
--- a/common/protos/linux_risc.c
+++ b/common/protos/linux_risc.c
@@ -95,9 +95,7 @@ struct boot_param {
 #define LINUX_HEADER_MAGIC2             0x818223cd
 #endif
 
-static const char *verify_kernel(struct boot_param *p) {
-    struct linux_header *header = p->kernel_base;
-
+static const char *verify_kernel(struct linux_header *header) {
     if (header->magic2 != LINUX_HEADER_MAGIC2) {
         return "kernel header magic does not match";
     }
@@ -436,15 +434,24 @@ noreturn void linux_load(char *config, char *cmdline) {
     }
 
     p.kernel_size = kernel_file->size;
+
+    if (p.kernel_size < sizeof(struct linux_header)) {
+        panic(true, "linux: kernel too small to contain a valid header");
+    }
+
+    struct linux_header tmp_hdr;
+    fread(kernel_file, &tmp_hdr, 0, sizeof(tmp_hdr));
+
+    const char *reason = verify_kernel(&tmp_hdr);
+    if (reason)
+        panic(true, "linux: invalid kernel image: %s", reason);
+
+    // Use image_size from kernel header for total memory including BSS
     size_t kernel_alloc_size = p.kernel_size;
-    // Read image_size from kernel header for total memory including BSS
-    if (p.kernel_size >= sizeof(struct linux_header)) {
-        struct linux_header tmp_hdr;
-        fread(kernel_file, &tmp_hdr, 0, sizeof(tmp_hdr));
-        if (tmp_hdr.image_size > kernel_alloc_size) {
-            kernel_alloc_size = tmp_hdr.image_size;
-        }
+    if (tmp_hdr.image_size > kernel_alloc_size) {
+        kernel_alloc_size = tmp_hdr.image_size;
     }
+
     p.kernel_base = ext_mem_alloc_type_aligned(
                 ALIGN_UP(kernel_alloc_size, 4096),
                 MEMMAP_KERNEL_AND_MODULES, 2 * 1024 * 1024);
@@ -452,10 +459,6 @@ noreturn void linux_load(char *config, char *cmdline) {
     fclose(kernel_file);
     printv("linux: loaded kernel `%s` at %p, size %U\n", kernel_path, p.kernel_base, (uint64_t)p.kernel_size);
 
-    const char *reason = verify_kernel(&p);
-    if (reason)
-        panic(true, "linux: invalid kernel image: %s", reason);
-
     load_module(&p, config);
 
     prepare_device_tree_blob(&p);
tab: 248 wrap: offon