From be06661d1a687201615203dcc1d42eb8d7337da9 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Sun, 9 Jun 2019 18:54:48 -0300 Subject: [PATCH] allow signal injection in ptrace::syscall and ptrace::detach --- src/sys/ptrace/bsd.rs | 13 ++++++++++--- src/sys/ptrace/linux.rs | 22 ++++++++++++++++------ test/sys/test_wait.rs | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/sys/ptrace/bsd.rs b/src/sys/ptrace/bsd.rs index 7797d10647..5528115304 100644 --- a/src/sys/ptrace/bsd.rs +++ b/src/sys/ptrace/bsd.rs @@ -84,9 +84,16 @@ pub fn attach(pid: Pid) -> Result<()> { /// Detaches the current running process, as with `ptrace(PT_DETACH, ...)` /// -/// Detaches from the process specified in pid allowing it to run freely -pub fn detach(pid: Pid) -> Result<()> { - unsafe { ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), 0).map(drop) } +/// Detaches from the process specified in pid allowing it to run freely, optionally delivering a +/// signal specified by `sig`. +pub fn detach>>(pid: Pid, sig: T) -> Result<()> { + let data = match sig.into() { + Some(s) => s as c_int, + None => 0, + }; + unsafe { + ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), data).map(drop) + } } /// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)` diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs index df15e66527..20b203cd60 100644 --- a/src/sys/ptrace/linux.rs +++ b/src/sys/ptrace/linux.rs @@ -290,14 +290,19 @@ pub fn traceme() -> Result<()> { /// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)` /// -/// Arranges for the tracee to be stopped at the next entry to or exit from a system call. -pub fn syscall(pid: Pid) -> Result<()> { +/// Arranges for the tracee to be stopped at the next entry to or exit from a system call, +/// optionally delivering a signal specified by `sig`. +pub fn syscall>>(pid: Pid, sig: T) -> Result<()> { + let data = match sig.into() { + Some(s) => s as i32 as *mut c_void, + None => ptr::null_mut(), + }; unsafe { ptrace_other( Request::PTRACE_SYSCALL, pid, ptr::null_mut(), - ptr::null_mut(), + data, ).map(drop) // ignore the useless return value } } @@ -318,14 +323,19 @@ pub fn attach(pid: Pid) -> Result<()> { /// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)` /// -/// Detaches from the process specified in pid allowing it to run freely -pub fn detach(pid: Pid) -> Result<()> { +/// Detaches from the process specified in pid allowing it to run freely, optionally delivering a +/// signal specified by `sig`. +pub fn detach>>(pid: Pid, sig: T) -> Result<()> { + let data = match sig.into() { + Some(s) => s as i32 as *mut c_void, + None => ptr::null_mut(), + }; unsafe { ptrace_other( Request::PTRACE_DETACH, pid, ptr::null_mut(), - ptr::null_mut() + data ).map(drop) } } diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs index d07d82f0d9..c17598f2c0 100644 --- a/test/sys/test_wait.rs +++ b/test/sys/test_wait.rs @@ -82,7 +82,7 @@ mod ptrace { assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok()); // First, stop on the next system call, which will be exit() - assert!(ptrace::syscall(child).is_ok()); + assert!(ptrace::syscall(child, None).is_ok()); assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); // Then get the ptrace event for the process exiting assert!(ptrace::cont(child, None).is_ok());