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