diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-10-21 17:23:58 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-10-21 17:23:58 +0000 |
commit | 9ed9a1dccb98e6a2f91269c09e49641c4ff395b8 (patch) | |
tree | 588c18b2f92397d9593ef1726ad7b6b2514952a4 /test | |
parent | eef3a432d57e8f830e05fede6e3099dcb689aa6b (diff) | |
parent | f1573a7efa8368507d581adeb3bff9bbf5aa0ead (diff) | |
download | nix-9ed9a1dccb98e6a2f91269c09e49641c4ff395b8.zip |
Merge #949
949: ptrace support for BSDs r=Susurrus a=xd009642
This PR adds support to the ptrace API for BSDs to close #947. It also adds a read and write method for reading and writing to a traced processes memory. The ptrace API created for linux offers this via a deprecated function so I added this so they can be feature equivalent without replicating a deprecated part of the API.
Due to the differences in ptrace on BSD and linux I've made a ptrace module to keep things readable.
Still to do - revert travis config to remove my feature branch and update the changelog.
Co-authored-by: xd009642 <danielmckenna93@gmail.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/sys/mod.rs | 7 | ||||
-rw-r--r-- | test/sys/test_ptrace.rs | 28 |
2 files changed, 29 insertions, 6 deletions
diff --git a/test/sys/mod.rs b/test/sys/mod.rs index bdc079d8..46f29123 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -27,5 +27,10 @@ mod test_uio; mod test_epoll; mod test_pthread; #[cfg(any(target_os = "android", - target_os = "linux"))] + target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd"))] mod test_ptrace; diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs index a15a7921..24d9b522 100644 --- a/test/sys/test_ptrace.rs +++ b/test/sys/test_ptrace.rs @@ -1,7 +1,9 @@ use nix::Error; use nix::errno::Errno; use nix::unistd::getpid; -use nix::sys::ptrace::{self, Options}; +use nix::sys::ptrace; +#[cfg(any(target_os = "android", target_os = "linux"))] +use nix::sys::ptrace::Options; #[cfg(any(target_os = "android", target_os = "linux"))] use std::mem; @@ -11,11 +13,13 @@ fn test_ptrace() { // 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::attach(getpid()).unwrap_err(); - assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS)); + assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) || + err == Error::Sys(Errno::ENOSYS)); } // Just make sure ptrace_setoptions can be called at all, for now. #[test] +#[cfg(any(target_os = "android", target_os = "linux"))] fn test_ptrace_setoptions() { let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err(); assert!(err != Error::UnsupportedOperation); @@ -23,6 +27,7 @@ fn test_ptrace_setoptions() { // Just make sure ptrace_getevent can be called at all, for now. #[test] +#[cfg(any(target_os = "android", target_os = "linux"))] fn test_ptrace_getevent() { let err = ptrace::getevent(getpid()).unwrap_err(); assert!(err != Error::UnsupportedOperation); @@ -30,6 +35,7 @@ fn test_ptrace_getevent() { // Just make sure ptrace_getsiginfo can be called at all, for now. #[test] +#[cfg(any(target_os = "android", target_os = "linux"))] fn test_ptrace_getsiginfo() { if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) { panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!"); @@ -38,6 +44,7 @@ fn test_ptrace_getsiginfo() { // Just make sure ptrace_setsiginfo can be called at all, for now. #[test] +#[cfg(any(target_os = "android", target_os = "linux"))] fn test_ptrace_setsiginfo() { let siginfo = unsafe { mem::uninitialized() }; if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) { @@ -50,10 +57,12 @@ fn test_ptrace_setsiginfo() { fn test_ptrace_cont() { use nix::sys::ptrace; use nix::sys::signal::{raise, Signal}; - use nix::sys::wait::{waitpid, WaitStatus}; + use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; use nix::unistd::fork; use nix::unistd::ForkResult::*; + let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test"); + // 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 @@ -79,9 +88,18 @@ fn test_ptrace_cont() { 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(); + ptrace::cont(child, Some(Signal::SIGKILL)).unwrap(); match waitpid(child, None) { - Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {} + Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => { + // FIXME It's been observed on some systems (apple) the + // tracee may not be killed but remain as a zombie process + // affecting other wait based tests. Add an extra kill just + // to make sure there are no zombies. + let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); + while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() { + let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); + } + } _ => panic!("The process should have been killed"), } }, |