From 97d0a177989131a5f6c1966433b45776ea2d5342 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Fri, 29 Oct 2021 19:51:22 +0200 Subject: [PATCH] stivale2: Introduce fully virtual kernel mappings (KASLR/PIE fixes) --- stage23/lib/elf.c | 29 +++++++++++++++++++---------- stage23/protos/stivale2.c | 3 +++ test/Makefile | 10 ++++++---- test/linker.ld | 5 +++++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c index db12643f..76755969 100644 --- a/stage23/lib/elf.c +++ b/stage23/lib/elf.c @@ -457,6 +457,8 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl uint64_t max_align = elf64_max_align(elf); + uint64_t image_size = 0; + if (fully_virtual) { simulation = false; @@ -470,9 +472,6 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl if (phdr.p_type != PT_LOAD) continue; - if (phdr.p_type != PT_LOAD) - continue; - if (phdr.p_vaddr < min_vaddr) { min_vaddr = phdr.p_vaddr; } @@ -482,7 +481,7 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl } } - uint64_t image_size = max_vaddr - min_vaddr; + image_size = max_vaddr - min_vaddr; *physical_base = (uintptr_t)ext_mem_alloc_type_aligned(image_size, alloc_type, max_align); *virtual_base = min_vaddr; @@ -494,9 +493,19 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl } again: - if (kaslr) + if (kaslr) { slide = rand32() & ~(max_align - 1); + if (fully_virtual) { + if ((*virtual_base - FIXED_HIGHER_HALF_OFFSET_64) + slide + image_size >= 0x80000000) { + if (++try_count == max_simulated_tries) { + panic("elf: Image wants to load too high"); + } + goto again; + } + } + } + final: if (top) *top = 0; @@ -528,16 +537,12 @@ final: } if (!fully_virtual) { - 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 + // Make sure we don't overshoot if (higher_half == true && this_top > 0x80000000) { goto again; } @@ -596,6 +601,10 @@ final: goto final; } + if (fully_virtual) { + *virtual_base += slide; + } + *entry_point = entry + slide; if (_slide) *_slide = slide; diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c index d7e834d5..4a8d3119 100644 --- a/stage23/protos/stivale2.c +++ b/stage23/protos/stivale2.c @@ -169,6 +169,9 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table want_fully_virtual, &physical_base, &virtual_base)) panic("stivale2: ELF64 load failure"); + printv("stivale2: Physical base: %X\n", physical_base); + printv("stivale2: Virtual base: %X\n", virtual_base); + ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide); } diff --git a/test/Makefile b/test/Makefile index 45cb828f..28e7bbde 100644 --- a/test/Makefile +++ b/test/Makefile @@ -9,7 +9,10 @@ INTERNALLDFLAGS := \ -Tlinker.ld \ -nostdlib \ -zmax-page-size=0x1000 \ - -static + -static \ + -pie \ + --no-dynamic-linker \ + -ztext INTERNALCFLAGS := \ -I../stivale \ @@ -17,15 +20,14 @@ INTERNALCFLAGS := \ -std=gnu11 \ -ffreestanding \ -fno-stack-protector \ - -fno-pic -fno-pie \ + -fpie \ -mabi=sysv \ -mno-80387 \ -mno-mmx \ -mno-3dnow \ -mno-sse \ -mno-sse2 \ - -mno-red-zone \ - -mcmodel=kernel + -mno-red-zone all: test.elf diff --git a/test/linker.ld b/test/linker.ld index 18222830..69aa865a 100644 --- a/test/linker.ld +++ b/test/linker.ld @@ -6,6 +6,7 @@ PHDRS text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ + dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic segment needed for PIE */ } SECTIONS @@ -36,6 +37,10 @@ SECTIONS *(.data*) } :data + .dynamic : { + *(.dynamic) + } :data :dynamic + .bss : { *(COMMON) *(.bss*)