summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2020-03-02 10:27:32 +0000
committerEmīls <emils@mullvad.net>2020-03-02 10:27:32 +0000
commitcb494f597ab1bc4a433ed4fd146bf147f4ef9d7a (patch)
tree4ee331a70b5378b9338d489a36445ce14bbff312
parent96cab3e773169f6be19aee8414265120254a9d6d (diff)
parent6ac144ec5833558e0db1846c6b81aa987a1ca7f9 (diff)
downloadmullvadvpn-cb494f597ab1bc4a433ed4fd146bf147f4ef9d7a.tar.xz
mullvadvpn-cb494f597ab1bc4a433ed4fd146bf147f4ef9d7a.zip
Merge branch 'add-signal-handlers'
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.lock16
-rw-r--r--mullvad-daemon/Cargo.toml1
-rw-r--r--mullvad-daemon/src/exception_logging/mod.rs11
-rw-r--r--mullvad-daemon/src/exception_logging/unix.rs85
-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.rs1
-rw-r--r--mullvad-daemon/src/main.rs6
-rw-r--r--mullvad-jni/src/lib.rs3
-rw-r--r--talpid-core/Cargo.toml2
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"