Fix ptrace after latest kernel changes
This commit is contained in:
Generated
+1
-1
@@ -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)",
|
||||
]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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, ®s);
|
||||
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, ®s);
|
||||
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; }
|
||||
|
||||
Reference in New Issue
Block a user