diff options
| author | Emīls <emils@mullvad.net> | 2020-07-21 12:11:51 +0100 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2020-07-23 10:36:09 +0100 |
| commit | 6a6e5dc05ea8cfd775aa6fb57ebdd328ee1f1884 (patch) | |
| tree | 393c88b5a6372716e42faf8fcd29610c99a70603 /talpid-core/src | |
| parent | 05fcc36628b7fd47ce348c038e9f19d9587352b1 (diff) | |
| download | mullvadvpn-6a6e5dc05ea8cfd775aa6fb57ebdd328ee1f1884.tar.xz mullvadvpn-6a6e5dc05ea8cfd775aa6fb57ebdd328ee1f1884.zip | |
Determine `net_cls` mountpoint dynamically
Diffstat (limited to 'talpid-core/src')
| -rw-r--r-- | talpid-core/src/split_tunnel/linux.rs | 67 |
1 files changed, 45 insertions, 22 deletions
diff --git a/talpid-core/src/split_tunnel/linux.rs b/talpid-core/src/split_tunnel/linux.rs index 6359e05669..8d9da5ebca 100644 --- a/talpid-core/src/split_tunnel/linux.rs +++ b/talpid-core/src/split_tunnel/linux.rs @@ -1,11 +1,12 @@ use std::{ fs, io::{self, BufRead, BufReader, BufWriter, Write}, - path::Path, + path::PathBuf, }; -use talpid_types::SPLIT_TUNNEL_CGROUP_NAME; +use talpid_types::cgroup::{find_net_cls_mount, SPLIT_TUNNEL_CGROUP_NAME}; -const NETCLS_DIR: &str = "/sys/fs/cgroup/net_cls/"; +const DEFAULT_NETCLS_DIR: &str = "/sys/fs/cgroup/net_cls"; +const NETCLS_DIR_OVERRIDE_ENV_VAR: &str = "TALPID_NETCLS_MOUNT_DIR"; /// Identifies packets coming from the cgroup. /// This should be an arbitrary but unique integer. @@ -41,37 +42,57 @@ pub enum Error { /// Unable to read cgroup.procs. #[error(display = "Unable to obtain PIDs from cgroup.procs")] ListCGroupPids(#[error(source)] io::Error), + + /// Unable to read /proc/mounts + #[error(display = "Failed to read /proc/mounts")] + ListMounts(#[error(source)] io::Error), } /// Manages PIDs to exclude from the tunnel. -pub struct PidManager(()); +pub struct PidManager { + net_cls_path: PathBuf, +} impl PidManager { /// Create object to manage split-tunnel PIDs. pub fn new() -> Result<PidManager, Error> { - Self::create_cgroup()?; - Ok(PidManager(())) + let manager = PidManager { + net_cls_path: Self::create_cgroup()?, + }; + manager.setup_exclusion_group()?; + Ok(manager) } /// Set up cgroup used to track PIDs for split tunneling. - fn create_cgroup() -> Result<(), Error> { - let netcls_dir = Path::new(NETCLS_DIR); + fn create_cgroup() -> Result<PathBuf, Error> { + if let Some(net_cls_path) = find_net_cls_mount().map_err(Error::ListMounts)? { + return Ok(net_cls_path); + } + + let netcls_dir = std::env::var(NETCLS_DIR_OVERRIDE_ENV_VAR) + .map(PathBuf::from) + .unwrap_or(PathBuf::from(DEFAULT_NETCLS_DIR)); + if !netcls_dir.exists() { fs::create_dir(netcls_dir.clone()).map_err(Error::CreateCGroup)?; - - // https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.txt - nix::mount::mount( - Some("net_cls"), - netcls_dir, - Some("cgroup"), - nix::mount::MsFlags::empty(), - Some("net_cls"), - ) - .map_err(Error::InitNetClsCGroup)?; } - let exclusions_dir = netcls_dir.join(SPLIT_TUNNEL_CGROUP_NAME); + // https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.txt + nix::mount::mount( + Some("net_cls"), + &netcls_dir, + Some("cgroup"), + nix::mount::MsFlags::empty(), + Some("net_cls"), + ) + .map_err(Error::InitNetClsCGroup)?; + + + Ok(netcls_dir) + } + fn setup_exclusion_group(&self) -> Result<(), Error> { + let exclusions_dir = self.net_cls_path.join(SPLIT_TUNNEL_CGROUP_NAME); if !exclusions_dir.exists() { fs::create_dir(exclusions_dir.clone()).map_err(Error::CreateCGroup)?; } @@ -88,7 +109,8 @@ impl PidManager { /// Add PIDs to exclude from the tunnel. pub fn add_list<T: Into<i32> + ToString>(&self, pids: &[T]) -> Result<(), Error> { - let exclusions_path = Path::new(NETCLS_DIR) + let exclusions_path = self + .net_cls_path .join(SPLIT_TUNNEL_CGROUP_NAME) .join("cgroup.procs"); @@ -113,7 +135,7 @@ impl PidManager { pub fn remove(&self, pid: i32) -> Result<(), Error> { // FIXME: We remove PIDs from our cgroup here by adding // them to the parent cgroup. This seems wrong. - let exclusions_path = Path::new(NETCLS_DIR).join("cgroup.procs"); + let exclusions_path = self.net_cls_path.join("cgroup.procs"); let mut file = fs::OpenOptions::new() .write(true) @@ -127,7 +149,8 @@ impl PidManager { /// Return a list of PIDs that are excluded from the tunnel. pub fn list(&self) -> Result<Vec<i32>, Error> { - let exclusions_path = Path::new(NETCLS_DIR) + let exclusions_path = self + .net_cls_path .join(SPLIT_TUNNEL_CGROUP_NAME) .join("cgroup.procs"); |
