Fix ptrace after latest kernel changes

This commit is contained in:
jD91mZM2
2019-07-30 11:42:56 +02:00
parent b8c50c7c64
commit a1e45941bf
5 changed files with 39 additions and 23 deletions
Generated
+1 -1
View File
@@ -163,7 +163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall?branch=ptrace-6#a0581db1fa26da148ad6bb35975be084d1504f58"
source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall?branch=ptrace-6#51f0ef2826ef2b0369766c8f23c8069ae0a56846"
dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+1
View File
@@ -39,6 +39,7 @@ sc = "0.2.2"
[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall", branch = "ptrace-6" }
# redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" }
spin = "0.4.10"
[features]
+5 -3
View File
@@ -2,7 +2,7 @@ use core::{mem, ptr, result::Result as CoreResult, slice};
use syscall::{
self,
data::{Map, Stat as redox_stat, StatVfs as redox_statvfs, TimeSpec as redox_timespec},
Result,
PtraceEvent, Result,
};
use crate::{
@@ -947,8 +947,10 @@ impl Pal for Sys {
let mut sessions = state.sessions.lock();
if let Ok(session) = ptrace::get_session(&mut sessions, pid) {
if options & sys_wait::WNOHANG != sys_wait::WNOHANG {
let _ =
(&mut &session.tracer).write(&syscall::PTRACE_FLAG_WAIT.bits().to_ne_bytes());
let _ = (&mut &session.tracer).write(&syscall::PTRACE_FLAG_WAIT);
let mut _event = PtraceEvent::default();
let _ = (&mut &session.tracer).read(&mut _event);
res = Some(e(inner(
&mut status,
options | sys_wait::WNOHANG | sys_wait::WUNTRACED,
+26 -17
View File
@@ -17,10 +17,11 @@ use core::mem;
use syscall;
pub struct Session {
pub tracer: File,
pub first: bool,
pub fpregs: File,
pub mem: File,
pub regs: File,
pub fpregs: File,
pub tracer: File,
}
pub struct State {
pub sessions: Mutex<BTreeMap<pid_t, Session>>,
@@ -45,13 +46,17 @@ pub fn is_traceme(pid: pid_t) -> bool {
)
.is_ok()
}
pub fn get_session(sessions: &mut BTreeMap<pid_t, Session>, pid: pid_t) -> io::Result<&Session> {
pub fn get_session(
sessions: &mut BTreeMap<pid_t, Session>,
pid: pid_t,
) -> io::Result<&mut Session> {
const NEW_FLAGS: c_int = fcntl::O_RDWR | fcntl::O_CLOEXEC;
match sessions.entry(pid) {
Entry::Vacant(entry) => {
if is_traceme(pid) {
Ok(entry.insert(Session {
first: true,
tracer: File::open(
&CString::new(format!("proc:{}/trace", pid)).unwrap(),
NEW_FLAGS | fcntl::O_NONBLOCK,
@@ -110,21 +115,25 @@ fn inner_ptrace(
Sys::kill(pid, signal::SIGCONT as _);
// TODO: Translate errors
let syscall =
syscall::PTRACE_STOP_PRE_SYSCALL.bits() | syscall::PTRACE_STOP_POST_SYSCALL.bits();
(&mut &session.tracer).write(
&match request {
sys_ptrace::PTRACE_CONT => 0,
sys_ptrace::PTRACE_SINGLESTEP => syscall::PTRACE_STOP_SINGLESTEP.bits(),
sys_ptrace::PTRACE_SYSCALL => syscall,
sys_ptrace::PTRACE_SYSEMU => syscall::PTRACE_FLAG_SYSEMU.bits() | syscall,
sys_ptrace::PTRACE_SYSEMU_SINGLESTEP => {
syscall::PTRACE_FLAG_SYSEMU.bits() | syscall::PTRACE_STOP_SINGLESTEP.bits()
}
_ => unreachable!("unhandled ptrace request type {}", request),
let syscall = syscall::PTRACE_STOP_PRE_SYSCALL | syscall::PTRACE_STOP_POST_SYSCALL;
(&mut &session.tracer).write(&match request {
sys_ptrace::PTRACE_CONT => syscall::PtraceFlags::empty(),
sys_ptrace::PTRACE_SINGLESTEP => syscall::PTRACE_STOP_SINGLESTEP,
// Skip the first post-syscall when connected
sys_ptrace::PTRACE_SYSCALL if session.first => syscall::PTRACE_STOP_PRE_SYSCALL,
sys_ptrace::PTRACE_SYSCALL => syscall,
// Skip the first post-syscall when connected
sys_ptrace::PTRACE_SYSEMU if session.first => {
syscall::PTRACE_FLAG_SYSEMU | syscall::PTRACE_STOP_PRE_SYSCALL
}
.to_ne_bytes(),
)?;
sys_ptrace::PTRACE_SYSEMU => syscall::PTRACE_FLAG_SYSEMU | syscall,
sys_ptrace::PTRACE_SYSEMU_SINGLESTEP => {
syscall::PTRACE_FLAG_SYSEMU | syscall::PTRACE_STOP_SINGLESTEP
}
_ => unreachable!("unhandled ptrace request type {}", request),
})?;
session.first = false;
Ok(0)
}
sys_ptrace::PTRACE_GETREGS => {
+6 -2
View File
@@ -48,28 +48,32 @@ int main() {
int status;
while (true) {
// Pre-syscall:
puts("----- Pre-syscall -----");
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
ERROR_IF(ptrace, result, == -1);
UNEXP_IF(ptrace, result, != 0);
puts("Wait...");
result = waitpid(pid, &status, 0);
ERROR_IF(waitpid, result, == -1);
if (WIFEXITED(status)) { break; }
struct user_regs_struct regs;
puts("Get regs");
result = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
ERROR_IF(ptrace, result, == -1);
if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) {
regs.rdi = 2;
puts("Set regs");
result = ptrace(PTRACE_SETREGS, pid, NULL, &regs);
ERROR_IF(ptrace, result, == -1);
}
// Post-syscall:
puts("Post-syscall");
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
ERROR_IF(ptrace, result, == -1);
UNEXP_IF(ptrace, result, != 0);
puts("Wait...");
result = waitpid(pid, &status, 0);
ERROR_IF(waitpid, result, == -1);
if (WIFEXITED(status)) { break; }