From 00364df70700c073b5c57d4cbd334ffe2fb1d358 Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Mon, 10 Jul 2017 09:21:02 +0200 Subject: [PATCH 1/3] Implement enum Register and three high level wrappers --- src/sys/ptrace.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index 17dfee3493..f4187aa125 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -3,6 +3,8 @@ use {Errno, Error, Result}; use libc::{c_void, c_long, siginfo_t}; use ::unistd::Pid; +//------------------ First part: a low-level wrapper for ptrace -----------------// + #[cfg(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64", @@ -146,3 +148,60 @@ pub fn ptrace_setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> { Err(e) => Err(e), } } + +//-------------------------- Second part: a low-level wrapper for ptrace ----------------------// + +#[cfg(target_arch = "x86_64")] +// We're going to export it anyway +#[allow(dead_code)] +#[allow(non_camel_case_types)] +pub enum Register { + R15 = 0 * 8, + R14 = 1 * 8, + R13 = 2 * 8, + R12 = 3 * 8, + RBP = 4 * 8, + RBX = 5 * 8, + R11 = 6 * 8, + R10 = 7 * 8, + R9 = 8 * 8, + R8 = 9 * 8, + RAX = 10 * 8, + RCX = 11 * 8, + RDX = 12 * 8, + RSI = 13 * 8, + RDI = 14 * 8, + ORIG_RAX = 15 * 8, + RIP = 16 * 8, + CS = 17 * 8, + EFLAGS = 18 * 8, + RSP = 19 * 8, + SS = 20 * 8, + FS_BASE = 21 * 8, + GS_BASE = 22 * 8, + DS = 23 * 8, + ES = 24 * 8, + FS = 25 * 8, + GS = 26 * 8, +} + +/// Makes the `PTRACE_SYSCALL` request to ptrace +pub fn syscall(pid: Pid) -> Result<()> { + ptrace(ptrace::PTRACE_SYSCALL, pid, ptr::null_mut(), ptr::null_mut()).map(|_| ()) // ignore the useless return value +} + +/// Makes the `PTRACE_PEEKUSER` request to ptrace +pub fn peekuser(pid: Pid, reg: Register) -> Result { + let reg_arg = (reg as i32) as *mut c_void; + ptrace(ptrace::PTRACE_PEEKUSER, pid, reg_arg, ptr::null_mut()) +} + +/// Sets the process as traceable with `PTRACE_TRACEME` +pub fn traceme() -> Result<()> { + ptrace( + ptrace::PTRACE_TRACEME, + Pid::from_raw(0), + ptr::null_mut(), + ptr::null_mut(), + ).map(|_| ()) // ignore the useless return value +} From a603a5de268d4c38fc6f4a18ed8ab26e34acd3d9 Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Mon, 10 Jul 2017 10:41:11 +0200 Subject: [PATCH 2/3] Add peekdata and pokedata --- src/sys/ptrace.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index f4187aa125..a772a3a350 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -205,3 +205,18 @@ pub fn traceme() -> Result<()> { ptr::null_mut(), ).map(|_| ()) // ignore the useless return value } + +/// Makes the `PTRACE_PEEKDATA` request to ptrace +pub fn peekdata(pid: Pid, addr: c_long) -> Result { + ptrace(ptrace::PTRACE_PEEKDATA, pid, addr as *mut c_void, ptr::null_mut()) +} + +/// Makes the `PTRACE_PEEKDATA` request to ptrace +pub fn pokedata(pid: Pid, addr: c_long, val: c_long) -> Result<()> { + ptrace( + ptrace::PTRACE_POKEDATA, + pid, + addr as *mut c_void, + val as *mut c_void, + ).map(|_| ()) // ignore the useless return value +} \ No newline at end of file From 067f937f087c4fe00b7281d9829f33a3dae4a9bd Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Fri, 14 Jul 2017 11:17:12 +0200 Subject: [PATCH 3/3] Add high-level wrappers for some common ptrace routines and mark `nix::sys::ptrace::ptrace` as unsafe. `nix::sys::ptrace::ptrace` is unsafe by design. Its incorrect usage may lead to race conditions or crashes, and according to this post [1] should be marked unsafe. Additionally, wrappers with typically Rusty API have been introduced for some of the common ptrace routines. It is not a complete coverage and this subject should be revisited in the future. Some of these are `unsafe` by the sheer specification and have been marked so. --- src/sys/ptrace.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index 88b056d07f..3ad25ff080 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -70,9 +70,12 @@ mod ffi { } } -/// Performs a ptrace request. If the request in question is provided by a specialised function +/// A low-level wrapper for `ptrace`. If available, the higher-level wrappers should be considered instead. +/// Performs a `ptrace` request. If the request in question is provided by a specialised function /// this function will return an unsupported operation error. -pub fn ptrace(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result { +/// +/// When used incorrectly, this function may crash the tracer or the tracee, thus is marked `unsafe`. +pub unsafe fn ptrace(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result { use self::ptrace::*; match request { @@ -202,12 +205,19 @@ pub fn traceme() -> Result<()> { } /// Makes the `PTRACE_PEEKDATA` request to ptrace -pub fn peekdata(pid: Pid, addr: c_long) -> Result { +/// +/// This function allows to access arbitrary data in the traced process +/// and may crash the inferior if used incorrectly and is thus marked `unsafe`. +pub unsafe fn peekdata(pid: Pid, addr: c_long) -> Result { ptrace(ptrace::PTRACE_PEEKDATA, pid, addr as *mut c_void, ptr::null_mut()) } /// Makes the `PTRACE_PEEKDATA` request to ptrace -pub fn pokedata(pid: Pid, addr: c_long, val: c_long) -> Result<()> { +/// +/// This function allows to access arbitrary data in the traced process +/// and may crash the inferior or introduce race conditions if used +/// incorrectly and is thus marked `unsafe`. +pub unsafe fn pokedata(pid: Pid, addr: c_long, val: c_long) -> Result<()> { ptrace( ptrace::PTRACE_POKEDATA, pid,