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;
