:: commit 9540ea620b1fc2538d2d51e91a9c20a7d3205a2a

mintsuki <mintsuki@protonmail.com> — 2021-07-29 13:44

parents: af28eee1bc

elf: Make sure KASLR doesn't result in load addresses higher than 0x80000000 for higher half kernels

diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c
index d7d159d7..6a6030f5 100644
--- a/stage23/lib/elf.c
+++ b/stage23/lib/elf.c
@@ -8,8 +8,6 @@
 #include <mm/pmm.h>
 #include <fs/file.h>
 
-#define KASLR_SLIDE_BITMASK ((uintptr_t)0x8ffff000)
-
 #define PT_LOAD     0x00000001
 #define PT_INTERP   0x00000003
 #define PT_PHDR     0x00000006
@@ -394,10 +392,7 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl
     uint64_t entry = hdr.entry;
     bool entry_adjusted = false;
 
-    uint64_t max_align = 1;
-    if (ranges != NULL) {
-        max_align = elf64_max_align(elf);
-    }
+    uint64_t max_align = elf64_max_align(elf);
 
     if (!elf64_is_relocatable(elf, &hdr)) {
         simulation = false;
@@ -406,12 +401,14 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl
 
 again:
     if (kaslr)
-        slide = (rand64() & KASLR_SLIDE_BITMASK) & ~(max_align - 1);
+        slide = rand32() & ~(max_align - 1);
 
 final:
     if (top)
         *top = 0;
 
+    bool higher_half = false;
+
     for (uint16_t i = 0; i < hdr.ph_num; i++) {
         struct elf64_phdr phdr;
         memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)),
@@ -427,14 +424,25 @@ final:
         } else {
             load_addr = phdr.p_vaddr;
 
-            if (load_addr & ((uint64_t)1 << 63))
+            if (load_addr & ((uint64_t)1 << 63)) {
+                higher_half = true;
                 load_addr -= FIXED_HIGHER_HALF_OFFSET_64;
+            }
+        }
+
+        if (higher_half == true && load_addr + phdr.p_memsz > 0x80000000) {
+            panic("elf: Higher half executable trying to load too high");
         }
 
         load_addr += slide;
 
         uint64_t this_top = load_addr + phdr.p_memsz;
 
+        // Make sure we don't overshoot due to KASLR
+        if (higher_half == true && this_top > 0x80000000) {
+            goto again;
+        }
+
         if (top) {
             if (this_top > *top) {
                 *top = this_top;
tab: 248 wrap: offon