瀏覽代碼

Kernel: Scheduler donations need to verify that the beneficiary is valid.

Add a Thread::is_thread(void*) helper that we can use to check that the
incoming donation beneficiary is a valid thread. The O(n) here is a bit sad
and we should eventually rethink the process/thread table data structures.
Andreas Kling 6 年之前
父節點
當前提交
c59f8cd663
共有 3 個文件被更改,包括 19 次插入5 次删除
  1. 8 5
      Kernel/Scheduler.cpp
  2. 10 0
      Kernel/Thread.cpp
  3. 1 0
      Kernel/Thread.h

+ 8 - 5
Kernel/Scheduler.cpp

@@ -243,11 +243,14 @@ bool Scheduler::pick_next()
 
 bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
 {
+    InterruptDisabler disabler;
+    if (!Thread::is_thread(beneficiary))
+        return false;
+
     (void)reason;
     unsigned ticks_left = current->ticks_left();
-    if (!beneficiary || beneficiary->state() != Thread::Runnable || ticks_left <= 1) {
+    if (!beneficiary || beneficiary->state() != Thread::Runnable || ticks_left <= 1)
         return yield();
-    }
 
     unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(beneficiary->process().priority()));
 #ifdef SCHEDULER_DEBUG
@@ -256,7 +259,7 @@ bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
     context_switch(*beneficiary);
     beneficiary->set_ticks_left(ticks_to_donate);
     switch_now();
-    return 0;
+    return false;
 }
 
 bool Scheduler::yield()
@@ -266,11 +269,11 @@ bool Scheduler::yield()
 //    dbgprintf("%s(%u:%u) yield()\n", current->process().name().characters(), current->pid(), current->tid());
 
     if (!pick_next())
-        return 1;
+        return false;
 
 //    dbgprintf("yield() jumping to new process: sel=%x, %s(%u:%u)\n", current->far_ptr().selector, current->process().name().characters(), current->pid(), current->tid());
     switch_now();
-    return 0;
+    return true;
 }
 
 void Scheduler::pick_next_and_switch_now()

+ 10 - 0
Kernel/Thread.cpp

@@ -526,3 +526,13 @@ Vector<Thread*> Thread::all_threads()
         threads.append(thread);
     return threads;
 }
+
+bool Thread::is_thread(void* ptr)
+{
+    ASSERT_INTERRUPTS_DISABLED();
+    for (auto* thread = g_threads->head(); thread; thread = thread->next()) {
+        if (thread == ptr)
+            return true;
+    }
+    return false;
+}

+ 1 - 0
Kernel/Thread.h

@@ -34,6 +34,7 @@ public:
     static void finalize_dying_threads();
 
     static Vector<Thread*> all_threads();
+    static bool is_thread(void*);
 
     int tid() const { return m_tid; }
     int pid() const;