瀏覽代碼

Kernel: Add a random offset to kernel stacks upon syscall entry

When entering the kernel from a syscall, we now insert a small bit of
stack padding after the RegisterDump. This makes kernel stacks less
deterministic across syscalls and may make some bugs harder to exploit.

Inspired by Elena Reshetova's talk on kernel stack exploitation.
Andreas Kling 5 年之前
父節點
當前提交
1d94b5eb04
共有 2 個文件被更改,包括 14 次插入0 次删除
  1. 8 0
      Kernel/Arch/i386/CPU.h
  2. 6 0
      Kernel/Syscall.cpp

+ 8 - 0
Kernel/Arch/i386/CPU.h

@@ -447,6 +447,14 @@ inline void read_tsc(u32& lsw, u32& msw)
                  : "=d"(msw), "=a"(lsw));
                  : "=d"(msw), "=a"(lsw));
 }
 }
 
 
+inline u64 read_tsc()
+{
+    u32 lsw;
+    u32 msw;
+    read_tsc(lsw, msw);
+    return ((u64)msw << 32) | lsw;
+}
+
 struct Stopwatch {
 struct Stopwatch {
     union SplitQword {
     union SplitQword {
         struct {
         struct {

+ 6 - 0
Kernel/Syscall.cpp

@@ -92,6 +92,12 @@ int handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
 
 
 void syscall_handler(RegisterDump regs)
 void syscall_handler(RegisterDump regs)
 {
 {
+    // Apply a random offset in the range 0-255 to the stack pointer,
+    // to make kernel stacks a bit less deterministic.
+    auto* ptr = (char*)__builtin_alloca(read_tsc() & 0xff);
+    asm volatile(""
+                 : "=m"(*ptr));
+
     auto& process = current->process();
     auto& process = current->process();
 
 
     if (!MM.validate_user_stack(process, VirtualAddress(regs.esp_if_crossRing))) {
     if (!MM.validate_user_stack(process, VirtualAddress(regs.esp_if_crossRing))) {