stivale2: Introduce fully virtual kernel mappings (KASLR/PIE fixes)
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*)
