:: commit 62d78d1f900095b3187fa8137bcfa505ad4a9df5

mintsuki <mintsuki@protonmail.com> — 2020-05-02 21:38

parents: adb083e107

Add out of memory checks

diff --git a/qloader2.bin b/qloader2.bin
index dd49ad0f..873de69d 100644
Binary files a/qloader2.bin and b/qloader2.bin differ
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 4337ae33..742eecf5 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -7,6 +7,25 @@
 #include <drivers/vga_textmode.h>
 #include <lib/real.h>
 #include <lib/cio.h>
+#include <lib/e820.h>
+
+// Checks if a given memory range is entirely within a usable e820 entry.
+// TODO: Consider the possibility of adjacent usable entries.
+// TODO: Consider the possibility of usable entry being overlapped by non-usable
+//       ones.
+void is_valid_memory_range(size_t base, size_t size) {
+    for (size_t i = 0; i < e820_entries; i++) {
+        if (e820_map[i].type != 1)
+            continue;
+        size_t entry_base = e820_map[i].base;
+        size_t entry_top  = e820_map[i].base + e820_map[i].length;
+        size_t limit      = base + size;
+        if (base  >= entry_base && base  < entry_top &&
+            limit >= entry_base && limit < entry_top)
+            return;
+    }
+    panic("Out of memory");
+}
 
 uint8_t bcd_to_int(uint8_t val) {
     return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;
diff --git a/src/lib/blib.h b/src/lib/blib.h
index 250979dd..4fbcbb02 100644
--- a/src/lib/blib.h
+++ b/src/lib/blib.h
@@ -4,6 +4,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+void is_valid_memory_range(size_t base, size_t size);
+
 uint8_t bcd_to_int(uint8_t val);
 
 int cpuid(uint32_t leaf, uint32_t subleaf,
diff --git a/src/lib/e820.c b/src/lib/e820.c
index f0e2e1a3..aaea8570 100644
--- a/src/lib/e820.c
+++ b/src/lib/e820.c
@@ -1,8 +1,11 @@
+#include <stdint.h>
+#include <stddef.h>
 #include <lib/e820.h>
 #include <lib/real.h>
 #include <lib/blib.h>
 
 struct e820_entry_t *e820_map;
+size_t e820_entries;
 
 static const char *e820_type(uint32_t type) {
     switch (type) {
@@ -21,13 +24,11 @@ static const char *e820_type(uint32_t type) {
     }
 }
 
-int init_e820(void) {
+void init_e820(void) {
     struct rm_regs r = {0};
 
-    int entry_count;
-
     e820_map = balloc(sizeof(struct e820_entry_t));
-    for (int i = 0; ; i++) {
+    for (size_t i = 0; ; i++) {
         struct e820_entry_t entry;
 
         r.eax = 0xe820;
@@ -39,25 +40,23 @@ int init_e820(void) {
         e820_map[i] = entry;
 
         if (r.eflags & EFLAGS_CF) {
-            entry_count = i;
+            e820_entries = i;
             break;
         }
 
         if (!r.ebx) {
-            entry_count = ++i;
+            e820_entries = ++i;
             break;
         }
 
         balloc(sizeof(struct e820_entry_t));
     }
 
-    for (int i = 0; i < entry_count; i++) {
+    for (size_t i = 0; i < e820_entries; i++) {
         print("e820: [%X -> %X] : %X  <%s>\n",
               e820_map[i].base,
               e820_map[i].base + e820_map[i].length,
               e820_map[i].length,
               e820_type(e820_map[i].type));
     }
-
-    return entry_count;
 }
diff --git a/src/lib/e820.h b/src/lib/e820.h
index 95e7ab2b..7ee07683 100644
--- a/src/lib/e820.h
+++ b/src/lib/e820.h
@@ -2,8 +2,7 @@
 #define __LIB__E820_H__
 
 #include <stdint.h>
-
-#define E820_MAX_ENTRIES 256
+#include <stddef.h>
 
 struct e820_entry_t {
     uint64_t base;
@@ -13,7 +12,8 @@ struct e820_entry_t {
 } __attribute__((packed));
 
 extern struct e820_entry_t *e820_map;
+extern size_t e820_entries;
 
-int init_e820(void);
+void init_e820(void);
 
 #endif
diff --git a/src/lib/elf.c b/src/lib/elf.c
index f0ff11db..71742545 100644
--- a/src/lib/elf.c
+++ b/src/lib/elf.c
@@ -243,8 +243,9 @@ int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *top) {
         if (this_top > *top)
             *top = this_top;
 
-        fread(fd, (void *)(uint32_t)phdr.p_vaddr,
-                   phdr.p_offset, phdr.p_filesz);
+        is_valid_memory_range((size_t)phdr.p_vaddr, (size_t)phdr.p_memsz);
+
+        fread(fd, (void *)(uint32_t)phdr.p_vaddr, phdr.p_offset, phdr.p_filesz);
 
         size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz);
 
@@ -292,6 +293,8 @@ int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t *top) {
         if (this_top > *top)
             *top = this_top;
 
+        is_valid_memory_range((size_t)phdr.p_paddr, (size_t)phdr.p_memsz);
+
         fread(fd, (void *)phdr.p_paddr, phdr.p_offset, phdr.p_filesz);
 
         size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz);
diff --git a/src/main.c b/src/main.c
index 8f44f728..3a0ff8ed 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,6 +20,7 @@ asm (
 #include <lib/libc.h>
 #include <lib/part.h>
 #include <lib/config.h>
+#include <lib/e820.h>
 #include <fs/file.h>
 #include <lib/elf.h>
 #include <protos/stivale.h>
@@ -149,6 +150,8 @@ void main(int boot_drive) {
     }
 
 got_entry:
+    init_e820();
+
     if (!config_get_value(buf, 0, 32, "KERNEL_DRIVE")) {
         drive = boot_drive;
     } else {
diff --git a/src/protos/linux.c b/src/protos/linux.c
index 21e88ce7..61443f08 100644
--- a/src/protos/linux.c
+++ b/src/protos/linux.c
@@ -7,6 +7,9 @@
 #include <drivers/vga_textmode.h>
 #include <lib/config.h>
 
+#define KERNEL_LOAD_ADDR ((size_t)0x100000)
+#define INITRD_LOAD_ADDR ((size_t)0x1000000)
+
 void linux_load(struct file_handle *fd, char *cmdline) {
     uint32_t signature;
     fread(fd, &signature, 0x202, sizeof(uint32_t));
@@ -70,7 +73,8 @@ void linux_load(struct file_handle *fd, char *cmdline) {
 
     // load kernel
     print("Loading kernel...\n");
-    fread(fd, (void *)0x100000, real_mode_code_size, fd->size - real_mode_code_size);
+    is_valid_memory_range(KERNEL_LOAD_ADDR, fd->size - real_mode_code_size);
+    fread(fd, (void *)KERNEL_LOAD_ADDR, real_mode_code_size, fd->size - real_mode_code_size);
 
     char initrd_path[64];
     if (!config_get_value(initrd_path, 0, 64, "INITRD_PATH"))
@@ -88,10 +92,10 @@ void linux_load(struct file_handle *fd, char *cmdline) {
     }
 
     print("Loading initrd...\n");
-    size_t initrd_addr = 0x1000000;
-    fread(&initrd, (void *)initrd_addr, 0, initrd.size);
+    is_valid_memory_range(INITRD_LOAD_ADDR, initrd.size);
+    fread(&initrd, (void *)INITRD_LOAD_ADDR, 0, initrd.size);
 
-    *((uint32_t *)(real_mode_code + 0x218)) = (uint32_t)initrd_addr;
+    *((uint32_t *)(real_mode_code + 0x218)) = (uint32_t)INITRD_LOAD_ADDR;
     *((uint32_t *)(real_mode_code + 0x21c)) = (uint32_t)initrd.size;
 
     uint16_t real_mode_code_seg = rm_seg(real_mode_code);
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index 148f69eb..4464e832 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -97,7 +97,7 @@ void stivale_load(struct file_handle *fd, char *cmdline) {
 
     print("stivale: Top used address in ELF: %X\n", top_used_addr);
 
-    stivale_struct.memory_map_entries = (uint64_t)init_e820();
+    stivale_struct.memory_map_entries = (uint64_t)e820_entries;
     stivale_struct.memory_map_addr    = (uint64_t)(size_t)e820_map;
 
     stivale_struct.module_count = 0;
@@ -126,6 +126,7 @@ void stivale_load(struct file_handle *fd, char *cmdline) {
             ((uint32_t)top_used_addr & ~((uint32_t)0xfff)) + 0x1000 :
             (uint32_t)top_used_addr);
 
+        is_valid_memory_range((size_t)module_addr, f.size);
         fread(&f, module_addr, 0, f.size);
 
         m->begin = (uint64_t)(size_t)module_addr;
tab: 248 wrap: offon