mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:27:35 +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
|
@ -272,7 +272,6 @@ public:
|
|||
int sys$set_thread_name(int tid, const char* buffer, size_t buffer_size);
|
||||
int sys$get_thread_name(int tid, char* buffer, size_t buffer_size);
|
||||
int sys$rename(const Syscall::SC_rename_params*);
|
||||
int sys$systrace(pid_t);
|
||||
int sys$mknod(const Syscall::SC_mknod_params*);
|
||||
int sys$shbuf_create(int, void** buffer);
|
||||
int sys$shbuf_allow_pid(int, pid_t peer_pid);
|
||||
|
@ -300,6 +299,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*);
|
||||
|
||||
template<bool sockname, typename Params>
|
||||
int get_sock_or_peer_name(const Params&);
|
||||
|
@ -316,9 +316,6 @@ public:
|
|||
const NonnullOwnPtrVector<Region>& regions() const { return m_regions; }
|
||||
void dump_regions();
|
||||
|
||||
ProcessTracer* tracer() { return m_tracer.ptr(); }
|
||||
ProcessTracer& ensure_tracer();
|
||||
|
||||
u32 m_ticks_in_user { 0 };
|
||||
u32 m_ticks_in_kernel { 0 };
|
||||
|
||||
|
@ -442,6 +439,8 @@ private:
|
|||
KResultOr<String> get_syscall_path_argument(const char* user_path, size_t path_length) const;
|
||||
KResultOr<String> get_syscall_path_argument(const Syscall::StringArgument&) const;
|
||||
|
||||
bool has_tracee_thread(int tracer_pid) const;
|
||||
|
||||
RefPtr<PageDirectory> m_page_directory;
|
||||
|
||||
Process* m_prev { nullptr };
|
||||
|
@ -500,8 +499,6 @@ private:
|
|||
|
||||
FixedArray<gid_t> m_extra_gids;
|
||||
|
||||
RefPtr<ProcessTracer> m_tracer;
|
||||
|
||||
WeakPtr<Region> m_master_tls_region;
|
||||
size_t m_master_tls_size { 0 };
|
||||
size_t m_master_tls_alignment { 0 };
|
||||
|
@ -526,6 +523,11 @@ private:
|
|||
OwnPtr<PerformanceEventBuffer> m_perf_event_buffer;
|
||||
|
||||
u32 m_inspector_count { 0 };
|
||||
|
||||
// This member is used in the implementation of ptrace's PT_TRACEME flag.
|
||||
// If it is set to true, the process will stop at the next execve syscall
|
||||
// and wait for a tracer to attach.
|
||||
bool m_wait_for_tracer_at_next_execve { false };
|
||||
};
|
||||
|
||||
class ProcessInspectionHandle {
|
||||
|
@ -585,7 +587,7 @@ inline void Process::for_each_child(Callback callback)
|
|||
pid_t my_pid = pid();
|
||||
for (auto* process = g_processes->head(); process;) {
|
||||
auto* next_process = process->next();
|
||||
if (process->ppid() == my_pid) {
|
||||
if (process->ppid() == my_pid || process->has_tracee_thread(m_pid)) {
|
||||
if (callback(*process) == IterationDecision::Break)
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue