mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +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
Notes:
sideshowbarker
2024-07-17 23:07:51 +09:00
Author: https://github.com/BenWiederhake Commit: https://github.com/SerenityOS/serenity/commit/0f8483f09ce Pull-request: https://github.com/SerenityOS/serenity/pull/11113 Reviewed-by: https://github.com/BertalanD Reviewed-by: https://github.com/IdanHo Reviewed-by: https://github.com/creator1creeper1
4 changed files with 35 additions and 0 deletions
|
@ -21,8 +21,11 @@ extern "C" {
|
|||
#define PT_PEEK 7
|
||||
#define PT_POKE 8
|
||||
#define PT_SETREGS 9
|
||||
|
||||
// Serenity extensions:
|
||||
#define PT_POKEDEBUG 10
|
||||
#define PT_PEEKDEBUG 11
|
||||
#define PT_PEEKBUF 12
|
||||
|
||||
#define PT_READ_I PT_PEEK
|
||||
#define PT_READ_D PT_PEEK
|
||||
|
|
|
@ -458,6 +458,10 @@ struct SC_stat_params {
|
|||
int follow_symlinks;
|
||||
};
|
||||
|
||||
struct SC_ptrace_buf_params {
|
||||
MutableBufferArgument<u8, size_t> buf;
|
||||
};
|
||||
|
||||
struct SC_ptrace_params {
|
||||
int request;
|
||||
pid_t tid;
|
||||
|
|
|
@ -481,6 +481,7 @@ public:
|
|||
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<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));
|
||||
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: {
|
||||
auto data = TRY(peer->peek_debug_register(reinterpret_cast<uintptr_t>(params.addr)));
|
||||
TRY(copy_to_user((FlatPtr*)params.data, &data));
|
||||
|
@ -168,6 +186,15 @@ ErrorOr<FlatPtr> Process::peek_user_data(Userspace<const FlatPtr*> address)
|
|||
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)
|
||||
{
|
||||
Memory::VirtualRange range = { address.vaddr(), sizeof(FlatPtr) };
|
||||
|
|
Loading…
Reference in a new issue