Kaynağa Gözat

Kernel: Panic if we're about to switch to a user thread with IOPL!=0

This is a crude protection against IOPL elevation attacks. If for
any reason we find ourselves about to switch to a user mode thread
with IOPL != 0, we'll now simply panic the kernel.

If this happens, it basically means that something tricked the kernel
into incorrectly modifying the IOPL of a thread, so it's no longer
safe to trust the kernel anyway.
Andreas Kling 4 yıl önce
ebeveyn
işleme
c25cf5fb56
2 değiştirilmiş dosya ile 14 ekleme ve 0 silme
  1. 6 0
      Kernel/Arch/i386/CPU.h
  2. 8 0
      Kernel/Scheduler.cpp

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

@@ -44,6 +44,12 @@ class PageDirectory;
 class PageTableEntry;
 
 static constexpr u32 safe_eflags_mask = 0xdff;
+static constexpr u32 iopl_mask = 3u << 12;
+
+inline u32 get_iopl_from_eflags(u32 eflags)
+{
+    return (eflags & iopl_mask) >> 12;
+}
 
 struct [[gnu::packed]] DescriptorTablePointer
 {

+ 8 - 0
Kernel/Scheduler.cpp

@@ -356,6 +356,14 @@ bool Scheduler::context_switch(Thread* thread)
     enter_current(*from_thread, false);
     ASSERT(thread == Thread::current());
 
+#if ARCH(I386)
+    auto iopl = get_iopl_from_eflags(Thread::current()->get_register_dump_from_stack().eflags);
+    if (thread->process().is_user_process() && iopl != 0) {
+        dbgln("PANIC: Switched to thread {} with non-zero IOPL={}", Thread::current()->tid().value(), iopl);
+        Processor::halt();
+    }
+#endif
+
     return true;
 }