1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:37:35 +00:00

Kernel: Use Userspace<T> in ptrace syscall

This commit is contained in:
Brian Gianforcaro 2020-08-01 15:25:19 -07:00 committed by Andreas Kling
parent 85b2413403
commit 1209bf82c1
4 changed files with 17 additions and 16 deletions

View file

@ -447,13 +447,13 @@ struct SC_stat_params {
struct SC_ptrace_params {
int request;
pid_t pid;
u8* addr;
Userspace<u8*> addr;
int data;
};
struct SC_ptrace_peek_params {
u32* address;
u32* out_data;
Userspace<const u32*> address;
Userspace<u32*> out_data;
};
void initialize();

View file

@ -326,7 +326,7 @@ public:
int sys$unveil(const Syscall::SC_unveil_params*);
int sys$perf_event(int type, FlatPtr arg1, FlatPtr arg2);
int sys$get_stack_bounds(FlatPtr* stack_base, size_t* stack_size);
int sys$ptrace(const Syscall::SC_ptrace_params*);
int sys$ptrace(Userspace<const Syscall::SC_ptrace_params*>);
int sys$sendfd(int sockfd, int fd);
int sys$recvfd(int sockfd);
long sys$sysconf(int name);
@ -559,8 +559,8 @@ public:
m_wait_for_tracer_at_next_execve = val;
}
KResultOr<u32> peek_user_data(u32* address);
KResult poke_user_data(u32* address, u32 data);
KResultOr<u32> peek_user_data(Userspace<const u32*> address);
KResult poke_user_data(Userspace<u32*> address, u32 data);
private:
friend class MemoryManager;

View file

@ -98,7 +98,7 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
if (!tracer->has_regs())
return KResult(-EINVAL);
auto* regs = reinterpret_cast<PtraceRegisters*>(params.addr);
auto* regs = reinterpret_cast<PtraceRegisters*>(params.addr.unsafe_userspace_ptr());
if (!caller.validate_write_typed(regs))
return KResult(-EFAULT);
copy_to_user(regs, &tracer->regs());
@ -110,7 +110,7 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
return KResult(-EINVAL);
PtraceRegisters regs;
if (!caller.validate_read_and_copy_typed(&regs, (const PtraceRegisters*)params.addr))
if (!caller.validate_read_and_copy_typed(&regs, (const PtraceRegisters*)params.addr.unsafe_userspace_ptr()))
return KResult(-EFAULT);
auto& peer_saved_registers = peer->get_register_dump_from_stack();
@ -125,8 +125,9 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
case PT_PEEK: {
Kernel::Syscall::SC_ptrace_peek_params peek_params;
if (!caller.validate_read_and_copy_typed(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr)))
if (!caller.validate_read_and_copy_typed(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr.unsafe_userspace_ptr())))
return -EFAULT;
// read validation is done inside 'peek_user_data'
auto result = peer->process().peek_user_data(peek_params.address);
if (result.is_error())
@ -138,7 +139,7 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
}
case PT_POKE: {
u32* addr = reinterpret_cast<u32*>(params.addr);
Userspace<u32*> addr = reinterpret_cast<FlatPtr>(params.addr.ptr());
// write validation is done inside 'poke_user_data'
return peer->process().poke_user_data(addr, params.data);
}

View file

@ -34,7 +34,7 @@
namespace Kernel {
int Process::sys$ptrace(const Syscall::SC_ptrace_params* user_params)
int Process::sys$ptrace(Userspace<const Syscall::SC_ptrace_params*> user_params)
{
REQUIRE_PROMISE(proc);
Syscall::SC_ptrace_params params;
@ -58,10 +58,10 @@ bool Process::has_tracee_thread(int tracer_pid) const
return has_tracee;
}
KResultOr<u32> Process::peek_user_data(u32* address)
KResultOr<u32> Process::peek_user_data(Userspace<const u32*> address)
{
if (!MM.validate_user_read(*this, VirtualAddress(address), sizeof(u32))) {
dbg() << "Invalid address for peek_user_data: " << address;
dbg() << "Invalid address for peek_user_data: " << address.ptr();
return KResult(-EFAULT);
}
uint32_t result;
@ -74,12 +74,12 @@ KResultOr<u32> Process::peek_user_data(u32* address)
return result;
}
KResult Process::poke_user_data(u32* address, u32 data)
KResult Process::poke_user_data(Userspace<u32*> address, u32 data)
{
// We validate for read (rather than write) because PT_POKE can write to readonly pages.
// So we effectively only care that the poke operation is trying to write to user pages.
if (!MM.validate_user_read(*this, VirtualAddress(address), sizeof(u32))) {
dbg() << "Invalid address for poke_user_data: " << address;
dbg() << "Invalid address for poke_user_data: " << address.ptr();
return KResult(-EFAULT);
}
ProcessPagingScope scope(*this);
@ -88,7 +88,7 @@ KResult Process::poke_user_data(u32* address, u32 data)
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
// to prevent the write operation from changing 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);