Ver código fonte

Kernel: Add an extremely primitive version of KASLR

This initial (and very basic) implementation of KASLR simply randomizes
the kernel base VA in the 256 MiB range following the default load base.
Idan Horowitz 3 anos atrás
pai
commit
1ad0e05ea1
1 arquivos alterados com 37 adições e 1 exclusões
  1. 37 1
      Kernel/Prekernel/init.cpp

+ 37 - 1
Kernel/Prekernel/init.cpp

@@ -14,6 +14,11 @@
 #include <LibC/elf.h>
 #include <LibELF/Relocation.h>
 
+#if ARCH(I386) || ARCH(X86_64)
+#    include <Kernel/Arch/x86/ASM_wrapper.h>
+#    include <Kernel/Arch/x86/CPUID.h>
+#endif
+
 // Defined in the linker script
 extern size_t __stack_chk_guard;
 size_t __stack_chk_guard __attribute__((used));
@@ -67,6 +72,8 @@ extern "C" [[noreturn]] void init();
 // This is where C++ execution begins, after boot.S transfers control here.
 //
 
+u64 generate_secure_seed();
+
 extern "C" [[noreturn]] void init()
 {
     if (multiboot_info_ptr->mods_count < 1)
@@ -88,6 +95,10 @@ extern "C" [[noreturn]] void init()
 #else
     FlatPtr kernel_load_base = 0x2000200000;
 #endif
+    // KASLR
+    static constexpr auto maximum_offset = 256 * MiB;
+    kernel_load_base = kernel_load_base + (generate_secure_seed() % maximum_offset);
+    kernel_load_base = kernel_load_base & ~(PAGE_SIZE - 1);
 
     FlatPtr kernel_load_end = 0;
     for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) {
@@ -201,7 +212,7 @@ extern "C" [[noreturn]] void init()
 #if ARCH(I386)
         "add %0, %%esp"
 #else
-        "movabs %0, %%rax\n"
+        "mov %0, %%rax\n"
         "add %%rax, %%rsp"
 #endif
         ::"g"(kernel_mapping_base)
@@ -225,6 +236,31 @@ extern "C" [[noreturn]] void init()
     __builtin_unreachable();
 }
 
+u64 generate_secure_seed()
+{
+    u32 seed = 0xFEEBDAED;
+
+#if ARCH(I386) || ARCH(X86_64)
+    CPUID processor_info(0x1);
+    if (processor_info.edx() & (1 << 4)) // TSC
+        seed ^= read_tsc();
+
+    if (processor_info.ecx() & (1 << 30)) // RDRAND
+        seed ^= rdrand();
+
+    CPUID extended_features(0x7);
+    if (extended_features.ebx() & (1 << 18)) // RDSEED
+        seed ^= rdseed();
+#else
+#    warning No native randomness source available for this architecture
+#endif
+
+    seed ^= multiboot_info_ptr->mods_addr;
+    seed ^= multiboot_info_ptr->framebuffer_addr;
+
+    return seed;
+}
+
 // Define some Itanium C++ ABI methods to stop the linker from complaining.
 // If we actually call these something has gone horribly wrong
 void* __dso_handle __attribute__((visibility("hidden")));