mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +00:00
Kernel: Implement new ptrace function PT_PEEKBUF
This enables the tracer to copy large amounts of data in a much saner way.
This commit is contained in:
parent
3e223185b3
commit
0f8483f09c
4 changed files with 35 additions and 0 deletions
|
@ -21,8 +21,11 @@ extern "C" {
|
||||||
#define PT_PEEK 7
|
#define PT_PEEK 7
|
||||||
#define PT_POKE 8
|
#define PT_POKE 8
|
||||||
#define PT_SETREGS 9
|
#define PT_SETREGS 9
|
||||||
|
|
||||||
|
// Serenity extensions:
|
||||||
#define PT_POKEDEBUG 10
|
#define PT_POKEDEBUG 10
|
||||||
#define PT_PEEKDEBUG 11
|
#define PT_PEEKDEBUG 11
|
||||||
|
#define PT_PEEKBUF 12
|
||||||
|
|
||||||
#define PT_READ_I PT_PEEK
|
#define PT_READ_I PT_PEEK
|
||||||
#define PT_READ_D PT_PEEK
|
#define PT_READ_D PT_PEEK
|
||||||
|
|
|
@ -458,6 +458,10 @@ struct SC_stat_params {
|
||||||
int follow_symlinks;
|
int follow_symlinks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SC_ptrace_buf_params {
|
||||||
|
MutableBufferArgument<u8, size_t> buf;
|
||||||
|
};
|
||||||
|
|
||||||
struct SC_ptrace_params {
|
struct SC_ptrace_params {
|
||||||
int request;
|
int request;
|
||||||
pid_t tid;
|
pid_t tid;
|
||||||
|
|
|
@ -481,6 +481,7 @@ public:
|
||||||
m_wait_for_tracer_at_next_execve = val;
|
m_wait_for_tracer_at_next_execve = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> peek_user_data(Span<u8> destination, Userspace<const u8*> address);
|
||||||
ErrorOr<FlatPtr> peek_user_data(Userspace<const FlatPtr*> address);
|
ErrorOr<FlatPtr> peek_user_data(Userspace<const FlatPtr*> address);
|
||||||
ErrorOr<void> poke_user_data(Userspace<FlatPtr*> address, FlatPtr data);
|
ErrorOr<void> poke_user_data(Userspace<FlatPtr*> address, FlatPtr data);
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,24 @@ static ErrorOr<FlatPtr> handle_ptrace(const Kernel::Syscall::SC_ptrace_params& p
|
||||||
TRY(peer->process().poke_user_data(Userspace<FlatPtr*> { (FlatPtr)params.addr }, params.data));
|
TRY(peer->process().poke_user_data(Userspace<FlatPtr*> { (FlatPtr)params.addr }, params.data));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case PT_PEEKBUF: {
|
||||||
|
Kernel::Syscall::SC_ptrace_buf_params buf_params {};
|
||||||
|
TRY(copy_from_user(&buf_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_buf_params*>(params.data)));
|
||||||
|
// This is a comparatively large allocation on the Kernel stack.
|
||||||
|
// However, we know that we're close to the root of the call stack, and the following calls shouldn't go too deep.
|
||||||
|
Array<u8, PAGE_SIZE> buf;
|
||||||
|
FlatPtr tracee_ptr = (FlatPtr)params.addr;
|
||||||
|
while (buf_params.buf.size > 0) {
|
||||||
|
size_t copy_this_iteration = min(buf.size(), buf_params.buf.size);
|
||||||
|
TRY(peer->process().peek_user_data(buf.span().slice(0, copy_this_iteration), Userspace<const u8*> { tracee_ptr }));
|
||||||
|
TRY(copy_to_user((void*)buf_params.buf.data, buf.data(), copy_this_iteration));
|
||||||
|
tracee_ptr += copy_this_iteration;
|
||||||
|
buf_params.buf.data += copy_this_iteration;
|
||||||
|
buf_params.buf.size -= copy_this_iteration;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PT_PEEKDEBUG: {
|
case PT_PEEKDEBUG: {
|
||||||
auto data = TRY(peer->peek_debug_register(reinterpret_cast<uintptr_t>(params.addr)));
|
auto data = TRY(peer->peek_debug_register(reinterpret_cast<uintptr_t>(params.addr)));
|
||||||
TRY(copy_to_user((FlatPtr*)params.data, &data));
|
TRY(copy_to_user((FlatPtr*)params.data, &data));
|
||||||
|
@ -168,6 +186,15 @@ ErrorOr<FlatPtr> Process::peek_user_data(Userspace<const FlatPtr*> address)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> Process::peek_user_data(Span<u8> destination, Userspace<const u8*> address)
|
||||||
|
{
|
||||||
|
// This function can be called from the context of another
|
||||||
|
// process that called PT_PEEKBUF
|
||||||
|
ScopedAddressSpaceSwitcher switcher(*this);
|
||||||
|
TRY(copy_from_user(destination.data(), address, destination.size()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<void> Process::poke_user_data(Userspace<FlatPtr*> address, FlatPtr data)
|
ErrorOr<void> Process::poke_user_data(Userspace<FlatPtr*> address, FlatPtr data)
|
||||||
{
|
{
|
||||||
Memory::VirtualRange range = { address.vaddr(), sizeof(FlatPtr) };
|
Memory::VirtualRange range = { address.vaddr(), sizeof(FlatPtr) };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue