Bläddra i källkod

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 år sedan
förälder
incheckning
1ad0e05ea1
1 ändrade filer med 37 tillägg och 1 borttagningar
  1. 37 1
      Kernel/Prekernel/init.cpp

+ 37 - 1
Kernel/Prekernel/init.cpp

@@ -14,6 +14,11 @@
 #include <LibC/elf.h>
 #include <LibC/elf.h>
 #include <LibELF/Relocation.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
 // Defined in the linker script
 extern size_t __stack_chk_guard;
 extern size_t __stack_chk_guard;
 size_t __stack_chk_guard __attribute__((used));
 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.
 // This is where C++ execution begins, after boot.S transfers control here.
 //
 //
 
 
+u64 generate_secure_seed();
+
 extern "C" [[noreturn]] void init()
 extern "C" [[noreturn]] void init()
 {
 {
     if (multiboot_info_ptr->mods_count < 1)
     if (multiboot_info_ptr->mods_count < 1)
@@ -88,6 +95,10 @@ extern "C" [[noreturn]] void init()
 #else
 #else
     FlatPtr kernel_load_base = 0x2000200000;
     FlatPtr kernel_load_base = 0x2000200000;
 #endif
 #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;
     FlatPtr kernel_load_end = 0;
     for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) {
     for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) {
@@ -201,7 +212,7 @@ extern "C" [[noreturn]] void init()
 #if ARCH(I386)
 #if ARCH(I386)
         "add %0, %%esp"
         "add %0, %%esp"
 #else
 #else
-        "movabs %0, %%rax\n"
+        "mov %0, %%rax\n"
         "add %%rax, %%rsp"
         "add %%rax, %%rsp"
 #endif
 #endif
         ::"g"(kernel_mapping_base)
         ::"g"(kernel_mapping_base)
@@ -225,6 +236,31 @@ extern "C" [[noreturn]] void init()
     __builtin_unreachable();
     __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.
 // Define some Itanium C++ ABI methods to stop the linker from complaining.
 // If we actually call these something has gone horribly wrong
 // If we actually call these something has gone horribly wrong
 void* __dso_handle __attribute__((visibility("hidden")));
 void* __dso_handle __attribute__((visibility("hidden")));