summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2022-09-21 15:06:31 +0200
committerEmīls Piņķis <emils@mullvad.net>2022-09-21 15:06:31 +0200
commit38dbbabc416076456ff9c80f5d5e62c573a13f0d (patch)
tree816703c1465157759b1bfdf2ff2484952127412d
parentd4b7d8004ac0074aa27048d0c97b988e740abab7 (diff)
parent55ab6decf719e9769fe7864ec7961118c275f404 (diff)
downloadmullvadvpn-38dbbabc416076456ff9c80f5d5e62c573a13f0d.tar.xz
mullvadvpn-38dbbabc416076456ff9c80f5d5e62c573a13f0d.zip
Merge branch 'linux-block-during-shutdown'
-rw-r--r--CHANGELOG.md5
-rw-r--r--Cargo.lock1
-rw-r--r--mullvad-daemon/Cargo.toml1
-rw-r--r--mullvad-daemon/src/lib.rs3
-rw-r--r--mullvad-daemon/src/main.rs10
-rw-r--r--mullvad-daemon/src/shutdown.rs25
-rw-r--r--talpid-dbus/src/lib.rs1
-rw-r--r--talpid-dbus/src/systemd.rs67
8 files changed, 108 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 125cd3bab5..b1ed1e7d4b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -74,10 +74,13 @@ Line wrap the file at 100 chars. Th
- Don't fail install if the device tree contains nameless callout driver devices.
### Security
-#### Linux
- Added traffic blocking during early boot, before the daemon starts, to prevent leaks in the case
that the system service starts after a networking daemon has already configured a network
interface.
+- When the system process is being shut down and the target state is _secured_, maintain the
+ blocking firewall rules unless it's possible to deduce that the system isn't shutting down and the
+ system service is being stopped by the user intentionally. This is to prevent leaks that might
+ occur during system shutdown.
## [android/2022.2-beta2] - 2022-09-09
diff --git a/Cargo.lock b/Cargo.lock
index 201b3f31d6..c53f7641df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1593,6 +1593,7 @@ dependencies = [
"serde_json",
"simple-signal",
"talpid-core",
+ "talpid-dbus",
"talpid-platform-metadata",
"talpid-time",
"talpid-types",
diff --git a/mullvad-daemon/Cargo.toml b/mullvad-daemon/Cargo.toml
index 6a811659c5..6eac4eb156 100644
--- a/mullvad-daemon/Cargo.toml
+++ b/mullvad-daemon/Cargo.toml
@@ -34,6 +34,7 @@ mullvad-relay-selector = { path = "../mullvad-relay-selector" }
mullvad-types = { path = "../mullvad-types" }
mullvad-api = { path = "../mullvad-api" }
talpid-core = { path = "../talpid-core" }
+talpid-dbus = { path = "../talpid-dbus" }
talpid-types = { path = "../talpid-types" }
talpid-platform-metadata = { path = "../talpid-platform-metadata" }
talpid-time = { path = "../talpid-time" }
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 88dd9da735..d2aea87af8 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -22,6 +22,7 @@ mod migrations;
pub mod rpc_uniqueness_check;
pub mod runtime;
pub mod settings;
+pub mod shutdown;
mod target_state;
mod tunnel;
pub mod version;
@@ -2159,11 +2160,9 @@ where
}
}
- #[cfg_attr(not(target_os = "windows"), allow(unused_variables))]
fn trigger_shutdown_event(&mut self, user_init_shutdown: bool) {
// Block all traffic before shutting down to ensure that no traffic can leak on boot or
// shutdown.
- #[cfg(windows)]
if !user_init_shutdown
&& (*self.target_state == TargetState::Secured || self.settings.auto_connect)
{
diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs
index 1d929c2d4a..23946fbf1a 100644
--- a/mullvad-daemon/src/main.rs
+++ b/mullvad-daemon/src/main.rs
@@ -14,7 +14,6 @@ mod cli;
#[cfg(target_os = "linux")]
mod early_boot_firewall;
mod exception_logging;
-mod shutdown;
#[cfg(windows)]
mod system_service;
@@ -138,7 +137,14 @@ async fn run_standalone(log_dir: Option<PathBuf>) -> Result<(), String> {
let daemon = create_daemon(log_dir).await?;
let shutdown_handle = daemon.shutdown_handle();
- shutdown::set_shutdown_signal_handler(move || shutdown_handle.shutdown(true))
+ #[cfg(any(target_os = "linux", target_os = "macos"))]
+ mullvad_daemon::shutdown::set_shutdown_signal_handler(move || {
+ shutdown_handle.shutdown(!mullvad_daemon::shutdown::is_shutdown_user_initiated())
+ })
+ .map_err(|e| e.display_chain())?;
+
+ #[cfg(any(windows, target_os = "android"))]
+ mullvad_daemon::shutdown::set_shutdown_signal_handler(move || shutdown_handle.shutdown(true))
.map_err(|e| e.display_chain())?;
daemon.run().await.map_err(|e| e.display_chain())?;
diff --git a/mullvad-daemon/src/shutdown.rs b/mullvad-daemon/src/shutdown.rs
index 8dff1bc553..a3f04a0c49 100644
--- a/mullvad-daemon/src/shutdown.rs
+++ b/mullvad-daemon/src/shutdown.rs
@@ -27,4 +27,29 @@ mod platform {
}
}
+/// Returns true if systemd successfully reported that the machine is not shutting down or entering
+/// maintenance. If obtaining this information fails, the return value will be `false` and it will
+/// be assumed that the machine is shutting down.
+#[cfg(target_os = "linux")]
+pub fn is_shutdown_user_initiated() -> bool {
+ match talpid_dbus::systemd::is_host_running() {
+ Ok(is_host_running) => is_host_running,
+ Err(err) => {
+ log::error!(
+ "{}",
+ talpid_types::ErrorExt::display_chain_with_msg(
+ &err,
+ "Failed to determine if host is shutting down, assuming it is shutting down"
+ )
+ );
+ false
+ }
+ }
+}
+
+#[cfg(target_os = "macos")]
+pub fn is_shutdown_user_initiated() -> bool {
+ false
+}
+
pub use self::platform::*;
diff --git a/talpid-dbus/src/lib.rs b/talpid-dbus/src/lib.rs
index c4b9bb7e12..f85581864a 100644
--- a/talpid-dbus/src/lib.rs
+++ b/talpid-dbus/src/lib.rs
@@ -4,6 +4,7 @@ pub use dbus;
use dbus::blocking::SyncConnection;
use std::sync::{Arc, Mutex};
pub mod network_manager;
+pub mod systemd;
pub mod systemd_resolved;
lazy_static::lazy_static! {
diff --git a/talpid-dbus/src/systemd.rs b/talpid-dbus/src/systemd.rs
new file mode 100644
index 0000000000..521f2a1b8e
--- /dev/null
+++ b/talpid-dbus/src/systemd.rs
@@ -0,0 +1,67 @@
+use dbus::blocking::{stdintf::org_freedesktop_dbus::Properties, Proxy, SyncConnection};
+use std::{sync::Arc, time::Duration};
+
+type Result<T> = std::result::Result<T, Error>;
+
+#[derive(err_derive::Error, Debug)]
+#[error(no_from)]
+pub enum Error {
+ #[error(display = "Failed to create a DBus connection")]
+ ConnectError(#[error(source)] dbus::Error),
+
+ #[error(display = "Failed to read SystemState property")]
+ ReadSystemStateError(#[error(source)] dbus::Error),
+}
+
+const SYSTEMD_BUS: &str = "org.freedesktop.systemd1";
+const SYSTEMD_PATH: &str = "/org/freedesktop/systemd1";
+const MANAGER_INTERFACE: &str = "org.freedesktop.systemd1.Manager";
+const SYSTEM_STATE: &str = "SystemState";
+const SYSTEM_STATE_STARTING: &str = "starting";
+const SYSTEM_STATE_INITIALIZING: &str = "initializing";
+const SYSTEM_STATE_RUNNING: &str = "running";
+const SYSTEM_STATE_DEGRADED: &str = "degraded";
+
+const RPC_TIMEOUT: Duration = Duration::from_secs(1);
+
+/// Returns true if the host is not shutting down or entering maintenance mode or some other weird
+/// state.
+pub fn is_host_running() -> Result<bool> {
+ Systemd::new()?.system_is_running()
+}
+
+struct Systemd {
+ pub dbus_connection: Arc<SyncConnection>,
+}
+
+impl Systemd {
+ fn new() -> Result<Self> {
+ Ok(Self {
+ dbus_connection: crate::get_connection().map_err(Error::ConnectError)?,
+ })
+ }
+
+ fn system_is_running(&self) -> Result<bool> {
+ self.as_manager_object()
+ .get(MANAGER_INTERFACE, SYSTEM_STATE)
+ .map(|state: String| {
+ ![
+ SYSTEM_STATE_STARTING,
+ SYSTEM_STATE_INITIALIZING,
+ SYSTEM_STATE_RUNNING,
+ SYSTEM_STATE_DEGRADED,
+ ]
+ .contains(&state.as_str())
+ })
+ .map_err(Error::ReadSystemStateError)
+ }
+
+ fn as_manager_object(&self) -> Proxy<'_, &SyncConnection> {
+ Proxy::new(
+ SYSTEMD_BUS,
+ SYSTEMD_PATH,
+ RPC_TIMEOUT,
+ &self.dbus_connection,
+ )
+ }
+}