|
| 1 | +#[cfg(all(target_os = "linux", |
| 2 | + any(target_arch = "x86_64", |
| 3 | + target_arch = "x86"), |
| 4 | + target_env = "gnu"))] |
| 5 | +use memoffset::offset_of; |
1 | 6 | use nix::errno::Errno; |
2 | 7 | use nix::unistd::getpid; |
3 | 8 | use nix::sys::ptrace; |
@@ -197,15 +202,29 @@ fn test_ptrace_syscall() { |
197 | 202 | #[cfg(target_arch = "x86")] |
198 | 203 | let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long; |
199 | 204 |
|
| 205 | + // this duplicates `get_syscall_id` for the purpose of testing `ptrace::read_user`. |
| 206 | + #[cfg(target_arch = "x86_64")] |
| 207 | + let rax_offset = offset_of!(libc::user_regs_struct, orig_rax); |
| 208 | + #[cfg(target_arch = "x86")] |
| 209 | + let rax_offset = offset_of!(libc::user_regs_struct, orig_eax); |
| 210 | + |
| 211 | + let get_syscall_from_user_area = || { |
| 212 | + // Find the offset of `user.regs.rax` (or `user.regs.eax` for x86) |
| 213 | + let rax_offset = offset_of!(libc::user, regs) + rax_offset; |
| 214 | + ptrace::read_user(child, rax_offset as _).unwrap() as libc::c_long |
| 215 | + }; |
| 216 | + |
200 | 217 | // kill entry |
201 | 218 | ptrace::syscall(child, None).unwrap(); |
202 | 219 | assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); |
203 | 220 | assert_eq!(get_syscall_id(), ::libc::SYS_kill); |
| 221 | + assert_eq!(get_syscall_from_user_area(), ::libc::SYS_kill); |
204 | 222 |
|
205 | 223 | // kill exit |
206 | 224 | ptrace::syscall(child, None).unwrap(); |
207 | 225 | assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); |
208 | 226 | assert_eq!(get_syscall_id(), ::libc::SYS_kill); |
| 227 | + assert_eq!(get_syscall_from_user_area(), ::libc::SYS_kill); |
209 | 228 |
|
210 | 229 | // receive signal |
211 | 230 | ptrace::syscall(child, None).unwrap(); |
|
0 commit comments