:: commit c3db6d0c41c7a284cd50fc1687c01cc1d9fc8a40

mintsuki <mintsuki@protonmail.com> — 2021-04-15 02:32

parents: 3c0fd2b56b

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
 
tab: 248 wrap: offon