Fix ptrace returning ENODEV when process exists

This commit is contained in:
jD91mZM2
2020-06-16 13:42:04 +02:00
parent cbb17327aa
commit 9c891384ea
3 changed files with 23 additions and 11 deletions

View File

@@ -112,7 +112,11 @@ impl Session {
F: FnOnce(&Session) -> Result<T>,
{
let sessions = sessions();
let session = sessions.get(&pid).ok_or(Error::new(ENODEV))?;
let session = sessions.get(&pid).ok_or_else(|| {
println!("session doesn't exist - returning ENODEV.");
println!("can this ever happen?");
Error::new(ENODEV)
})?;
callback(session)
}
@@ -160,6 +164,18 @@ pub fn close_session(pid: ContextId) {
if let Some(session) = sessions_mut().remove(&pid) {
session.tracer.notify();
session.tracee.notify();
}
}
/// Wake up the tracer to make sure it catches on that the tracee is dead. This
/// is different from `close_session` in that it doesn't actually close the
/// session, and instead waits for the file handle to be closed, where the
/// session will *actually* be closed. This is partly to ensure ENOSRCH is
/// returned rather than ENODEV (which occurs when there's no session - should
/// never really happen).
pub fn close_tracee(pid: ContextId) {
if let Some(session) = sessions().get(&pid) {
session.tracer.notify();
let data = session.data.lock();
proc_trigger_event(data.file_id, EVENT_READ);
@@ -250,13 +266,6 @@ pub fn wait(pid: ContextId) -> Result<()> {
}
}
let contexts = context::contexts();
let context = contexts.get(pid).ok_or(Error::new(ESRCH))?;
let context = context.read();
if let Status::Exited(_) = context.status {
return Err(Error::new(ESRCH));
}
Ok(())
}

View File

@@ -374,6 +374,9 @@ impl Scheme for ProcScheme {
ptrace::wait(handle.info.pid)?;
}
// Check if context exists
with_context(handle.info.pid, |_| Ok(()))?;
// Read events
let slice = unsafe {
slice::from_raw_parts_mut(

View File

@@ -1065,6 +1065,8 @@ pub fn fexec(fd: FileHandle, arg_ptrs: &[[usize; 2]], var_ptrs: &[[usize; 2]]) -
}
pub fn exit(status: usize) -> ! {
ptrace::breakpoint_callback(PTRACE_STOP_EXIT, Some(ptrace_event!(PTRACE_STOP_EXIT, status)));
{
let context_lock = {
let contexts = context::contexts();
@@ -1072,8 +1074,6 @@ pub fn exit(status: usize) -> ! {
Arc::clone(&context_lock)
};
ptrace::breakpoint_callback(PTRACE_STOP_EXIT, Some(ptrace_event!(PTRACE_STOP_EXIT, status)));
let mut close_files = Vec::new();
let pid = {
let mut context = context_lock.write();
@@ -1152,7 +1152,7 @@ pub fn exit(status: usize) -> ! {
}
// Alert any tracers waiting of this process
ptrace::close_session(pid);
ptrace::close_tracee(pid);
if pid == ContextId::from(1) {
println!("Main kernel thread exited with status {:X}", status);