From cf0a7620df02d5f0faacbe2dbbc83c51bb73f81b Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Thu, 15 Aug 2019 14:23:54 +0200 Subject: [PATCH] Add ptrace exit breakpoint This will let you stop at process exit and inspect it right before the process dies. --- src/context/signal.rs | 1 - src/lib.rs | 1 - src/ptrace.rs | 8 +++++--- src/scheme/mod.rs | 6 +++--- src/scheme/sys/mod.rs | 2 +- src/syscall/process.rs | 9 ++++++--- syscall | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/context/signal.rs b/src/context/signal.rs index 942fb28c..78e165af 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -1,6 +1,5 @@ use alloc::sync::Arc; use core::mem; -use syscall::data::PtraceEvent; use syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_SIGNAL, SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU}; use syscall::ptrace_event; diff --git a/src/lib.rs b/src/lib.rs index 24b265af..b7acc714 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,6 @@ #![cfg_attr(feature = "clippy", allow(or_fun_call))] #![cfg_attr(feature = "clippy", allow(too_many_arguments))] #![deny(unreachable_patterns)] -#![feature(alloc)] #![feature(allocator_api)] #![feature(asm)] #![feature(concat_idents)] diff --git a/src/ptrace.rs b/src/ptrace.rs index a720ea3e..b3631969 100644 --- a/src/ptrace.rs +++ b/src/ptrace.rs @@ -209,8 +209,8 @@ pub fn set_breakpoint(pid: ContextId, flags: PtraceFlags) { /// Wait for the tracee to stop. If an event occurs, it returns a copy /// of that. It will still be available for read using recv_event. /// -/// Note: Don't call while holding any locks, this will switch -/// contexts +/// Note: Don't call while holding any locks or allocated data, this +/// will switch contexts and may in fact just never terminate. pub fn wait(pid: ContextId) -> Result<()> { let tracer: Arc<WaitCondition> = { let sessions = sessions(); @@ -238,7 +238,9 @@ pub fn wait(pid: ContextId) -> Result<()> { } /// Notify the tracer and await green flag to continue. -/// Note: Don't call while holding any locks, this will switch contexts +/// +/// Note: Don't call while holding any locks or allocated data, this +/// will switch contexts and may in fact just never terminate. pub fn breakpoint_callback(match_flags: PtraceFlags, event: Option<PtraceEvent>) -> Option<PtraceFlags> { // Can't hold any locks when executing wait() let (tracee, flags) = { diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 8d2e345e..fbdaba62 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -173,7 +173,7 @@ impl SchemeList { Ok(to) } - pub fn iter(&self) -> ::alloc::collections::btree_map::Iter<SchemeId, Arc<Box<Scheme + Send + Sync>>> { + pub fn iter(&self) -> ::alloc::collections::btree_map::Iter<SchemeId, Arc<Box<dyn Scheme + Send + Sync>>> { self.map.iter() } @@ -188,7 +188,7 @@ impl SchemeList { self.map.get(&id) } - pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> { + pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<dyn Scheme + Send + Sync>>)> { if let Some(names) = self.names.get(&ns) { if let Some(&id) = names.get(name) { return self.get(id).map(|scheme| (id, scheme)); @@ -199,7 +199,7 @@ impl SchemeList { /// Create a new scheme. pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId> - where F: Fn(SchemeId) -> Arc<Box<Scheme + Send + Sync>> + where F: Fn(SchemeId) -> Arc<Box<dyn Scheme + Send + Sync>> { if let Some(names) = self.names.get(&ns) { if names.contains_key(&name) { diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index ee995117..d12729d7 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -27,7 +27,7 @@ struct Handle { seek: usize } -type SysFn = Fn() -> Result<Vec<u8>> + Send + Sync; +type SysFn = dyn Fn() -> Result<Vec<u8>> + Send + Sync; /// System information scheme pub struct SysScheme { diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 646db9a1..45baf3b1 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -21,12 +21,13 @@ use crate::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, PA use crate::{ptrace, syscall}; use crate::scheme::FileHandle; use crate::start::usermode; -use crate::syscall::data::{PtraceEvent, SigAction, Stat}; +use crate::syscall::data::{SigAction, Stat}; use crate::syscall::error::*; use crate::syscall::flag::{CloneFlags, CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, CLONE_STACK, MapFlags, PROT_EXEC, PROT_READ, PROT_WRITE, PTRACE_EVENT_CLONE, - SigActionFlags, SIG_DFL, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, SIGCONT, SIGTERM, - WaitFlags, WCONTINUED, WNOHANG, WUNTRACED, wifcontinued, wifstopped}; + PTRACE_STOP_EXIT, SigActionFlags, SIG_DFL, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, + SIGCONT, SIGTERM, WaitFlags, WCONTINUED, WNOHANG, WUNTRACED, wifcontinued, + wifstopped}; use crate::syscall::ptrace_event; use crate::syscall::validate::{validate_slice, validate_slice_mut}; @@ -1064,6 +1065,8 @@ 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(); diff --git a/syscall b/syscall index 0e1e7d5d..6ba71e7e 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 0e1e7d5d36f8c6f045e30c37515d366350eb2122 +Subproject commit 6ba71e7e065d37309b7d5c4fc86835dd350f61b7 -- GitLab