Skip to content

Commit 43a2943

Browse files
committed
Added ptrace utilities.
Some ptrace functions return structures through the data argument. This commit adds utilities to return data through this mechanism and function specialisations for a few of these functions (getting event messages or the siginfo_t struct). Once the next version of libc is released these utilities will be expanded to include the fpregs and user_regs structs. Ptrace requests that are now satisfied by a more specific public function will return an unsupported operation error. This has involved adding an UnsupportedOperation to the nix::Error enum and removed the mapping from Error to Errno and from Error to std::io::Error.
1 parent 6783ffc commit 43a2943

File tree

3 files changed

+56
-20
lines changed

3 files changed

+56
-20
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1818
([#556](https://github.com/nix-rust/nix/pull/556)
1919
- Added `nix::ptr::openpty`
2020
([#456](https://github.com/nix-rust/nix/pull/456))
21+
- Added `nix::ptrace::{ptrace_get_data, ptrace_getsiginfo, ptrace_setsiginfo
22+
and nix::Error::UnsupportedOperation}`
23+
([#614](https://github.com/nix-rust/nix/pull/614))
2124

2225
### Changed
2326
- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe.
@@ -29,6 +32,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2932
- Changed type signature of `sys::select::FdSet::contains` to make `self`
3033
immutable ([#564](https://github.com/nix-rust/nix/pull/564))
3134

35+
### Removed
36+
- Removed io::Error from nix::Error and conversion from nix::Error to Errno
37+
([#614](https://github.com/nix-rust/nix/pull/614))
38+
3239
### Fixed
3340
- Fixed multiple issues compiling under different archetectures and OSes.
3441
Now compiles on Linux/MIPS ([#538](https://github.com/nix-rust/nix/pull/538)),

src/lib.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ use std::{ptr, result};
7575
use std::ffi::{CStr, OsStr};
7676
use std::path::{Path, PathBuf};
7777
use std::os::unix::ffi::OsStrExt;
78-
use std::io;
7978
use std::fmt;
8079
use std::error;
8180
use libc::PATH_MAX;
@@ -97,6 +96,9 @@ pub enum Error {
9796
/// The operation involved a conversion to Rust's native String type, which failed because the
9897
/// string did not contain all valid UTF-8.
9998
InvalidUtf8,
99+
/// The operation is not supported by Nix, in this instance either use the libc bindings or
100+
/// consult the module documentation to see if there is a more appropriate interface available.
101+
UnsupportedOperation,
100102
}
101103

102104
impl Error {
@@ -116,14 +118,6 @@ impl Error {
116118
Error::Sys(errno::EINVAL)
117119
}
118120

119-
/// Get the errno associated with this error
120-
pub fn errno(&self) -> errno::Errno {
121-
match *self {
122-
Error::InvalidPath => errno::Errno::EINVAL,
123-
Error::InvalidUtf8 => errno::Errno::UnknownErrno,
124-
Error::Sys(errno) => errno,
125-
}
126-
}
127121
}
128122

129123
impl From<errno::Errno> for Error {
@@ -139,6 +133,7 @@ impl error::Error for Error {
139133
match self {
140134
&Error::InvalidPath => "Invalid path",
141135
&Error::InvalidUtf8 => "Invalid UTF-8 string",
136+
&Error::UnsupportedOperation => "Unsupported Operation",
142137
&Error::Sys(ref errno) => errno.desc(),
143138
}
144139
}
@@ -149,21 +144,12 @@ impl fmt::Display for Error {
149144
match self {
150145
&Error::InvalidPath => write!(f, "Invalid path"),
151146
&Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
147+
&Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
152148
&Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
153149
}
154150
}
155151
}
156152

157-
impl From<Error> for io::Error {
158-
fn from(err: Error) -> Self {
159-
match err {
160-
Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
161-
Error::InvalidUtf8 => io::Error::new(io::ErrorKind::Other, err),
162-
Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
163-
}
164-
}
165-
}
166-
167153
pub trait NixPath {
168154
fn len(&self) -> usize;
169155

src/sys/ptrace.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use std::{mem, ptr};
12
use {Errno, Error, Result};
2-
use libc::{pid_t, c_void, c_long};
3+
use libc::{pid_t, c_void, c_long, siginfo_t};
34

45
#[cfg(all(target_os = "linux",
56
any(target_arch = "x86",
@@ -71,11 +72,14 @@ mod ffi {
7172
}
7273
}
7374

75+
/// Performs a ptrace request. If the request in question is provided by a specialised function
76+
/// this function will return an unsupported operation error.
7477
pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
7578
use self::ptrace::*;
7679

7780
match request {
7881
PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data),
82+
PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err(Error::UnsupportedOperation),
7983
_ => ptrace_other(request, pid, addr, data)
8084
}
8185
}
@@ -91,6 +95,20 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da
9195
}
9296
}
9397

98+
/// Function for ptrace requests that return values from the data field.
99+
/// Some ptrace get requests populate structs or larger elements than c_long
100+
/// and therefore use the data field to return values. This function handles these
101+
/// requests.
102+
fn ptrace_get_data<T>(request: ptrace::PtraceRequest, pid: pid_t) -> Result<T> {
103+
// Creates an uninitialized pointer to store result in
104+
let data: Box<T> = Box::new(unsafe { mem::uninitialized() });
105+
let data: *mut c_void = unsafe { mem::transmute(data) };
106+
ptrace(request, pid, ptr::null_mut(), data)?;
107+
// Convert back into the original data format and return unboxed value
108+
let data: Box<T> = unsafe { mem::transmute(data) };
109+
Ok(*data)
110+
}
111+
94112
fn ptrace_other(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
95113
Errno::result(unsafe { ffi::ptrace(request, pid, addr, data) }).map(|_| 0)
96114
}
@@ -102,3 +120,28 @@ pub fn ptrace_setoptions(pid: pid_t, options: ptrace::PtraceOptions) -> Result<(
102120

103121
ptrace(PTRACE_SETOPTIONS, pid, ptr::null_mut(), options as *mut c_void).map(drop)
104122
}
123+
124+
/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
125+
pub fn ptrace_getevent(pid: pid_t) -> Result<c_long> {
126+
use self::ptrace::*;
127+
ptrace_get_data::<c_long>(PTRACE_GETEVENTMSG, pid)
128+
}
129+
130+
/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
131+
pub fn ptrace_getsiginfo(pid: pid_t) -> Result<siginfo_t> {
132+
use self::ptrace::*;
133+
ptrace_get_data::<siginfo_t>(PTRACE_GETSIGINFO, pid)
134+
}
135+
136+
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
137+
pub fn ptrace_setsiginfo(pid: pid_t, sig: &siginfo_t) -> Result<()> {
138+
use self::ptrace::*;
139+
let ret = unsafe{
140+
Errno::clear();
141+
ffi::ptrace(PTRACE_SETSIGINFO, pid, ptr::null_mut(), sig as *const _ as *const c_void)
142+
};
143+
match Errno::result(ret) {
144+
Ok(_) => Ok(()),
145+
Err(e) => Err(e),
146+
}
147+
}

0 commit comments

Comments
 (0)