mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:57:35 +00:00
Kernel: Use Userspace<T> in ptrace syscall
This commit is contained in:
parent
85b2413403
commit
1209bf82c1
4 changed files with 17 additions and 16 deletions
|
@ -447,13 +447,13 @@ struct SC_stat_params {
|
||||||
struct SC_ptrace_params {
|
struct SC_ptrace_params {
|
||||||
int request;
|
int request;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
u8* addr;
|
Userspace<u8*> addr;
|
||||||
int data;
|
int data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_ptrace_peek_params {
|
struct SC_ptrace_peek_params {
|
||||||
u32* address;
|
Userspace<const u32*> address;
|
||||||
u32* out_data;
|
Userspace<u32*> out_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
|
@ -326,7 +326,7 @@ public:
|
||||||
int sys$unveil(const Syscall::SC_unveil_params*);
|
int sys$unveil(const Syscall::SC_unveil_params*);
|
||||||
int sys$perf_event(int type, FlatPtr arg1, FlatPtr arg2);
|
int sys$perf_event(int type, FlatPtr arg1, FlatPtr arg2);
|
||||||
int sys$get_stack_bounds(FlatPtr* stack_base, size_t* stack_size);
|
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$sendfd(int sockfd, int fd);
|
||||||
int sys$recvfd(int sockfd);
|
int sys$recvfd(int sockfd);
|
||||||
long sys$sysconf(int name);
|
long sys$sysconf(int name);
|
||||||
|
@ -559,8 +559,8 @@ public:
|
||||||
m_wait_for_tracer_at_next_execve = val;
|
m_wait_for_tracer_at_next_execve = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
KResultOr<u32> peek_user_data(u32* address);
|
KResultOr<u32> peek_user_data(Userspace<const u32*> address);
|
||||||
KResult poke_user_data(u32* address, u32 data);
|
KResult poke_user_data(Userspace<u32*> address, u32 data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
|
|
|
@ -98,7 +98,7 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
|
||||||
if (!tracer->has_regs())
|
if (!tracer->has_regs())
|
||||||
return KResult(-EINVAL);
|
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))
|
if (!caller.validate_write_typed(regs))
|
||||||
return KResult(-EFAULT);
|
return KResult(-EFAULT);
|
||||||
copy_to_user(regs, &tracer->regs());
|
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);
|
return KResult(-EINVAL);
|
||||||
|
|
||||||
PtraceRegisters regs;
|
PtraceRegisters regs;
|
||||||
if (!caller.validate_read_and_copy_typed(®s, (const PtraceRegisters*)params.addr))
|
if (!caller.validate_read_and_copy_typed(®s, (const PtraceRegisters*)params.addr.unsafe_userspace_ptr()))
|
||||||
return KResult(-EFAULT);
|
return KResult(-EFAULT);
|
||||||
|
|
||||||
auto& peer_saved_registers = peer->get_register_dump_from_stack();
|
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: {
|
case PT_PEEK: {
|
||||||
Kernel::Syscall::SC_ptrace_peek_params peek_params;
|
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;
|
return -EFAULT;
|
||||||
|
|
||||||
// read validation is done inside 'peek_user_data'
|
// read validation is done inside 'peek_user_data'
|
||||||
auto result = peer->process().peek_user_data(peek_params.address);
|
auto result = peer->process().peek_user_data(peek_params.address);
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
|
@ -138,7 +139,7 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
|
||||||
}
|
}
|
||||||
|
|
||||||
case PT_POKE: {
|
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'
|
// write validation is done inside 'poke_user_data'
|
||||||
return peer->process().poke_user_data(addr, params.data);
|
return peer->process().poke_user_data(addr, params.data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
namespace Kernel {
|
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);
|
REQUIRE_PROMISE(proc);
|
||||||
Syscall::SC_ptrace_params params;
|
Syscall::SC_ptrace_params params;
|
||||||
|
@ -58,10 +58,10 @@ bool Process::has_tracee_thread(int tracer_pid) const
|
||||||
return has_tracee;
|
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))) {
|
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);
|
return KResult(-EFAULT);
|
||||||
}
|
}
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
|
@ -74,12 +74,12 @@ KResultOr<u32> Process::peek_user_data(u32* address)
|
||||||
return result;
|
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.
|
// 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.
|
// 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))) {
|
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);
|
return KResult(-EFAULT);
|
||||||
}
|
}
|
||||||
ProcessPagingScope scope(*this);
|
ProcessPagingScope scope(*this);
|
||||||
|
@ -88,7 +88,7 @@ KResult Process::poke_user_data(u32* address, u32 data)
|
||||||
ASSERT(region != nullptr);
|
ASSERT(region != nullptr);
|
||||||
if (region->is_shared()) {
|
if (region->is_shared()) {
|
||||||
// If the region is shared, we change its vmobject to a PrivateInodeVMObject
|
// 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());
|
ASSERT(region->vmobject().is_shared_inode());
|
||||||
region->set_vmobject(PrivateInodeVMObject::create_with_inode(static_cast<SharedInodeVMObject&>(region->vmobject()).inode()));
|
region->set_vmobject(PrivateInodeVMObject::create_with_inode(static_cast<SharedInodeVMObject&>(region->vmobject()).inode()));
|
||||||
region->set_shared(false);
|
region->set_shared(false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue