Skip to content

Commit

Permalink
Merge #686
Browse files Browse the repository at this point in the history
686: Fix special ptraces r=Susurrus

In #614 we added specializations of `ptrace()` that added more type safety. As part of this, the `UnsupportedOperation` error was introduced for the requests that are covered by specialized versions so they couldn't be used with the general `ptrace()`. Unfortunately, no tests were added with this PR and so it slipped through that you could not do those operations at all anymore: `ptrace()` reported `UnsupportedOperation` for them and `ptrace_*` called `ptrace`, not `ffi::ptrace` and so also reported `UnsupportedOperation`! Whoops!

This minimally-invasive surgery corrects this by adding tests that call all the specialized `ptrace_*` ignoring the return value save checking for `UnsupportedOperation`. It also changes the functions calls to use `ffi::ptrace()` directly to fix the bug.

As this was never a bug in a released version of `nix`, there's no need for a changelog entry here.
  • Loading branch information
bors[bot] committed Jul 19, 2017
2 parents f8406b8 + bba9e43 commit aa85ec9
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 10 deletions.
17 changes: 8 additions & 9 deletions src/sys/ptrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,16 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data
}
}

/// Function for ptrace requests that return values from the data field.
/// Function for ptrace requests that return values from the data field.
/// Some ptrace get requests populate structs or larger elements than c_long
/// and therefore use the data field to return values. This function handles these
/// requests.
fn ptrace_get_data<T>(request: ptrace::PtraceRequest, pid: Pid) -> Result<T> {
// Creates an uninitialized pointer to store result in
let data: Box<T> = Box::new(unsafe { mem::uninitialized() });
let data: *mut c_void = unsafe { mem::transmute(data) };
ptrace(request, pid, ptr::null_mut(), data)?;
// Convert back into the original data format and return unboxed value
let data: Box<T> = unsafe { mem::transmute(data) };
Ok(*data)
// Creates an uninitialized pointer to store result in
let data: T = unsafe { mem::uninitialized() };
let res = unsafe { ffi::ptrace(request, pid.into(), ptr::null_mut(), &data as *const _ as *const c_void) };
Errno::result(res)?;
Ok(data)
}

fn ptrace_other(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
Expand All @@ -114,7 +112,8 @@ pub fn ptrace_setoptions(pid: Pid, options: ptrace::PtraceOptions) -> Result<()>
use self::ptrace::*;
use std::ptr;

ptrace(PTRACE_SETOPTIONS, pid, ptr::null_mut(), options as *mut c_void).map(drop)
let res = unsafe { ffi::ptrace(PTRACE_SETOPTIONS, pid.into(), ptr::null_mut(), options as *mut c_void) };
Errno::result(res).map(|_| ())
}

/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
Expand Down
36 changes: 35 additions & 1 deletion test/sys/test_ptrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use nix::errno::*;
use nix::unistd::*;
use nix::sys::ptrace::*;
use nix::sys::ptrace::ptrace::*;
use std::ptr;

use std::{mem, ptr};

#[test]
fn test_ptrace() {
Expand All @@ -12,3 +13,36 @@ fn test_ptrace() {
let err = ptrace(PTRACE_ATTACH, getpid(), ptr::null_mut(), ptr::null_mut()).unwrap_err();
assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS));
}

// Just make sure ptrace_setoptions can be called at all, for now.
#[test]
fn test_ptrace_setoptions() {
let err = ptrace_setoptions(getpid(), PTRACE_O_TRACESYSGOOD).unwrap_err();
assert!(err != Error::UnsupportedOperation);
}

// Just make sure ptrace_getevent can be called at all, for now.
#[test]
fn test_ptrace_getevent() {
let err = ptrace_getevent(getpid()).unwrap_err();
assert!(err != Error::UnsupportedOperation);
}

// Just make sure ptrace_getsiginfo can be called at all, for now.
#[test]
fn test_ptrace_getsiginfo() {
match ptrace_getsiginfo(getpid()) {
Err(Error::UnsupportedOperation) => panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!"),
_ => (),
}
}

// Just make sure ptrace_setsiginfo can be called at all, for now.
#[test]
fn test_ptrace_setsiginfo() {
let siginfo = unsafe { mem::uninitialized() };
match ptrace_setsiginfo(getpid(), &siginfo) {
Err(Error::UnsupportedOperation) => panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!"),
_ => (),
}
}

0 comments on commit aa85ec9

Please sign in to comment.