diff options
Diffstat (limited to 'Kernel/Process.cpp')
-rw-r--r-- | Kernel/Process.cpp | 42 |
1 files changed, 40 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; } |