summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Process.cpp42
-rw-r--r--Kernel/UnixTypes.h1
-rw-r--r--Kernel/VM/Region.h2
3 files changed, 43 insertions, 2 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index d3ccd13b87..ee27b6a7ba 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -4916,8 +4916,11 @@ int Process::sys$ptrace(const Syscall::SC_ptrace_params* user_params)
if (params.pid == m_pid)
return -EINVAL;
- InterruptDisabler disabler;
- auto* peer = Thread::from_tid(params.pid);
+ Thread* peer = nullptr;
+ {
+ InterruptDisabler disabler;
+ peer = Thread::from_tid(params.pid);
+ }
if (!peer)
return -ESRCH;
@@ -4974,6 +4977,7 @@ int Process::sys$ptrace(const Syscall::SC_ptrace_params* user_params)
}
break;
}
+
case PT_PEEK: {
uint32_t* addr = reinterpret_cast<uint32_t*>(params.addr);
if (!MM.validate_user_read(peer->process(), VirtualAddress(addr), sizeof(uint32_t))) {
@@ -4987,6 +4991,40 @@ int Process::sys$ptrace(const Syscall::SC_ptrace_params* user_params)
result = *addr;
return result;
+ }
+
+ case PT_POKE: {
+ uint32_t* addr = reinterpret_cast<uint32_t*>(params.addr);
+ // We validate for "read" because PT_POKE can write to readonly pages,
+ // as long as they are user pages
+ if (!MM.validate_user_read(peer->process(), VirtualAddress(addr), sizeof(uint32_t))) {
+ return -EFAULT;
+ }
+ ProcessPagingScope scope(peer->process());
+ Range range = { VirtualAddress(addr), sizeof(uint32_t) };
+ auto* region = peer->process().region_containing(range);
+ ASSERT(region != nullptr);
+ if (region->is_shared()) {
+ // If the region is shared, we change its vmobject to a PrivateInodeVMObject
+ // to prevent the write operation from chaning any shared inode data
+ ASSERT(region->vmobject().is_shared_inode());
+ region->set_vmobject(PrivateInodeVMObject::create_with_inode(static_cast<SharedInodeVMObject&>(region->vmobject()).inode()));
+ region->set_shared(false);
+ }
+ const bool was_writable = region->is_writable();
+ if (!was_writable) //TODO refactor into scopeguard
+ region->set_writable(true);
+ region->remap();
+
+ {
+ SmapDisabler dis;
+ *addr = params.data;
+ }
+
+ if (!was_writable) {
+ region->set_writable(false);
+ region->remap();
+ }
break;
}
diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h
index 4448de7f00..e698a1b3f2 100644
--- a/Kernel/UnixTypes.h
+++ b/Kernel/UnixTypes.h
@@ -555,3 +555,4 @@ struct rtentry {
#define PT_GETREGS 5
#define PT_DETACH 6
#define PT_PEEK 7
+#define PT_POKE 8
diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h
index 5671dec795..b71c8986e9 100644
--- a/Kernel/VM/Region.h
+++ b/Kernel/VM/Region.h
@@ -31,6 +31,7 @@
#include <AK/Weakable.h>
#include <Kernel/Heap/SlabAllocator.h>
#include <Kernel/VM/RangeAllocator.h>
+#include <Kernel/VM/VMObject.h>
namespace Kernel {
@@ -79,6 +80,7 @@ public:
const VMObject& vmobject() const { return *m_vmobject; }
VMObject& vmobject() { return *m_vmobject; }
+ void set_vmobject(NonnullRefPtr<VMObject>&& obj) { m_vmobject = obj; }
bool is_shared() const { return m_shared; }
void set_shared(bool shared) { m_shared = shared; }