mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 05:38:11 +00:00
Kernel: Add 'ptrace' syscall
This commit adds a basic implementation of the ptrace syscall, which allows one process (the tracer) to control another process (the tracee). While a process is being traced, it is stopped whenever a signal is received (other than SIGCONT). The tracer can start tracing another thread with PT_ATTACH, which causes the tracee to stop. From there, the tracer can use PT_CONTINUE to continue the execution of the tracee, or use other request codes (which haven't been implemented yet) to modify the state of the tracee. Additional request codes are PT_SYSCALL, which causes the tracee to continue exection but stop at the next entry or exit from a syscall, and PT_GETREGS which fethces the last saved register set of the tracee (can be used to inspect syscall arguments and return value). A special request code is PT_TRACE_ME, which is issued by the tracee and causes it to stop when it calls execve and wait for the tracer to attach.
This commit is contained in:
parent
c9396be83f
commit
6b74d38aab
13 changed files with 300 additions and 102 deletions
|
@ -26,9 +26,9 @@
|
|||
|
||||
#include <Kernel/Arch/i386/CPU.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/ProcessTracer.h>
|
||||
#include <Kernel/Random.h>
|
||||
#include <Kernel/Syscall.h>
|
||||
#include <Kernel/ThreadTracer.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
@ -92,8 +92,6 @@ int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
|
|||
if (function == SC_exit || function == SC_exit_thread) {
|
||||
// These syscalls need special handling since they never return to the caller.
|
||||
cli();
|
||||
if (auto* tracer = process.tracer())
|
||||
tracer->did_syscall(function, arg1, arg2, arg3, 0);
|
||||
if (function == SC_exit)
|
||||
process.sys$exit((int)arg1);
|
||||
else
|
||||
|
@ -132,6 +130,11 @@ void syscall_handler(RegisterState& regs)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Thread::current->tracer() && Thread::current->tracer()->is_tracing_syscalls()) {
|
||||
Thread::current->tracer()->set_trace_syscalls(false);
|
||||
Thread::current->tracer_trap(regs);
|
||||
}
|
||||
|
||||
// Make sure SMAP protection is enabled on syscall entry.
|
||||
clac();
|
||||
|
||||
|
@ -168,8 +171,12 @@ void syscall_handler(RegisterState& regs)
|
|||
u32 arg2 = regs.ecx;
|
||||
u32 arg3 = regs.ebx;
|
||||
regs.eax = (u32)Syscall::handle(regs, function, arg1, arg2, arg3);
|
||||
if (auto* tracer = process.tracer())
|
||||
tracer->did_syscall(function, arg1, arg2, arg3, regs.eax);
|
||||
|
||||
if (Thread::current->tracer() && Thread::current->tracer()->is_tracing_syscalls()) {
|
||||
Thread::current->tracer()->set_trace_syscalls(false);
|
||||
Thread::current->tracer_trap(regs);
|
||||
}
|
||||
|
||||
process.big_lock().unlock();
|
||||
|
||||
// Check if we're supposed to return to userspace or just die.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue