stivale: Implement KASLR config option
diff --git a/CONFIG.md b/CONFIG.md
index 9f2913f7..dbf8fdc6 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -3,7 +3,8 @@
## Location of the config file
Limine scans for a config file on *the boot drive*. Every partition on the boot drive
-is scanned sequentially (first partition first, last partition last) for the presence of either a `/limine.cfg`, `/boot/limine.cfg`, or a `/EFI/BOOT/limine.cfg` file, in that order.
+is scanned sequentially (first partition first, last partition last) for the presence
+of either a `/limine.cfg`, `/boot/limine.cfg`, or a `/EFI/BOOT/limine.cfg` file, in that order.
Once the file is located, Limine will use it as its config file. Other possible
candidates in subsequent partitions or directories are ignored.
@@ -90,6 +91,7 @@ Some keys take *URIs* as values; these are described in the next section.
The entries will be matched in order. E.g.: the 1st module path entry will be matched
to the 1st module string entry that appear, and so on.
* `RESOLUTION` - The resolution to be used should the kernel request a graphical framebuffer. This setting takes the form of `<width>x<height>x<bpp>` and *overrides* any resolution requested by the kernel, or automatic resolution requests. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
+ * `KASLR` - For relocatable kernels, if set to `no`, disable kernel address space layout randomisation. KASLR is enabled by default.
* Chainload protocol:
* `DRIVE` - The 1-based BIOS drive to chainload.
* `PARTITION` - The 1-based BIOS partition to chainload, if omitted, chainload drive.
diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c
index 1977c8ee..8e15474f 100644
--- a/stage23/lib/elf.c
+++ b/stage23/lib/elf.c
@@ -292,7 +292,7 @@ int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limi
return 2;
}
-int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type) {
+int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr) {
struct elf64_hdr hdr;
memcpy(&hdr, elf + (0), sizeof(struct elf64_hdr));
@@ -322,7 +322,8 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t a
}
again:
- slide = rand64() & KASLR_SLIDE_BITMASK;
+ if (kaslr)
+ slide = rand64() & KASLR_SLIDE_BITMASK;
final:
for (uint16_t i = 0; i < hdr.ph_num; i++) {
@@ -343,6 +344,8 @@ final:
if (!memmap_alloc_range((size_t)load_vaddr, (size_t)phdr.p_memsz, alloc_type, true, false, simulation, false)) {
if (++try_count == max_simulated_tries || simulation == false)
return -1;
+ if (!kaslr)
+ slide += 0x1000;
goto again;
}
diff --git a/stage23/lib/elf.h b/stage23/lib/elf.h
index 564e82a5..e9b0b6c2 100644
--- a/stage23/lib/elf.h
+++ b/stage23/lib/elf.h
@@ -2,13 +2,14 @@
#define __LIB__ELF_H__
#include <stdint.h>
+#include <stdbool.h>
#include <fs/file.h>
#define FIXED_HIGHER_HALF_OFFSET_64 ((uint64_t)0xffffffff80000000)
int elf_bits(uint8_t *elf);
-int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *slide, uint32_t alloc_type);
+int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *slide, uint32_t alloc_type, bool kaslr);
int elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit, uint64_t slide);
int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t alloc_type);
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 9a93f646..f7e41642 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -51,6 +51,11 @@ void stivale_load(char *config, char *cmdline) {
bool level5pg = false;
+ char *kaslr_s = config_get_value(config, 0, "KASLR");
+ bool kaslr = true;
+ if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
+ kaslr = false;
+
uint64_t slide = 0;
uint64_t entry_point = 0;
@@ -67,7 +72,7 @@ void stivale_load(char *config, char *cmdline) {
level5pg = true;
}
- if (elf64_load(kernel, &entry_point, &slide, STIVALE_MMAP_KERNEL_AND_MODULES))
+ if (elf64_load(kernel, &entry_point, &slide, STIVALE_MMAP_KERNEL_AND_MODULES, kaslr))
panic("stivale: ELF64 load failure");
ret = elf64_load_section(kernel, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide);
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index 7e586c5a..49640738 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -74,6 +74,11 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
bool level5pg = false;
+ char *kaslr_s = config_get_value(config, 0, "KASLR");
+ bool kaslr = true;
+ if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
+ kaslr = false;
+
uint64_t slide = 0;
uint64_t entry_point = 0;
@@ -90,7 +95,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
level5pg = true;
}
- if (elf64_load(kernel, &entry_point, &slide, STIVALE2_MMAP_KERNEL_AND_MODULES))
+ if (elf64_load(kernel, &entry_point, &slide, STIVALE2_MMAP_KERNEL_AND_MODULES, kaslr))
panic("stivale2: ELF64 load failure");
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide);
diff --git a/test/Makefile b/test/Makefile
index c3f51dc8..e99d3f78 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,10 +3,9 @@ CFLAGS = -O2
LD = cc
QEMU = qemu-system-x86_64
QEMUFLAGS = -m 1G -enable-kvm -cpu host
-LDINTERNALFLAGS := -Tlinker.ld -nostdlib -static-pie -pie -fno-pic -fpie -z max-page-size=0x1000
+LDINTERNALFLAGS := -Tlinker.ld -nostdlib -pie -static-pie -fno-pic -fpie -z max-page-size=0x1000
INTERNALCFLAGS := -I../stivale -I. -ffreestanding -fno-stack-protector \
- -fno-pic -fpie -fomit-frame-pointer -mno-red-zone -mno-80387 -mno-mmx -mno-3dnow -mno-sse \
- -mno-sse2 -masm=intel
+ -fno-pic -fpie -fomit-frame-pointer -mno-red-zone -mgeneral-regs-only -masm=intel
all: test.elf
