diff options
| author | Emīls <emils@mullvad.net> | 2020-03-02 10:27:32 +0000 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2020-03-02 10:27:32 +0000 |
| commit | cb494f597ab1bc4a433ed4fd146bf147f4ef9d7a (patch) | |
| tree | 4ee331a70b5378b9338d489a36445ce14bbff312 | |
| parent | 96cab3e773169f6be19aee8414265120254a9d6d (diff) | |
| parent | 6ac144ec5833558e0db1846c6b81aa987a1ca7f9 (diff) | |
| download | mullvadvpn-cb494f597ab1bc4a433ed4fd146bf147f4ef9d7a.tar.xz mullvadvpn-cb494f597ab1bc4a433ed4fd146bf147f4ef9d7a.zip | |
Merge branch 'add-signal-handlers'
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | Cargo.lock | 16 | ||||
| -rw-r--r-- | mullvad-daemon/Cargo.toml | 1 | ||||
| -rw-r--r-- | mullvad-daemon/src/exception_logging/mod.rs | 11 | ||||
| -rw-r--r-- | mullvad-daemon/src/exception_logging/unix.rs | 85 | ||||
| -rw-r--r-- | mullvad-daemon/src/exception_logging/win.rs (renamed from mullvad-daemon/src/windows_exception_logging.rs) | 0 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 1 | ||||
| -rw-r--r-- | mullvad-daemon/src/main.rs | 6 | ||||
| -rw-r--r-- | mullvad-jni/src/lib.rs | 3 | ||||
| -rw-r--r-- | talpid-core/Cargo.toml | 2 |
10 files changed, 120 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index da329aade8..f6d0665b47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ Line wrap the file at 100 chars. Th ## [Unreleased] ### Added +- Added signal handlers on Unix platforms to better log critical faults with the daemon. + #### Android - Add option to enable auto-connecting behavior - Include an initial relay list in the APK so that the app can connect to the VPN even if it fails diff --git a/Cargo.lock b/Cargo.lock index 8c49e13408..1341249e2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1272,6 +1272,7 @@ dependencies = [ "mullvad-paths 0.1.0", "mullvad-rpc 0.1.0", "mullvad-types 0.1.0", + "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1525,6 +1526,18 @@ dependencies = [ ] [[package]] +name = "nix" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2443,7 +2456,7 @@ dependencies = [ "netlink-proto 0.1.1 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", "netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?rev=f768adfcc8c6b064ef7ae3c792c4c21d0d96d0b5)", "nftnl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "openvpn-plugin 0.3.0 (git+https://github.com/mullvad/openvpn-plugin-rs?branch=auth-failed-event)", "os_pipe 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3313,6 +3326,7 @@ dependencies = [ "checksum nftnl-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d559148c09433fa20478524cb97ee3af7b6391d8edf19c709e9eb86a53f2bab" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" +"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" diff --git a/mullvad-daemon/Cargo.toml b/mullvad-daemon/Cargo.toml index ddd41ff074..c2f934e716 100644 --- a/mullvad-daemon/Cargo.toml +++ b/mullvad-daemon/Cargo.toml @@ -45,6 +45,7 @@ android_logger = "0.8" [target.'cfg(unix)'.dependencies] libc = "0.2" +nix = "0.17" simple-signal = "1.1" [target.'cfg(windows)'.dependencies] diff --git a/mullvad-daemon/src/exception_logging/mod.rs b/mullvad-daemon/src/exception_logging/mod.rs new file mode 100644 index 0000000000..c1962a1ca1 --- /dev/null +++ b/mullvad-daemon/src/exception_logging/mod.rs @@ -0,0 +1,11 @@ +#[cfg(windows)] +mod win; + +#[cfg(windows)] +pub use win::enable; + +#[cfg(unix)] +mod unix; + +#[cfg(unix)] +pub use unix::enable; diff --git a/mullvad-daemon/src/exception_logging/unix.rs b/mullvad-daemon/src/exception_logging/unix.rs new file mode 100644 index 0000000000..977d3857b1 --- /dev/null +++ b/mullvad-daemon/src/exception_logging/unix.rs @@ -0,0 +1,85 @@ +//! Installs signal handlers to catch critical program faults and logs them. + +use libc::{c_int, c_void, siginfo_t}; +use nix::sys::signal::*; + +use std::{convert::TryFrom, sync::Once}; + +const INIT_ONCE: Once = Once::new(); + +const FAULT_SIGNALS: [Signal; 5] = [ + // Access to invalid memory address + Signal::SIGBUS, + // Floating point exception + Signal::SIGFPE, + // Illegal instructors + Signal::SIGILL, + // Invalid memory reference + Signal::SIGSEGV, + // Bad syscall + Signal::SIGSYS, +]; + +/// Installs a signal handler. +pub fn enable() { + INIT_ONCE.call_once(|| { + // Setup alt stack for signal handlers to be executed in. + // If the daemon ever needs to be compiled for architectures where memory can't be writeable + // and executable, the following block of code has to be disabled. This will also mean that + // stack overflows may be silent and undetectable in logs. + let sig_handler_flags = { + // The kernel will use the first properly aligned address, so alignment is not an issue. + let alt_stack = vec![0u8; libc::SIGSTKSZ]; + let stack_t = libc::stack_t { + ss_sp: alt_stack.as_ptr() as *mut c_void, + ss_flags: 0, + ss_size: alt_stack.len(), + }; + let ret = unsafe { libc::sigaltstack(&stack_t, std::ptr::null_mut()) }; + if ret != 0 { + log::error!( + "Failed to set alternative stack - {}", + std::io::Error::last_os_error() + ); + SaFlags::empty() + } else { + std::mem::forget(alt_stack); + SaFlags::SA_ONSTACK + } + }; + + let signal_action = SigAction::new( + SigHandler::SigAction(fault_handler), + sig_handler_flags, + SigSet::empty(), + ); + + for signal in &FAULT_SIGNALS { + if let Err(err) = unsafe { sigaction(*signal, &signal_action) } { + log::error!("Failed to install signal handler for {}: {}", signal, err); + } + } + }); +} + +/// Signal handler to catch signals that are used to indicate unrecoverable errors in the daemon +extern "C" fn fault_handler( + signum: c_int, + _siginfo: *mut siginfo_t, + _thread_context_ptr: *mut c_void, +) { + let signal: Signal = match Signal::try_from(signum) { + Ok(signal) => signal, + Err(err) => { + log::error!( + "Signal handler triggered by unknown signal {}, exiting: {}", + signum, + err + ); + std::process::exit(2); + } + }; + + log::error!("Caught signal {}", signal); + std::process::exit(2); +} diff --git a/mullvad-daemon/src/windows_exception_logging.rs b/mullvad-daemon/src/exception_logging/win.rs index c6e2422398..c6e2422398 100644 --- a/mullvad-daemon/src/windows_exception_logging.rs +++ b/mullvad-daemon/src/exception_logging/win.rs diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index ffce1b4187..aa7912ebf6 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -5,6 +5,7 @@ extern crate serde; mod account_history; +pub mod exception_logging; mod geoip; pub mod logging; #[cfg(not(target_os = "android"))] diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index 4928ba277e..8795861dbe 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -10,11 +10,10 @@ use std::{path::PathBuf, thread, time::Duration}; use talpid_types::ErrorExt; mod cli; +mod exception_logging; mod shutdown; #[cfg(windows)] mod system_service; -#[cfg(windows)] -mod windows_exception_logging; const DAEMON_LOG_FILENAME: &str = "daemon.log"; @@ -46,8 +45,7 @@ fn init_logging(config: &cli::Config) -> Result<Option<PathBuf>, String> { ) .map_err(|e| e.display_chain_with_msg("Unable to initialize logger"))?; log_panics::init(); - #[cfg(windows)] - windows_exception_logging::enable(); + exception_logging::enable(); version::log_version(); if let Some(ref log_dir) = log_dir { info!("Logging to {}", log_dir.display()); diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index b9ff6a40fb..d26deeb2af 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -17,7 +17,7 @@ use jnix::{ FromJava, IntoJava, JnixEnv, }; use lazy_static::lazy_static; -use mullvad_daemon::{logging, version, Daemon, DaemonCommandChannel}; +use mullvad_daemon::{exception_logging, logging, version, Daemon, DaemonCommandChannel}; use mullvad_types::account::AccountData; use std::{ path::{Path, PathBuf}, @@ -118,6 +118,7 @@ fn start_logging() -> Result<PathBuf, Error> { logging::init_logger(log::LevelFilter::Debug, Some(&log_file), true) .map_err(Error::StartLogging)?; + exception_logging::enable(); log_panics::init(); version::log_version(); diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index 607c02349c..6221b14d8f 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -35,7 +35,7 @@ chrono = "0.4" [target.'cfg(unix)'.dependencies] -nix = "0.15" +nix = "0.17" tokio-process = "0.2" tokio-io = "0.1" |
