diff options
author | Marcin Mielniczuk <marmistrz.dev@zoho.eu> | 2017-07-26 09:53:11 +0200 |
---|---|---|
committer | Marcin Mielniczuk <marmistrz.dev@zoho.eu> | 2017-07-26 09:53:11 +0200 |
commit | b03011fcc39cb1fce1686f6c4ac180c218d611f3 (patch) | |
tree | 79d684e7cb982de60c5f61a34a5bd651f1341920 | |
parent | e08a430226a3b823278795fe8671c264f9ae6594 (diff) | |
download | nix-b03011fcc39cb1fce1686f6c4ac180c218d611f3.zip |
Mark nix::sys::ptrace::ptrace as unsafe, add safe variants of source routines.
These include:
* PTRACE_TRACEME
* PTRACE_CONT
* PTRACE_ATTACH
* PTRACE_SYSCALL
-rw-r--r-- | src/sys/ptrace.rs | 50 | ||||
-rw-r--r-- | test/sys/test_ptrace.rs | 5 | ||||
-rw-r--r-- | test/sys/test_wait.rs | 9 |
3 files changed, 55 insertions, 9 deletions
diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index 877bfcb0..d83c6e09 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -70,7 +70,7 @@ mod ffi { /// Performs a ptrace request. If the request in question is provided by a specialised function /// this function will return an unsupported operation error. -pub fn ptrace(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { +pub unsafe fn ptrace(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { use self::ptrace::*; match request { @@ -140,3 +140,51 @@ pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> { Err(e) => Err(e), } } + +/// Sets the process as traceable with `PTRACE_TRACEME` +pub fn traceme() -> Result<()> { + unsafe { + ptrace( + ptrace::PTRACE_TRACEME, + Pid::from_raw(0), + ptr::null_mut(), + ptr::null_mut(), + ).map(|_| ()) // ignore the useless return value + } +} + +/// Makes the `PTRACE_SYSCALL` request to ptrace +pub fn syscall(pid: Pid) -> Result<()> { + unsafe { + ptrace( + ptrace::PTRACE_SYSCALL, + pid, + ptr::null_mut(), + ptr::null_mut(), + ).map(|_| ()) // ignore the useless return value + } +} + +/// Makes the `PTRACE_ATTACH` request to ptrace +pub fn attach(pid: Pid) -> Result<()> { + unsafe { + ptrace( + ptrace::PTRACE_ATTACH, + pid, + ptr::null_mut(), + ptr::null_mut(), + ).map(|_| ()) // ignore the useless return value + } +} + +/// Makes the `PTRACE_CONT` request to ptrace +pub fn cont(pid: Pid) -> Result<()> { + unsafe { + ptrace( + ptrace::PTRACE_CONT, + pid, + ptr::null_mut(), + ptr::null_mut(), + ).map(|_| ()) // ignore the useless return value + } +} diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs index 0614c13f..16a60ba7 100644 --- a/test/sys/test_ptrace.rs +++ b/test/sys/test_ptrace.rs @@ -3,14 +3,13 @@ use nix::errno::Errno; use nix::unistd::getpid; use nix::sys::ptrace; -use std::{mem, ptr}; +use std::mem; #[test] fn test_ptrace() { - use nix::sys::ptrace::ptrace::PTRACE_ATTACH; // Just make sure ptrace can be called at all, for now. // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS - let err = ptrace::ptrace(PTRACE_ATTACH, getpid(), ptr::null_mut(), ptr::null_mut()).unwrap_err(); + let err = ptrace::attach(getpid()).unwrap_err(); assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS)); } diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs index 8d2ca85f..4a7379c1 100644 --- a/test/sys/test_wait.rs +++ b/test/sys/test_wait.rs @@ -47,11 +47,10 @@ mod ptrace { use nix::sys::wait::*; use nix::unistd::*; use nix::unistd::ForkResult::*; - use std::{ptr, process}; use libc::_exit; fn ptrace_child() -> ! { - ptrace::ptrace(PTRACE_TRACEME, Pid::from_raw(0), ptr::null_mut(), ptr::null_mut()).unwrap(); + ptrace::traceme().unwrap(); // As recommended by ptrace(2), raise SIGTRAP to pause the child // until the parent is ready to continue let _ = raise(SIGTRAP); @@ -65,13 +64,13 @@ mod ptrace { assert!(ptrace::setoptions(child, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXIT).is_ok()); // First, stop on the next system call, which will be exit() - assert!(ptrace::ptrace(PTRACE_SYSCALL, child, ptr::null_mut(), ptr::null_mut()).is_ok()); + assert!(ptrace::syscall(child).is_ok()); assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); // Then get the ptrace event for the process exiting - assert!(ptrace::ptrace(PTRACE_CONT, child, ptr::null_mut(), ptr::null_mut()).is_ok()); + assert!(ptrace::cont(child).is_ok()); assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, PTRACE_EVENT_EXIT))); // Finally get the normal wait() result, now that the process has exited - assert!(ptrace::ptrace(PTRACE_CONT, child, ptr::null_mut(), ptr::null_mut()).is_ok()); + assert!(ptrace::cont(child).is_ok()); assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0))); } |