-
Notifications
You must be signed in to change notification settings - Fork 674
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Move Ptrace{Request, Event, Options} into enums and bitflags. #461
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,87 @@ | ||
use {Errno, Error, Result}; | ||
use libc::{pid_t, c_void, c_long}; | ||
use libc::{pid_t, c_int, c_void, c_long}; | ||
|
||
#[cfg(all(target_os = "linux", | ||
any(target_arch = "x86", | ||
target_arch = "x86_64", | ||
target_arch = "arm")), | ||
)] | ||
#[cfg(any(target_os = "linux", target_os = "android"))] | ||
pub mod ptrace { | ||
use libc::c_int; | ||
use libc; | ||
|
||
pub type PtraceRequest = c_int; | ||
#[repr(u32)] | ||
pub enum PtraceRequest { | ||
PTRACE_TRACEME = libc::PTRACE_TRACEME, | ||
PTRACE_PEEKTEXT = libc::PTRACE_PEEKTEXT, | ||
PTRACE_PEEKDATA = libc::PTRACE_PEEKDATA, | ||
PTRACE_PEEKUSER = libc::PTRACE_PEEKUSER, | ||
PTRACE_POKETEXT = libc::PTRACE_POKETEXT, | ||
PTRACE_POKEDATA = libc::PTRACE_POKEDATA, | ||
PTRACE_POKEUSER = libc::PTRACE_POKEUSER, | ||
PTRACE_CONT = libc::PTRACE_CONT, | ||
PTRACE_KILL = libc::PTRACE_KILL, | ||
PTRACE_SINGLESTEP = libc::PTRACE_SINGLESTEP, | ||
PTRACE_GETREGS = libc::PTRACE_GETREGS, | ||
PTRACE_SETREGS = libc::PTRACE_SETREGS, | ||
PTRACE_GETFPREGS = libc::PTRACE_GETFPREGS, | ||
PTRACE_SETFPREGS = libc::PTRACE_SETFPREGS, | ||
PTRACE_ATTACH = libc::PTRACE_ATTACH, | ||
PTRACE_DETACH = libc::PTRACE_DETACH, | ||
PTRACE_GETFPXREGS = libc::PTRACE_GETFPXREGS, | ||
PTRACE_SETFPXREGS = libc::PTRACE_SETFPXREGS, | ||
PTRACE_SYSCALL = libc::PTRACE_SYSCALL, | ||
PTRACE_SETOPTIONS = libc::PTRACE_SETOPTIONS, | ||
PTRACE_GETEVENTMSG = libc::PTRACE_GETEVENTMSG, | ||
PTRACE_GETSIGINFO = libc::PTRACE_GETSIGINFO, | ||
PTRACE_SETSIGINFO = libc::PTRACE_SETSIGINFO, | ||
PTRACE_GETREGSET = libc::PTRACE_GETREGSET, | ||
PTRACE_SETREGSET = libc::PTRACE_SETREGSET, | ||
PTRACE_SEIZE = libc::PTRACE_SEIZE, | ||
PTRACE_INTERRUPT = libc::PTRACE_INTERRUPT, | ||
PTRACE_LISTEN = libc::PTRACE_LISTEN, | ||
PTRACE_PEEKSIGINFO = libc::PTRACE_PEEKSIGINFO, | ||
} | ||
|
||
pub const PTRACE_TRACEME: PtraceRequest = 0; | ||
pub const PTRACE_PEEKTEXT: PtraceRequest = 1; | ||
pub const PTRACE_PEEKDATA: PtraceRequest = 2; | ||
pub const PTRACE_PEEKUSER: PtraceRequest = 3; | ||
pub const PTRACE_POKETEXT: PtraceRequest = 4; | ||
pub const PTRACE_POKEDATA: PtraceRequest = 5; | ||
pub const PTRACE_POKEUSER: PtraceRequest = 6; | ||
pub const PTRACE_CONT: PtraceRequest = 7; | ||
pub const PTRACE_KILL: PtraceRequest = 8; | ||
pub const PTRACE_SINGLESTEP: PtraceRequest = 9; | ||
pub const PTRACE_GETREGS: PtraceRequest = 12; | ||
pub const PTRACE_SETREGS: PtraceRequest = 13; | ||
pub const PTRACE_GETFPREGS: PtraceRequest = 14; | ||
pub const PTRACE_SETFPREGS: PtraceRequest = 15; | ||
pub const PTRACE_ATTACH: PtraceRequest = 16; | ||
pub const PTRACE_DETACH: PtraceRequest = 17; | ||
pub const PTRACE_GETFPXREGS: PtraceRequest = 18; | ||
pub const PTRACE_SETFPXREGS: PtraceRequest = 19; | ||
pub const PTRACE_SYSCALL: PtraceRequest = 24; | ||
pub const PTRACE_SETOPTIONS: PtraceRequest = 0x4200; | ||
pub const PTRACE_GETEVENTMSG: PtraceRequest = 0x4201; | ||
pub const PTRACE_GETSIGINFO: PtraceRequest = 0x4202; | ||
pub const PTRACE_SETSIGINFO: PtraceRequest = 0x4203; | ||
pub const PTRACE_GETREGSET: PtraceRequest = 0x4204; | ||
pub const PTRACE_SETREGSET: PtraceRequest = 0x4205; | ||
pub const PTRACE_SEIZE: PtraceRequest = 0x4206; | ||
pub const PTRACE_INTERRUPT: PtraceRequest = 0x4207; | ||
pub const PTRACE_LISTEN: PtraceRequest = 0x4208; | ||
pub const PTRACE_PEEKSIGINFO: PtraceRequest = 0x4209; | ||
// These aren't currently in libc. | ||
#[cfg(any(target_os = "linux", target_os = "android"))] | ||
#[derive(Eq, PartialEq, Clone, Copy, Debug)] | ||
#[repr(u32)] | ||
pub enum PtraceEvent { | ||
PTRACE_EVENT_FORK = 1, | ||
PTRACE_EVENT_VFORK = 2, | ||
PTRACE_EVENT_CLONE = 3, | ||
PTRACE_EVENT_EXEC = 4, | ||
PTRACE_EVENT_VFORK_DONE = 5, | ||
PTRACE_EVENT_EXIT = 6, | ||
PTRACE_EVENT_SECCOMP = 7, | ||
PTRACE_EVENT_STOP = 128, | ||
} | ||
|
||
pub type PtraceEvent = c_int; | ||
#[cfg(any(target_os = "linux", target_os = "android"))] | ||
impl PtraceEvent { | ||
/// Creates a PtraceEvent from the extra bits of a wait status (status >> 16) | ||
#[inline] | ||
pub fn from_c_int(event: libc::c_uint) -> Option<PtraceEvent> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah sounds good I'll change that soon |
||
use std::mem; | ||
|
||
pub const PTRACE_EVENT_FORK: PtraceEvent = 1; | ||
pub const PTRACE_EVENT_VFORK: PtraceEvent = 2; | ||
pub const PTRACE_EVENT_CLONE: PtraceEvent = 3; | ||
pub const PTRACE_EVENT_EXEC: PtraceEvent = 4; | ||
pub const PTRACE_EVENT_VFORK_DONE: PtraceEvent = 5; | ||
pub const PTRACE_EVENT_EXIT: PtraceEvent = 6; | ||
pub const PTRACE_EVENT_SECCOMP: PtraceEvent = 6; | ||
pub const PTRACE_EVENT_STOP: PtraceEvent = 128; | ||
if (event >= PtraceEvent::PTRACE_EVENT_FORK as u32 && | ||
event <= PtraceEvent::PTRACE_EVENT_SECCOMP as u32) | ||
|| event == PtraceEvent::PTRACE_EVENT_STOP as u32 { | ||
Some(unsafe { mem::transmute(event) }) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
pub type PtraceOptions = c_int; | ||
pub const PTRACE_O_TRACESYSGOOD: PtraceOptions = 1; | ||
pub const PTRACE_O_TRACEFORK: PtraceOptions = (1 << PTRACE_EVENT_FORK); | ||
pub const PTRACE_O_TRACEVFORK: PtraceOptions = (1 << PTRACE_EVENT_VFORK); | ||
pub const PTRACE_O_TRACECLONE: PtraceOptions = (1 << PTRACE_EVENT_CLONE); | ||
pub const PTRACE_O_TRACEEXEC: PtraceOptions = (1 << PTRACE_EVENT_EXEC); | ||
pub const PTRACE_O_TRACEVFORKDONE: PtraceOptions = (1 << PTRACE_EVENT_VFORK_DONE); | ||
pub const PTRACE_O_TRACEEXIT: PtraceOptions = (1 << PTRACE_EVENT_EXIT); | ||
pub const PTRACE_O_TRACESECCOMP: PtraceOptions = (1 << PTRACE_EVENT_SECCOMP); | ||
bitflags! { | ||
flags PtraceOptions: libc::c_uint { | ||
const PTRACE_O_TRACESYSGOOD = libc::PTRACE_O_TRACESYSGOOD, | ||
const PTRACE_O_TRACEFORK = libc::PTRACE_O_TRACEFORK, | ||
const PTRACE_O_TRACEVFORK = libc::PTRACE_O_TRACEVFORK, | ||
const PTRACE_O_TRACECLONE = libc::PTRACE_O_TRACECLONE, | ||
const PTRACE_O_TRACEEXEC = libc::PTRACE_O_TRACEEXEC, | ||
const PTRACE_O_TRACEVFORKDONE = libc::PTRACE_O_TRACEVFORKDONE, | ||
const PTRACE_O_TRACEEXIT = libc::PTRACE_O_TRACEEXIT, | ||
const PTRACE_O_TRACESECCOMP = libc::PTRACE_O_TRACESECCOMP, | ||
} | ||
} | ||
} | ||
|
||
mod ffi { | ||
|
@@ -75,15 +96,15 @@ pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, dat | |
use self::ptrace::*; | ||
|
||
match request { | ||
PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), | ||
PtraceRequest::PTRACE_PEEKTEXT | PtraceRequest::PTRACE_PEEKDATA | PtraceRequest::PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), | ||
_ => ptrace_other(request, pid, addr, data) | ||
} | ||
} | ||
|
||
fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { | ||
let ret = unsafe { | ||
Errno::clear(); | ||
ffi::ptrace(request, pid, addr, data) | ||
ffi::ptrace(request as c_int, pid, addr, data) | ||
}; | ||
match Errno::result(ret) { | ||
Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret), | ||
|
@@ -92,13 +113,13 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da | |
} | ||
|
||
fn ptrace_other(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { | ||
Errno::result(unsafe { ffi::ptrace(request, pid, addr, data) }).map(|_| 0) | ||
Errno::result(unsafe { ffi::ptrace(request as c_int, pid, addr, data) }).map(|_| 0) | ||
} | ||
|
||
/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`. | ||
pub fn ptrace_setoptions(pid: pid_t, options: ptrace::PtraceOptions) -> Result<()> { | ||
use self::ptrace::*; | ||
use std::ptr; | ||
|
||
ptrace(PTRACE_SETOPTIONS, pid, ptr::null_mut(), options as *mut c_void).map(drop) | ||
ptrace(PtraceRequest::PTRACE_SETOPTIONS, pid, ptr::null_mut(), options.bits() as *mut c_void).map(drop) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use
#[repr(i32)]
and thus consistently the type, which is used by the ffi function.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't actually need the ffi function anymore, as ptrace has been added to the
libc
crate (https://doc.rust-lang.org/time/libc/fn.ptrace.html).u32
is consistent withlibc
's use ofc_uint
, but not with most C compilers' usage ofint
for enums (its not defined in the C spec afaik).I feel like the cleanest way to do this is to remove nix's ffi and just wrap
libc
as it is and leave the rest up tolibc
upstream. Thoughts?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, we do defer to libc. I just think that the signatures of
libc::ptrace
undfrom_c_[u]int
should use the same type (either c_int or c_uint), depending onlibc::ptrace
, because we have no influence on it.