Browse Source

Kernel: Fix race causing modifying a Process to fail with a panic

The ProtectedDataMutationScope cannot blindly assume that there is only
exactly one thread at a time that may want to unprotect the Process.
Most of the time the big lock guaranteed this, but there are some cases
such as finalization (among others) where this is not necessarily
guaranteed.

This fixes random panics due to access violations when the
ProtectedDataMutationScope protects the Process instance while another
is still modifying it.

Fixes #8512
Tom 4 years ago
parent
commit
a95b726fd8
2 changed files with 8 additions and 2 deletions
  1. 6 2
      Kernel/Process.cpp
  2. 2 0
      Kernel/Process.h

+ 6 - 2
Kernel/Process.cpp

@@ -205,12 +205,16 @@ RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, Str
 
 void Process::protect_data()
 {
-    MM.set_page_writable_direct(VirtualAddress { this }, false);
+    m_protected_data_refs.unref([&]() {
+        MM.set_page_writable_direct(VirtualAddress { this }, false);
+    });
 }
 
 void Process::unprotect_data()
 {
-    MM.set_page_writable_direct(VirtualAddress { this }, true);
+    m_protected_data_refs.ref([&]() {
+        MM.set_page_writable_direct(VirtualAddress { this }, true);
+    });
 }
 
 RefPtr<Process> Process::create(RefPtr<Thread>& first_thread, const String& name, uid_t uid, gid_t gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> cwd, RefPtr<Custody> executable, TTY* tty, Process* fork_parent)

+ 2 - 0
Kernel/Process.h

@@ -17,6 +17,7 @@
 #include <AK/WeakPtr.h>
 #include <AK/Weakable.h>
 #include <Kernel/API/Syscall.h>
+#include <Kernel/AtomicEdgeAction.h>
 #include <Kernel/FileSystem/FileDescription.h>
 #include <Kernel/FileSystem/InodeMetadata.h>
 #include <Kernel/Forward.h>
@@ -569,6 +570,7 @@ private:
 
     RefPtr<ProcessGroup> m_pg;
 
+    AtomicEdgeAction<u32> m_protected_data_refs;
     void protect_data();
     void unprotect_data();