diff options
| author | David Lönnhager <david.l@mullvad.net> | 2022-06-07 15:16:31 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2022-06-14 13:59:49 +0200 |
| commit | f3acffca0c5da48c854658a19d11eed4104036b0 (patch) | |
| tree | 8ca38b0a72ebc231b891c244faf52ebb11f9899f /talpid-core/src | |
| parent | 463042e83845efd09f61cd99feb65db58240bb32 (diff) | |
| download | mullvadvpn-f3acffca0c5da48c854658a19d11eed4104036b0.tar.xz mullvadvpn-f3acffca0c5da48c854658a19d11eed4104036b0.zip | |
Track excluded processes and add CLI command for listing them on Windows
Diffstat (limited to 'talpid-core/src')
7 files changed, 100 insertions, 1 deletions
diff --git a/talpid-core/src/split_tunnel/windows/mod.rs b/talpid-core/src/split_tunnel/windows/mod.rs index 5b5b29e0cc..8b679106ea 100644 --- a/talpid-core/src/split_tunnel/windows/mod.rs +++ b/talpid-core/src/split_tunnel/windows/mod.rs @@ -12,15 +12,17 @@ use crate::{ }; use futures::channel::{mpsc, oneshot}; use std::{ + collections::HashMap, convert::TryFrom, ffi::{OsStr, OsString}, io, mem, net::{IpAddr, Ipv4Addr, Ipv6Addr}, os::windows::io::{AsRawHandle, RawHandle}, + path::{Path, PathBuf}, ptr, sync::{ atomic::{AtomicBool, Ordering}, - mpsc as sync_mpsc, Arc, Mutex, Weak, + mpsc as sync_mpsc, Arc, Mutex, RwLock, Weak, }, time::Duration, }; @@ -102,6 +104,7 @@ pub struct SplitTunnel { request_tx: RequestTx, event_thread: Option<std::thread::JoinHandle<()>>, quit_event: Arc<QuitEvent>, + excluded_pids: Arc<RwLock<HashMap<usize, ExcludedProcess>>>, _route_change_callback: Option<WinNetCallbackHandle>, daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>, async_path_update_in_progress: Arc<AtomicBool>, @@ -148,10 +151,23 @@ struct InterfaceAddresses { internet_ipv6: Option<Ipv6Addr>, } +/// Represents a process that is being excluded from the tunnel. +#[derive(Debug, Clone)] +pub struct ExcludedProcess { + /// Process identifier. + pub pid: u32, + /// Path to the image that this process is an instance of. + pub image: PathBuf, + /// If true, then the process is split because its parent was split, + /// not due to its path being in the config. + pub inherited: bool, +} + struct EventThreadContext { handle: Arc<driver::DeviceHandle>, event_overlapped: OVERLAPPED, quit_event: Arc<QuitEvent>, + excluded_pids: Arc<RwLock<HashMap<usize, ExcludedProcess>>>, } unsafe impl Send for EventThreadContext {} @@ -172,11 +188,13 @@ impl SplitTunnel { } let quit_event = Arc::new(QuitEvent::new()); + let excluded_pids = Arc::new(RwLock::new(HashMap::new())); let event_context = EventThreadContext { handle: handle.clone(), event_overlapped, quit_event: quit_event.clone(), + excluded_pids: excluded_pids.clone(), }; let event_thread = std::thread::spawn(move || { @@ -291,6 +309,34 @@ impl SplitTunnel { reason, image, } => { + let mut pids = event_context.excluded_pids.write().unwrap(); + match event_id { + EventId::StartSplittingProcess => { + if let Some(prev_entry) = pids.get(&process_id) { + log::error!("PID collision: {process_id} is already in the list of excluded processes. New image: {:?}. Current image: {:?}", image, prev_entry); + } + pids.insert( + process_id, + ExcludedProcess { + pid: u32::try_from(process_id) + .expect("PID should be containable in a DWORD"), + image: Path::new(&image).to_path_buf(), + inherited: reason.contains( + driver::SplittingChangeReason::BY_INHERITANCE, + ), + }, + ); + } + EventId::StopSplittingProcess => { + if pids.remove(&process_id).is_none() { + log::error!( + "Inconsistent process tree: {process_id} was not found" + ); + } + } + _ => (), + } + log::trace!( "{}:\n\tpid: {}\n\treason: {:?}\n\timage: {:?}", event_str, @@ -326,6 +372,7 @@ impl SplitTunnel { _route_change_callback: None, daemon_tx, async_path_update_in_progress: Arc::new(AtomicBool::new(false)), + excluded_pids, }) } @@ -562,6 +609,17 @@ impl SplitTunnel { self._route_change_callback = None; self.send_request(Request::RegisterIps(InterfaceAddresses::default())) } + + /// Return processes that are currently being excluded. + pub fn get_processes(&self) -> Result<Vec<ExcludedProcess>, Error> { + Ok(self + .excluded_pids + .read() + .unwrap() + .values() + .cloned() + .collect()) + } } impl Drop for SplitTunnel { diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs index 80e5e28957..beb29590c1 100644 --- a/talpid-core/src/tunnel_state_machine/connected_state.rs +++ b/talpid-core/src/tunnel_state_machine/connected_state.rs @@ -277,6 +277,11 @@ impl ConnectedState { shared_values.split_tunnel.set_paths(&paths, result_tx); SameState(self.into()) } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + SameState(self.into()) + } } } diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index 7536b26b09..64d21086cd 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -390,6 +390,11 @@ impl ConnectingState { shared_values.split_tunnel.set_paths(&paths, result_tx); SameState(self.into()) } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + SameState(self.into()) + } } } diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs index fa91284f6b..281b22b8f2 100644 --- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs @@ -208,6 +208,11 @@ impl TunnelState for DisconnectedState { shared_values.split_tunnel.set_paths(&paths, result_tx); SameState(self.into()) } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + SameState(self.into()) + } None => { Self::reset_dns(shared_values); Finished diff --git a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs index 2a14d881d6..2c42a1a864 100644 --- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs @@ -57,6 +57,11 @@ impl DisconnectingState { shared_values.split_tunnel.set_paths(&paths, result_tx); AfterDisconnect::Nothing } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + AfterDisconnect::Nothing + } }, AfterDisconnect::Block(reason) => match command { Some(TunnelCommand::AllowLan(allow_lan)) => { @@ -97,6 +102,11 @@ impl DisconnectingState { shared_values.split_tunnel.set_paths(&paths, result_tx); AfterDisconnect::Block(reason) } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + AfterDisconnect::Block(reason) + } None => AfterDisconnect::Block(reason), }, AfterDisconnect::Reconnect(retry_attempt) => match command { @@ -138,6 +148,11 @@ impl DisconnectingState { shared_values.split_tunnel.set_paths(&paths, result_tx); AfterDisconnect::Reconnect(retry_attempt) } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + AfterDisconnect::Reconnect(retry_attempt) + } }, }; diff --git a/talpid-core/src/tunnel_state_machine/error_state.rs b/talpid-core/src/tunnel_state_machine/error_state.rs index a11e49d859..d64393a432 100644 --- a/talpid-core/src/tunnel_state_machine/error_state.rs +++ b/talpid-core/src/tunnel_state_machine/error_state.rs @@ -209,6 +209,11 @@ impl TunnelState for ErrorState { shared_values.split_tunnel.set_paths(&paths, result_tx); SameState(self.into()) } + #[cfg(windows)] + Some(TunnelCommand::GetExcludedProcesses(result_tx)) => { + let _ = result_tx.send(shared_values.split_tunnel.get_processes()); + SameState(self.into()) + } } } } diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs index 6c388a4680..42d20181a4 100644 --- a/talpid-core/src/tunnel_state_machine/mod.rs +++ b/talpid-core/src/tunnel_state_machine/mod.rs @@ -189,6 +189,12 @@ pub enum TunnelCommand { oneshot::Sender<Result<(), split_tunnel::Error>>, Vec<OsString>, ), + /// Return a list of processes that are currently being split, as well as their + /// paths. + #[cfg(windows)] + GetExcludedProcesses( + oneshot::Sender<Result<Vec<split_tunnel::ExcludedProcess>, split_tunnel::Error>>, + ), } type TunnelCommandReceiver = stream::Fuse<mpsc::UnboundedReceiver<TunnelCommand>>; |
