From 9540ea620b1fc2538d2d51e91a9c20a7d3205a2a Mon Sep 17 00:00:00 2001 From: mintsuki Date: Thu, 29 Jul 2021 15:44:27 +0200 Subject: [PATCH] elf: Make sure KASLR doesn't result in load addresses higher than 0x80000000 for higher half kernels --- stage23/lib/elf.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) 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 #include -#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;