summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-21 00:06:19 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-21 00:14:56 +0100
commit928ee2c791b0789ad4e845062a8212f50fe299e3 (patch)
tree8abab1650b870d04b58afe8f3250e4619e563667 /Kernel/Arch
parent1f53dd0943c02baded5f10cdeb1cd8aea8cf6fa5 (diff)
downloadserenity-928ee2c791b0789ad4e845062a8212f50fe299e3.zip
Kernel: Don't let signals unblock threads while handling a page fault
It was possible to signal a process while it was paging in an inode backed VM object. This would cause the inode read to EINTR, and the page fault handler would assert. Solve this by simply not unblocking threads due to signals if they are currently busy handling a page fault. This is probably not the best way to solve this issue, so I've added a FIXME to that effect.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/i386/CPU.cpp9
1 files changed, 9 insertions, 0 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index e0aa077c3b..20be34443f 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -25,6 +25,7 @@
*/
#include <AK/Assertions.h>
+#include <AK/ScopeGuard.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/Types.h>
@@ -257,6 +258,14 @@ void page_fault_handler(TrapFrame* trap)
}
auto current_thread = Thread::current();
+
+ if (current_thread)
+ current_thread->set_handling_page_fault(true);
+ ScopeGuard guard = [current_thread] {
+ if (current_thread)
+ current_thread->set_handling_page_fault(false);
+ };
+
if (!faulted_in_kernel && !MM.validate_user_stack(current_thread->process(), VirtualAddress(regs.userspace_esp))) {
dbgln("Invalid stack pointer: {}", VirtualAddress(regs.userspace_esp));
handle_crash(regs, "Bad stack on page fault", SIGSTKFLT);