More cleanup...

This commit is contained in:
jD91mZM2
2019-07-27 15:37:04 +02:00
parent 538ca49ee2
commit a7b2bd22c1
3 changed files with 47 additions and 54 deletions

View File

@@ -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(())
}

View File

@@ -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>())

View File

@@ -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!(