Skip to content

Commit aa85ec9

Browse files
committed
Merge #686
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.
2 parents f8406b8 + bba9e43 commit aa85ec9

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

src/sys/ptrace.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,16 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data
9191
}
9292
}
9393

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

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

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

120119
/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`

test/sys/test_ptrace.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use nix::errno::*;
33
use nix::unistd::*;
44
use nix::sys::ptrace::*;
55
use nix::sys::ptrace::ptrace::*;
6-
use std::ptr;
6+
7+
use std::{mem, ptr};
78

89
#[test]
910
fn test_ptrace() {
@@ -12,3 +13,36 @@ fn test_ptrace() {
1213
let err = ptrace(PTRACE_ATTACH, getpid(), ptr::null_mut(), ptr::null_mut()).unwrap_err();
1314
assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS));
1415
}
16+
17+
// Just make sure ptrace_setoptions can be called at all, for now.
18+
#[test]
19+
fn test_ptrace_setoptions() {
20+
let err = ptrace_setoptions(getpid(), PTRACE_O_TRACESYSGOOD).unwrap_err();
21+
assert!(err != Error::UnsupportedOperation);
22+
}
23+
24+
// Just make sure ptrace_getevent can be called at all, for now.
25+
#[test]
26+
fn test_ptrace_getevent() {
27+
let err = ptrace_getevent(getpid()).unwrap_err();
28+
assert!(err != Error::UnsupportedOperation);
29+
}
30+
31+
// Just make sure ptrace_getsiginfo can be called at all, for now.
32+
#[test]
33+
fn test_ptrace_getsiginfo() {
34+
match ptrace_getsiginfo(getpid()) {
35+
Err(Error::UnsupportedOperation) => panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!"),
36+
_ => (),
37+
}
38+
}
39+
40+
// Just make sure ptrace_setsiginfo can be called at all, for now.
41+
#[test]
42+
fn test_ptrace_setsiginfo() {
43+
let siginfo = unsafe { mem::uninitialized() };
44+
match ptrace_setsiginfo(getpid(), &siginfo) {
45+
Err(Error::UnsupportedOperation) => panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!"),
46+
_ => (),
47+
}
48+
}

0 commit comments

Comments
 (0)