@@ -6,68 +6,117 @@ use libc::{self, c_void, c_long, siginfo_t};
66use :: unistd:: Pid ;
77use sys:: signal:: Signal ;
88
9- pub mod ptrace {
10- use libc:: c_int;
11-
12- cfg_if ! {
13- if #[ cfg( any( all( target_os = "linux" , arch = "s390x" ) ,
14- all( target_os = "linux" , target_env = "gnu" ) ) ) ] {
15- pub type PtraceRequest = :: libc:: c_uint;
16- } else {
17- pub type PtraceRequest = c_int;
18- }
9+
10+ cfg_if ! {
11+ if #[ cfg( any( all( target_os = "linux" , arch = "s390x" ) ,
12+ all( target_os = "linux" , target_env = "gnu" ) ) ) ] {
13+ #[ doc( hidden) ]
14+ pub type RequestType = :: libc:: c_uint;
15+ } else {
16+ #[ doc( hidden) ]
17+ pub type RequestType = :: libc:: c_int;
18+ }
19+ }
20+
21+ libc_enum ! {
22+ #[ cfg_attr( not( any( target_env = "musl" , target_os = "android" ) ) , repr( u32 ) ) ]
23+ #[ cfg_attr( any( target_env = "musl" , target_os = "android" ) , repr( i32 ) ) ]
24+ /// Ptrace Request enum defining the action to be taken.
25+ pub enum Request {
26+ PTRACE_TRACEME ,
27+ PTRACE_PEEKTEXT ,
28+ PTRACE_PEEKDATA ,
29+ PTRACE_PEEKUSER ,
30+ PTRACE_POKETEXT ,
31+ PTRACE_POKEDATA ,
32+ PTRACE_POKEUSER ,
33+ PTRACE_CONT ,
34+ PTRACE_KILL ,
35+ PTRACE_SINGLESTEP ,
36+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" , target_arch = "s390x" ) , not( target_os = "android" ) ) ) ]
37+ PTRACE_GETREGS ,
38+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" , target_arch = "s390x" ) , not( target_os = "android" ) ) ) ]
39+ PTRACE_SETREGS ,
40+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" , target_arch = "s390x" ) , not( target_os = "android" ) ) ) ]
41+ PTRACE_GETFPREGS ,
42+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" , target_arch = "s390x" ) , not( target_os = "android" ) ) ) ]
43+ PTRACE_SETFPREGS ,
44+ PTRACE_ATTACH ,
45+ PTRACE_DETACH ,
46+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" ) , not( target_os = "android" ) ) ) ]
47+ PTRACE_GETFPXREGS ,
48+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" ) , not( target_os = "android" ) ) ) ]
49+ PTRACE_SETFPXREGS ,
50+ PTRACE_SYSCALL ,
51+ PTRACE_SETOPTIONS ,
52+ PTRACE_GETEVENTMSG ,
53+ PTRACE_GETSIGINFO ,
54+ PTRACE_SETSIGINFO ,
55+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" , target_arch = "s390x" ) , not( target_os = "android" ) ) ) ]
56+ PTRACE_GETREGSET ,
57+ #[ cfg( all( any( target_env = "musl" , target_arch ="x86_64" , target_arch = "s390x" ) , not( target_os = "android" ) ) ) ]
58+ PTRACE_SETREGSET ,
59+ #[ cfg( not( any( target_os = "android" , target_arch = "mips" , target_arch = "mips64" ) ) ) ]
60+ PTRACE_SEIZE ,
61+ #[ cfg( not( any( target_os = "android" , target_arch = "mips" , target_arch = "mips64" ) ) ) ]
62+ PTRACE_INTERRUPT ,
63+ #[ cfg( not( any( target_os = "android" , target_arch = "mips" , target_arch = "mips64" ) ) ) ]
64+ PTRACE_LISTEN ,
65+ #[ cfg( not( any( target_os = "android" , target_arch = "mips" , target_arch = "mips64" ) ) ) ]
66+ PTRACE_PEEKSIGINFO ,
67+ }
68+ }
69+
70+ libc_enum ! {
71+ #[ repr( i32 ) ]
72+ /// Using the ptrace options the tracer can configure the tracee to stop
73+ /// at certain events. This enum is used to define those events as defined
74+ /// in `man ptrace`.
75+ pub enum Event {
76+ /// Event that stops before a return from fork or clone.
77+ PTRACE_EVENT_FORK ,
78+ /// Event that stops before a return from vfork or clone.
79+ PTRACE_EVENT_VFORK ,
80+ /// Event that stops before a return from clone.
81+ PTRACE_EVENT_CLONE ,
82+ /// Event that stops before a return from execve.
83+ PTRACE_EVENT_EXEC ,
84+ /// Event for a return from vfork.
85+ PTRACE_EVENT_VFORK_DONE ,
86+ /// Event for a stop before an exit. Unlike the waitpid Exit status program.
87+ /// registers can still be examined
88+ PTRACE_EVENT_EXIT ,
89+ /// STop triggered by a seccomp rule on a tracee.
90+ PTRACE_EVENT_SECCOMP ,
91+ // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
1992 }
93+ }
2094
21- pub const PTRACE_TRACEME : PtraceRequest = 0 ;
22- pub const PTRACE_PEEKTEXT : PtraceRequest = 1 ;
23- pub const PTRACE_PEEKDATA : PtraceRequest = 2 ;
24- pub const PTRACE_PEEKUSER : PtraceRequest = 3 ;
25- pub const PTRACE_POKETEXT : PtraceRequest = 4 ;
26- pub const PTRACE_POKEDATA : PtraceRequest = 5 ;
27- pub const PTRACE_POKEUSER : PtraceRequest = 6 ;
28- pub const PTRACE_CONT : PtraceRequest = 7 ;
29- pub const PTRACE_KILL : PtraceRequest = 8 ;
30- pub const PTRACE_SINGLESTEP : PtraceRequest = 9 ;
31- pub const PTRACE_GETREGS : PtraceRequest = 12 ;
32- pub const PTRACE_SETREGS : PtraceRequest = 13 ;
33- pub const PTRACE_GETFPREGS : PtraceRequest = 14 ;
34- pub const PTRACE_SETFPREGS : PtraceRequest = 15 ;
35- pub const PTRACE_ATTACH : PtraceRequest = 16 ;
36- pub const PTRACE_DETACH : PtraceRequest = 17 ;
37- pub const PTRACE_GETFPXREGS : PtraceRequest = 18 ;
38- pub const PTRACE_SETFPXREGS : PtraceRequest = 19 ;
39- pub const PTRACE_SYSCALL : PtraceRequest = 24 ;
40- pub const PTRACE_SETOPTIONS : PtraceRequest = 0x4200 ;
41- pub const PTRACE_GETEVENTMSG : PtraceRequest = 0x4201 ;
42- pub const PTRACE_GETSIGINFO : PtraceRequest = 0x4202 ;
43- pub const PTRACE_SETSIGINFO : PtraceRequest = 0x4203 ;
44- pub const PTRACE_GETREGSET : PtraceRequest = 0x4204 ;
45- pub const PTRACE_SETREGSET : PtraceRequest = 0x4205 ;
46- pub const PTRACE_SEIZE : PtraceRequest = 0x4206 ;
47- pub const PTRACE_INTERRUPT : PtraceRequest = 0x4207 ;
48- pub const PTRACE_LISTEN : PtraceRequest = 0x4208 ;
49- pub const PTRACE_PEEKSIGINFO : PtraceRequest = 0x4209 ;
50-
51- pub type PtraceEvent = c_int ;
52-
53- pub const PTRACE_EVENT_FORK : PtraceEvent = 1 ;
54- pub const PTRACE_EVENT_VFORK : PtraceEvent = 2 ;
55- pub const PTRACE_EVENT_CLONE : PtraceEvent = 3 ;
56- pub const PTRACE_EVENT_EXEC : PtraceEvent = 4 ;
57- pub const PTRACE_EVENT_VFORK_DONE : PtraceEvent = 5 ;
58- pub const PTRACE_EVENT_EXIT : PtraceEvent = 6 ;
59- pub const PTRACE_EVENT_SECCOMP : PtraceEvent = 6 ;
60- pub const PTRACE_EVENT_STOP : PtraceEvent = 128 ;
61-
62- pub type PtraceOptions = c_int ;
63- pub const PTRACE_O_TRACESYSGOOD : PtraceOptions = 1 ;
64- pub const PTRACE_O_TRACEFORK : PtraceOptions = ( 1 << PTRACE_EVENT_FORK ) ;
65- pub const PTRACE_O_TRACEVFORK : PtraceOptions = ( 1 << PTRACE_EVENT_VFORK ) ;
66- pub const PTRACE_O_TRACECLONE : PtraceOptions = ( 1 << PTRACE_EVENT_CLONE ) ;
67- pub const PTRACE_O_TRACEEXEC : PtraceOptions = ( 1 << PTRACE_EVENT_EXEC ) ;
68- pub const PTRACE_O_TRACEVFORKDONE : PtraceOptions = ( 1 << PTRACE_EVENT_VFORK_DONE ) ;
69- pub const PTRACE_O_TRACEEXIT : PtraceOptions = ( 1 << PTRACE_EVENT_EXIT ) ;
70- pub const PTRACE_O_TRACESECCOMP : PtraceOptions = ( 1 << PTRACE_EVENT_SECCOMP ) ;
95+ libc_bitflags ! {
96+ /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
97+ /// See `man ptrace` for more details.
98+ pub struct Options : libc:: c_int {
99+ /// When delivering system call traps set a bit to allow tracer to
100+ /// distinguish between normal stops or syscall stops. May not work on
101+ /// all systems.
102+ PTRACE_O_TRACESYSGOOD ;
103+ /// Stop tracee at next fork and start tracing the forked process.
104+ PTRACE_O_TRACEFORK ;
105+ /// Stop tracee at next vfork call and trace the vforked process.
106+ PTRACE_O_TRACEVFORK ;
107+ /// Stop tracee at next clone call and trace the cloned process.
108+ PTRACE_O_TRACECLONE ;
109+ /// Stop tracee at next execve call.
110+ PTRACE_O_TRACEEXEC ;
111+ /// Stop tracee at vfork completion.
112+ PTRACE_O_TRACEVFORKDONE ;
113+ /// Stop tracee at next exit call. Stops before exit commences allowing
114+ /// tracer to see location of exit and register states.
115+ PTRACE_O_TRACEEXIT ;
116+ /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
117+ /// details.
118+ PTRACE_O_TRACESECCOMP ;
119+ }
71120}
72121
73122/// Performs a ptrace request. If the request in question is provided by a specialised function
@@ -76,20 +125,19 @@ pub mod ptrace {
76125 since="0.10.0" ,
77126 note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
78127) ]
79- pub unsafe fn ptrace ( request : ptrace:: PtraceRequest , pid : Pid , addr : * mut c_void , data : * mut c_void ) -> Result < c_long > {
80- use self :: ptrace:: * ;
81-
128+ pub unsafe fn ptrace ( request : Request , pid : Pid , addr : * mut c_void , data : * mut c_void ) -> Result < c_long > {
129+ use self :: Request :: * ;
82130 match request {
83131 PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek ( request, pid, addr, data) ,
84132 PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err ( Error :: UnsupportedOperation ) ,
85133 _ => ptrace_other ( request, pid, addr, data)
86134 }
87135}
88136
89- fn ptrace_peek ( request : ptrace :: PtraceRequest , pid : Pid , addr : * mut c_void , data : * mut c_void ) -> Result < c_long > {
137+ fn ptrace_peek ( request : Request , pid : Pid , addr : * mut c_void , data : * mut c_void ) -> Result < c_long > {
90138 let ret = unsafe {
91139 Errno :: clear ( ) ;
92- libc:: ptrace ( request, libc:: pid_t:: from ( pid) , addr, data)
140+ libc:: ptrace ( request as RequestType , libc:: pid_t:: from ( pid) , addr, data)
93141 } ;
94142 match Errno :: result ( ret) {
95143 Ok ( ..) | Err ( Error :: Sys ( Errno :: UnknownErrno ) ) => Ok ( ret) ,
@@ -101,45 +149,54 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data
101149/// Some ptrace get requests populate structs or larger elements than c_long
102150/// and therefore use the data field to return values. This function handles these
103151/// requests.
104- fn ptrace_get_data < T > ( request : ptrace :: PtraceRequest , pid : Pid ) -> Result < T > {
152+ fn ptrace_get_data < T > ( request : Request , pid : Pid ) -> Result < T > {
105153 // Creates an uninitialized pointer to store result in
106154 let data: T = unsafe { mem:: uninitialized ( ) } ;
107- let res = unsafe { libc:: ptrace ( request, libc:: pid_t:: from ( pid) , ptr:: null_mut :: < T > ( ) , & data as * const _ as * const c_void ) } ;
155+ let res = unsafe {
156+ libc:: ptrace ( request as RequestType ,
157+ libc:: pid_t:: from ( pid) ,
158+ ptr:: null_mut :: < T > ( ) ,
159+ & data as * const _ as * const c_void )
160+ } ;
108161 Errno :: result ( res) ?;
109162 Ok ( data)
110163}
111164
112- unsafe fn ptrace_other ( request : ptrace :: PtraceRequest , pid : Pid , addr : * mut c_void , data : * mut c_void ) -> Result < c_long > {
113- Errno :: result ( libc:: ptrace ( request, libc:: pid_t:: from ( pid) , addr, data) ) . map ( |_| 0 )
165+ unsafe fn ptrace_other ( request : Request , pid : Pid , addr : * mut c_void , data : * mut c_void ) -> Result < c_long > {
166+ Errno :: result ( libc:: ptrace ( request as RequestType , libc:: pid_t:: from ( pid) , addr, data) ) . map ( |_| 0 )
114167}
115168
116169/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
117- pub fn setoptions ( pid : Pid , options : ptrace:: PtraceOptions ) -> Result < ( ) > {
118- use self :: ptrace:: * ;
170+ pub fn setoptions ( pid : Pid , options : Options ) -> Result < ( ) > {
119171 use std:: ptr;
120172
121- let res = unsafe { libc:: ptrace ( PTRACE_SETOPTIONS , libc:: pid_t:: from ( pid) , ptr:: null_mut :: < libc:: c_void > ( ) , options as * mut c_void ) } ;
173+ let res = unsafe {
174+ libc:: ptrace ( Request :: PTRACE_SETOPTIONS as RequestType ,
175+ libc:: pid_t:: from ( pid) ,
176+ ptr:: null_mut :: < libc:: c_void > ( ) ,
177+ options. bits ( ) as * mut c_void )
178+ } ;
122179 Errno :: result ( res) . map ( |_| ( ) )
123180}
124181
125182/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
126183pub fn getevent ( pid : Pid ) -> Result < c_long > {
127- use self :: ptrace:: * ;
128- ptrace_get_data :: < c_long > ( PTRACE_GETEVENTMSG , pid)
184+ ptrace_get_data :: < c_long > ( Request :: PTRACE_GETEVENTMSG , pid)
129185}
130186
131187/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
132188pub fn getsiginfo ( pid : Pid ) -> Result < siginfo_t > {
133- use self :: ptrace:: * ;
134- ptrace_get_data :: < siginfo_t > ( PTRACE_GETSIGINFO , pid)
189+ ptrace_get_data :: < siginfo_t > ( Request :: PTRACE_GETSIGINFO , pid)
135190}
136191
137192/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
138193pub fn setsiginfo ( pid : Pid , sig : & siginfo_t ) -> Result < ( ) > {
139- use self :: ptrace:: * ;
140194 let ret = unsafe {
141195 Errno :: clear ( ) ;
142- libc:: ptrace ( PTRACE_SETSIGINFO , libc:: pid_t:: from ( pid) , ptr:: null_mut :: < libc:: c_void > ( ) , sig as * const _ as * const c_void )
196+ libc:: ptrace ( Request :: PTRACE_SETSIGINFO as RequestType ,
197+ libc:: pid_t:: from ( pid) ,
198+ ptr:: null_mut :: < libc:: c_void > ( ) ,
199+ sig as * const _ as * const c_void )
143200 } ;
144201 match Errno :: result ( ret) {
145202 Ok ( _) => Ok ( ( ) ) ,
@@ -154,7 +211,7 @@ pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
154211pub fn traceme ( ) -> Result < ( ) > {
155212 unsafe {
156213 ptrace_other (
157- ptrace :: PTRACE_TRACEME ,
214+ Request :: PTRACE_TRACEME ,
158215 Pid :: from_raw ( 0 ) ,
159216 ptr:: null_mut ( ) ,
160217 ptr:: null_mut ( ) ,
@@ -168,7 +225,7 @@ pub fn traceme() -> Result<()> {
168225pub fn syscall ( pid : Pid ) -> Result < ( ) > {
169226 unsafe {
170227 ptrace_other (
171- ptrace :: PTRACE_SYSCALL ,
228+ Request :: PTRACE_SYSCALL ,
172229 pid,
173230 ptr:: null_mut ( ) ,
174231 ptr:: null_mut ( ) ,
@@ -182,14 +239,28 @@ pub fn syscall(pid: Pid) -> Result<()> {
182239pub fn attach ( pid : Pid ) -> Result < ( ) > {
183240 unsafe {
184241 ptrace_other (
185- ptrace :: PTRACE_ATTACH ,
242+ Request :: PTRACE_ATTACH ,
186243 pid,
187244 ptr:: null_mut ( ) ,
188245 ptr:: null_mut ( ) ,
189246 ) . map ( |_| ( ) ) // ignore the useless return value
190247 }
191248}
192249
250+ /// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
251+ ///
252+ /// Detaches from the process specified in pid allowing it to run freely
253+ pub fn detach ( pid : Pid ) -> Result < ( ) > {
254+ unsafe {
255+ ptrace_other (
256+ Request :: PTRACE_DETACH ,
257+ pid,
258+ ptr:: null_mut ( ) ,
259+ ptr:: null_mut ( )
260+ ) . map ( |_| ( ) )
261+ }
262+ }
263+
193264/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
194265///
195266/// Continues the execution of the process with PID `pid`, optionally
@@ -200,7 +271,7 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
200271 None => ptr:: null_mut ( ) ,
201272 } ;
202273 unsafe {
203- ptrace_other ( ptrace :: PTRACE_CONT , pid, ptr:: null_mut ( ) , data) . map ( |_| ( ) ) // ignore the useless return value
274+ ptrace_other ( Request :: PTRACE_CONT , pid, ptr:: null_mut ( ) , data) . map ( |_| ( ) ) // ignore the useless return value
204275 }
205276}
206277
0 commit comments