diff --git a/Cargo.lock b/Cargo.lock index b8de54a..29bed3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,7 @@ dependencies = [ "hashbrown 0.11.2", "hex", "indexmap", + "privdrop", "rand", "serde", ] @@ -179,7 +180,6 @@ dependencies = [ "mimalloc", "mio", "parking_lot", - "privdrop", "quickcheck", "quickcheck_macros", "rand", diff --git a/aquatic_common/Cargo.toml b/aquatic_common/Cargo.toml index 02fbe6e..e86e0d0 100644 --- a/aquatic_common/Cargo.toml +++ b/aquatic_common/Cargo.toml @@ -16,5 +16,6 @@ arc-swap = "1" hashbrown = "0.11.2" hex = "0.4" indexmap = "1" +privdrop = "0.5" rand = { version = "0.8", features = ["small_rng"] } serde = { version = "1", features = ["derive"] } diff --git a/aquatic_common/src/lib.rs b/aquatic_common/src/lib.rs index 4ad9e8e..8866e45 100644 --- a/aquatic_common/src/lib.rs +++ b/aquatic_common/src/lib.rs @@ -6,6 +6,7 @@ use rand::Rng; pub mod access_list; pub mod cpu_pinning; +pub mod privileges; /// Peer or connection valid until this instant /// diff --git a/aquatic_common/src/privileges.rs b/aquatic_common/src/privileges.rs new file mode 100644 index 0000000..67b9e5b --- /dev/null +++ b/aquatic_common/src/privileges.rs @@ -0,0 +1,59 @@ +use std::{sync::{Arc, atomic::{AtomicUsize, Ordering}}, time::Duration}; + +use privdrop::PrivDrop; +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct PrivilegeConfig { + /// Chroot and switch user after binding to sockets + pub drop_privileges: bool, + /// Chroot to this path + pub chroot_path: String, + /// User to switch to after chrooting + pub user: String, +} + +impl Default for PrivilegeConfig { + fn default() -> Self { + Self { + drop_privileges: false, + chroot_path: ".".to_string(), + user: "nobody".to_string(), + } + } +} + +pub fn drop_privileges_after_socket_binding( + config: &PrivilegeConfig, + num_bound_sockets: Arc, + target_num: usize, +) -> anyhow::Result<()> { + if config.drop_privileges { + let mut counter = 0usize; + + loop { + let num_bound = num_bound_sockets.load(Ordering::SeqCst); + + if num_bound == target_num { + PrivDrop::default() + .chroot(config.chroot_path.clone()) + .user(config.user.clone()) + .apply()?; + + break; + } + + ::std::thread::sleep(Duration::from_millis(10)); + + counter += 1; + + if counter == 500 { + panic!("Sockets didn't bind in time for privilege drop."); + } + } + } + + Ok(()) +} + diff --git a/aquatic_http/src/lib/config.rs b/aquatic_http/src/lib/config.rs index 0be33ed..33068a4 100644 --- a/aquatic_http/src/lib/config.rs +++ b/aquatic_http/src/lib/config.rs @@ -1,6 +1,6 @@ use std::{net::SocketAddr, path::PathBuf}; -use aquatic_common::access_list::AccessListConfig; +use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig}; use aquatic_common::cpu_pinning::CpuPinningConfig; use serde::{Deserialize, Serialize}; @@ -94,17 +94,6 @@ pub struct StatisticsConfig { pub interval: u64, } -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(default)] -pub struct PrivilegeConfig { - /// Chroot and switch user after binding to sockets - pub drop_privileges: bool, - /// Chroot to this path - pub chroot_path: String, - /// User to switch to after chrooting - pub user: String, -} - impl Default for Config { fn default() -> Self { Self { @@ -118,7 +107,7 @@ impl Default for Config { statistics: StatisticsConfig::default(), privileges: PrivilegeConfig::default(), access_list: AccessListConfig::default(), - cpu_pinning: CpuPinningConfig::default(), + cpu_pinning: Default::default(), } } } @@ -171,16 +160,6 @@ impl Default for StatisticsConfig { } } -impl Default for PrivilegeConfig { - fn default() -> Self { - Self { - drop_privileges: false, - chroot_path: ".".to_string(), - user: "nobody".to_string(), - } - } -} - impl Default for TlsConfig { fn default() -> Self { Self { diff --git a/aquatic_http/src/lib/glommio/mod.rs b/aquatic_http/src/lib/glommio/mod.rs index 5976602..629e239 100644 --- a/aquatic_http/src/lib/glommio/mod.rs +++ b/aquatic_http/src/lib/glommio/mod.rs @@ -4,7 +4,7 @@ use std::{ sync::{atomic::AtomicUsize, Arc}, }; -use aquatic_common::access_list::AccessList; +use aquatic_common::{access_list::AccessList, privileges::drop_privileges_after_socket_binding}; use glommio::{channels::channel_mesh::MeshBuilder, prelude::*}; use crate::config::Config; @@ -94,7 +94,7 @@ pub fn run(config: Config) -> anyhow::Result<()> { executors.push(executor); } - // drop_privileges_after_socket_binding(&config, num_bound_sockets).unwrap(); + drop_privileges_after_socket_binding(&config.privileges, num_bound_sockets, config.socket_workers).unwrap(); for executor in executors { executor diff --git a/aquatic_udp/Cargo.toml b/aquatic_udp/Cargo.toml index 4dfed44..a7bf538 100644 --- a/aquatic_udp/Cargo.toml +++ b/aquatic_udp/Cargo.toml @@ -32,7 +32,6 @@ indexmap = "1" log = "0.4" mimalloc = { version = "0.1", default-features = false } parking_lot = "0.11" -privdrop = "0.5" rand = { version = "0.8", features = ["small_rng"] } serde = { version = "1", features = ["derive"] } diff --git a/aquatic_udp/src/lib/config.rs b/aquatic_udp/src/lib/config.rs index ccf1b37..2f1540a 100644 --- a/aquatic_udp/src/lib/config.rs +++ b/aquatic_udp/src/lib/config.rs @@ -1,6 +1,6 @@ use std::net::SocketAddr; -use aquatic_common::access_list::AccessListConfig; +use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig}; use aquatic_common::cpu_pinning::CpuPinningConfig; use serde::{Deserialize, Serialize}; @@ -99,17 +99,6 @@ pub struct CleaningConfig { pub max_connection_age: u64, } -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(default)] -pub struct PrivilegeConfig { - /// Chroot and switch user after binding to sockets - pub drop_privileges: bool, - /// Chroot to this path - pub chroot_path: String, - /// User to switch to after chrooting - pub user: String, -} - impl Default for Config { fn default() -> Self { Self { @@ -177,13 +166,3 @@ impl Default for CleaningConfig { } } } - -impl Default for PrivilegeConfig { - fn default() -> Self { - Self { - drop_privileges: false, - chroot_path: ".".to_string(), - user: "nobody".to_string(), - } - } -} diff --git a/aquatic_udp/src/lib/glommio/mod.rs b/aquatic_udp/src/lib/glommio/mod.rs index 407bb18..4979d84 100644 --- a/aquatic_udp/src/lib/glommio/mod.rs +++ b/aquatic_udp/src/lib/glommio/mod.rs @@ -1,11 +1,11 @@ use std::sync::{atomic::AtomicUsize, Arc}; use aquatic_common::access_list::AccessList; +use aquatic_common::privileges::drop_privileges_after_socket_binding; use glommio::channels::channel_mesh::MeshBuilder; use glommio::prelude::*; use crate::config::Config; -use crate::drop_privileges_after_socket_binding; mod common; pub mod handlers; @@ -88,7 +88,7 @@ pub fn run(config: Config) -> anyhow::Result<()> { executors.push(executor); } - drop_privileges_after_socket_binding(&config, num_bound_sockets).unwrap(); + drop_privileges_after_socket_binding(&config.privileges, num_bound_sockets, config.socket_workers).unwrap(); for executor in executors { executor diff --git a/aquatic_udp/src/lib/lib.rs b/aquatic_udp/src/lib/lib.rs index e3eea68..e7796d4 100644 --- a/aquatic_udp/src/lib/lib.rs +++ b/aquatic_udp/src/lib/lib.rs @@ -16,7 +16,6 @@ pub mod glommio; pub mod mio; use config::Config; -use privdrop::PrivDrop; pub const APP_NAME: &str = "aquatic_udp: UDP BitTorrent tracker"; @@ -28,36 +27,4 @@ pub fn run(config: Config) -> ::anyhow::Result<()> { mio::run(config) } } -} - -fn drop_privileges_after_socket_binding( - config: &Config, - num_bound_sockets: Arc, -) -> anyhow::Result<()> { - if config.privileges.drop_privileges { - let mut counter = 0usize; - - loop { - let sockets = num_bound_sockets.load(Ordering::SeqCst); - - if sockets == config.socket_workers { - PrivDrop::default() - .chroot(config.privileges.chroot_path.clone()) - .user(config.privileges.user.clone()) - .apply()?; - - break; - } - - ::std::thread::sleep(Duration::from_millis(10)); - - counter += 1; - - if counter == 500 { - panic!("Sockets didn't bind in time for privilege drop."); - } - } - } - - Ok(()) -} +} \ No newline at end of file diff --git a/aquatic_udp/src/lib/mio/mod.rs b/aquatic_udp/src/lib/mio/mod.rs index 0a74702..3127ce2 100644 --- a/aquatic_udp/src/lib/mio/mod.rs +++ b/aquatic_udp/src/lib/mio/mod.rs @@ -6,6 +6,7 @@ use std::{ }; use anyhow::Context; +use aquatic_common::privileges::drop_privileges_after_socket_binding; use crossbeam_channel::unbounded; pub mod common; @@ -16,7 +17,6 @@ pub mod tasks; use aquatic_common::access_list::{AccessListArcSwap, AccessListMode, AccessListQuery}; use crate::config::Config; -use crate::drop_privileges_after_socket_binding; use common::State; @@ -35,7 +35,7 @@ pub fn run(config: Config) -> ::anyhow::Result<()> { start_workers(config.clone(), state.clone(), num_bound_sockets.clone())?; - drop_privileges_after_socket_binding(&config, num_bound_sockets).unwrap(); + drop_privileges_after_socket_binding(&config.privileges, num_bound_sockets, config.socket_workers).unwrap(); loop { ::std::thread::sleep(Duration::from_secs(config.cleaning.interval));