summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2020-07-21 12:11:51 +0100
committerEmīls <emils@mullvad.net>2020-07-23 10:36:09 +0100
commit6a6e5dc05ea8cfd775aa6fb57ebdd328ee1f1884 (patch)
tree393c88b5a6372716e42faf8fcd29610c99a70603 /talpid-core/src
parent05fcc36628b7fd47ce348c038e9f19d9587352b1 (diff)
downloadmullvadvpn-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.rs67
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");