diff options
Diffstat (limited to 'test/sys/test_ptrace.rs')
-rw-r--r-- | test/sys/test_ptrace.rs | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs index 0614c13f..16b24110 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)); } @@ -47,3 +46,47 @@ fn test_ptrace_setsiginfo() { _ => (), } } + + +#[test] +fn test_ptrace_cont() { + use nix::sys::ptrace; + use nix::sys::signal::{raise, Signal}; + use nix::sys::wait::{waitpid, WaitStatus}; + use nix::unistd::fork; + use nix::unistd::ForkResult::*; + + // FIXME: qemu-user doesn't implement ptrace on all architectures + // and retunrs ENOSYS in this case. + // We (ab)use this behavior to detect the affected platforms + // and skip the test then. + // On valid platforms the ptrace call should return Errno::EPERM, this + // is already tested by `test_ptrace`. + let err = ptrace::attach(getpid()).unwrap_err(); + if err == Error::Sys(Errno::ENOSYS) { + return; + } + + match fork() { + Ok(Child) => { + ptrace::traceme().unwrap(); + // As recommended by ptrace(2), raise SIGTRAP to pause the child + // until the parent is ready to continue + loop { + raise(Signal::SIGTRAP).unwrap(); + } + + }, + Ok(Parent { child }) => { + assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP))); + ptrace::cont(child, None).unwrap(); + assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP))); + ptrace::cont(child, Signal::SIGKILL).unwrap(); + match waitpid(child, None) { + Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {} + _ => panic!("The process should have been killed"), + } + }, + Err(_) => panic!("Error: Fork Failed") + } +} |