From a7b2bd22c1c0c3bd50c1be9c94ee9352799c639d Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Sat, 27 Jul 2019 15:37:04 +0200 Subject: [PATCH] More cleanup... --- src/ptrace.rs | 62 +++++++++++++++++++------------------------- src/scheme/proc.rs | 23 +++++++++------- src/syscall/debug.rs | 16 ++++++------ 3 files changed, 47 insertions(+), 54 deletions(-) diff --git a/src/ptrace.rs b/src/ptrace.rs index 0de6b055..c296922a 100644 --- a/src/ptrace.rs +++ b/src/ptrace.rs @@ -55,6 +55,20 @@ struct Session { tracee: Arc<WaitCondition>, tracer: Arc<WaitCondition>, } +impl Session { + fn send_event(&mut self, event: PtraceEvent) { + self.events.push_back(event); + + // Notify nonblocking tracers + if self.events.len() == 1 { + // If the list of events was previously empty, alert now + proc_trigger_event(self.file_id, EVENT_READ); + } + + // Alert blocking tracers + self.tracer.notify(); + } +} type SessionMap = BTreeMap<ContextId, Session>; @@ -103,9 +117,6 @@ pub fn session_fevent_flags(pid: ContextId) -> Option<EventFlags> { if !session.events.is_empty() { flags |= EVENT_READ; } - if session.breakpoint.as_ref().map(|b| b.reached).unwrap_or(true) { - flags |= EVENT_WRITE; - } Some(flags) } @@ -139,16 +150,7 @@ pub fn send_event(event: PtraceEvent) -> Option<()> { return None; } - session.events.push_back(event); - - // Notify nonblocking tracers - if session.events.len() == 1 { - // If the list of events was previously empty, alert now - proc_trigger_event(session.file_id, EVENT_READ); - } - - // Alert blocking tracers - session.tracer.notify(); + session.send_event(event); Some(()) } @@ -209,31 +211,22 @@ pub fn set_breakpoint(pid: ContextId, flags: PtraceFlags) { /// /// Note: Don't call while holding any locks, this will switch /// contexts -pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> { +pub fn wait(pid: ContextId) -> Result<()> { let tracer: Arc<WaitCondition> = { let sessions = sessions(); match sessions.get(&pid) { Some(session) if session.breakpoint.as_ref().map(|b| !b.reached).unwrap_or(true) => { if !session.events.is_empty() { - return Ok(None); + return Ok(()); } Arc::clone(&session.tracer) }, - _ => return Ok(None) + _ => return Ok(()) } }; while !tracer.wait() {} - { - let sessions = sessions(); - if let Some(session) = sessions.get(&pid) { - if let Some(event) = session.events.front() { - return Ok(Some(event.clone())); - } - } - } - let contexts = context::contexts(); let context = contexts.get(pid).ok_or(Error::new(ESRCH))?; let context = context.read(); @@ -241,7 +234,7 @@ pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> { return Err(Error::new(ESRCH)); } - Ok(None) + Ok(()) } /// Notify the tracer and await green flag to continue. @@ -261,23 +254,16 @@ pub fn breakpoint_callback(match_flags: PtraceFlags, event: Option<PtraceEvent>) return None; } - session.events.push_back(event.unwrap_or(ptrace_event!(match_flags))); - - // Notify nonblocking tracers - if session.events.len() == 1 { - // If the list of events was previously empty, alert now - proc_trigger_event(session.file_id, EVENT_READ); - } - // In case no tracer is waiting, make sure the next one gets // the memo breakpoint.reached = true; - session.tracer.notify(); + let flags = breakpoint.flags; + session.send_event(event.unwrap_or(ptrace_event!(match_flags))); ( Arc::clone(&session.tracee), - breakpoint.flags + flags ) }; @@ -306,8 +292,12 @@ pub fn close_tracee(pid: ContextId) -> Option<()> { let mut sessions = sessions_mut(); let session = sessions.get_mut(&pid)?; + // Cause tracers to wake up. Any action will cause ESRCH which can + // be used to detect exit. session.breakpoint = None; session.tracer.notify(); + proc_trigger_event(session.file_id, EVENT_READ); + Some(()) } diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 57d06e0f..b91831a4 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -119,7 +119,7 @@ impl Handle { let contexts = context::contexts(); for pid in clones.drain(..) { if ptrace::is_traced(pid) { - return None; + continue; } if let Some(context) = contexts.get(pid) { let mut context = context.write(); @@ -332,13 +332,20 @@ impl Scheme for ProcScheme { Ok(len) }, - Operation::Trace { .. } => { - let read = ptrace::recv_events(info.pid, unsafe { + Operation::Trace { ref mut clones } => { + let slice = unsafe { slice::from_raw_parts_mut( buf.as_mut_ptr() as *mut PtraceEvent, buf.len() / mem::size_of::<PtraceEvent>() ) - }).unwrap_or(0); + }; + let read = ptrace::recv_events(info.pid, slice).unwrap_or(0); + + for event in &slice[..read] { + if event.cause == PTRACE_EVENT_CLONE { + clones.push(ContextId::from(event.a)); + } + } Ok(read * mem::size_of::<PtraceEvent>()) } @@ -409,7 +416,7 @@ impl Scheme for ProcScheme { }) } }, - Operation::Trace { ref mut clones } => { + Operation::Trace { .. } => { if buf.len() < mem::size_of::<u64>() { return Ok(0); } @@ -454,11 +461,7 @@ impl Scheme for ProcScheme { } if op.contains(PTRACE_FLAG_WAIT) || info.flags & O_NONBLOCK != O_NONBLOCK { - if let Some(event) = ptrace::wait(info.pid)? { - if event.cause == PTRACE_EVENT_CLONE { - clones.push(ContextId::from(event.a)); - } - } + ptrace::wait(info.pid)?; } Ok(mem::size_of::<u64>()) diff --git a/src/syscall/debug.rs b/src/syscall/debug.rs index 94f45528..3596efbb 100644 --- a/src/syscall/debug.rs +++ b/src/syscall/debug.rs @@ -175,8 +175,8 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - validate_slice_mut(c as *mut TimeSpec, 1) ), SYS_CLONE => format!( - "clone({})", - b + "clone({:?})", + CloneFlags::from_bits(b) ), SYS_EXIT => format!( "exit({})", @@ -256,10 +256,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - validate_slice(b as *const [usize; 2], c) ), SYS_MPROTECT => format!( - "mprotect({:#X}, {}, {:#X})", + "mprotect({:#X}, {}, {:?})", b, c, - d + ProtFlags::from_bits(d) ), SYS_NANOSLEEP => format!( "nanosleep({:?}, ({}, {}))", @@ -277,10 +277,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - c ), SYS_PHYSMAP => format!( - "physmap({:#X}, {}, {:#X})", + "physmap({:#X}, {}, {:?})", b, c, - d + PhysmapFlags::from_bits(d) ), SYS_PHYSUNMAP => format!( "physunmap({:#X})", @@ -315,10 +315,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - b ), SYS_WAITPID => format!( - "waitpid({}, {:#X}, {})", + "waitpid({}, {:#X}, {:?})", b, c, - d + WaitFlags::from_bits(d) ), SYS_YIELD => format!("yield()"), _ => format!( -- GitLab