summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Mielniczuk <marmistrz.dev@zoho.eu>2017-07-26 09:53:11 +0200
committerMarcin Mielniczuk <marmistrz.dev@zoho.eu>2017-07-26 09:53:11 +0200
commitb03011fcc39cb1fce1686f6c4ac180c218d611f3 (patch)
tree79d684e7cb982de60c5f61a34a5bd651f1341920
parente08a430226a3b823278795fe8671c264f9ae6594 (diff)
downloadnix-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.rs50
-rw-r--r--test/sys/test_ptrace.rs5
-rw-r--r--test/sys/test_wait.rs9
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)));
}