From 846d0a2be3e0e982005fc5f7801a9be477879dcd Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Mon, 1 Nov 2021 21:00:51 +0100 Subject: [PATCH] fix(core): prevent certain commands from being run as root on macOS. Fix #648 --- espanso/src/cli/daemon/mod.rs | 4 +++- espanso/src/cli/service/macos.rs | 6 ++++++ espanso/src/cli/util.rs | 16 ++++++++++++++++ espanso/src/cli/worker/mod.rs | 3 +++ espanso/src/exit_code.rs | 3 +++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/espanso/src/cli/daemon/mod.rs b/espanso/src/cli/daemon/mod.rs index 1b1c2fe..206ad73 100644 --- a/espanso/src/cli/daemon/mod.rs +++ b/espanso/src/cli/daemon/mod.rs @@ -28,7 +28,7 @@ use espanso_path::Paths; use log::{error, info, warn}; use crate::{ - cli::util::CommandExt, + cli::util::{prevent_running_as_root_on_macos, CommandExt}, common_flags::*, exit_code::{ DAEMON_ALREADY_RUNNING, DAEMON_FATAL_CONFIG_ERROR, DAEMON_GENERAL_ERROR, @@ -60,6 +60,8 @@ pub fn new() -> CliModule { } fn daemon_main(args: CliModuleArgs) -> i32 { + prevent_running_as_root_on_macos(); + let paths = args.paths.expect("missing paths in daemon main"); let paths_overrides = args .paths_overrides diff --git a/espanso/src/cli/service/macos.rs b/espanso/src/cli/service/macos.rs index f6914f5..cbf1b8c 100644 --- a/espanso/src/cli/service/macos.rs +++ b/espanso/src/cli/service/macos.rs @@ -23,12 +23,16 @@ use std::process::Command; use std::{fs::create_dir_all, process::ExitStatus}; use thiserror::Error; +use crate::cli::util::prevent_running_as_root_on_macos; + #[cfg(target_os = "macos")] const SERVICE_PLIST_CONTENT: &str = include_str!("../../res/macos/com.federicoterzi.espanso.plist"); #[cfg(target_os = "macos")] const SERVICE_PLIST_FILE_NAME: &str = "com.federicoterzi.espanso.plist"; pub fn register() -> Result<()> { + prevent_running_as_root_on_macos(); + let home_dir = dirs::home_dir().expect("could not get user home directory"); let library_dir = home_dir.join("Library"); let agents_dir = library_dir.join("LaunchAgents"); @@ -94,6 +98,8 @@ pub enum RegisterError { } pub fn unregister() -> Result<()> { + prevent_running_as_root_on_macos(); + let home_dir = dirs::home_dir().expect("could not get user home directory"); let library_dir = home_dir.join("Library"); let agents_dir = library_dir.join("LaunchAgents"); diff --git a/espanso/src/cli/util.rs b/espanso/src/cli/util.rs index e029a74..401ce2c 100644 --- a/espanso/src/cli/util.rs +++ b/espanso/src/cli/util.rs @@ -53,3 +53,19 @@ impl CommandExt for Command { self } } + +// For context, see also this issue: https://github.com/federico-terzi/espanso/issues/648 +#[cfg(target_os = "macos")] +pub fn prevent_running_as_root_on_macos() { + use crate::{error_eprintln, exit_code::UNEXPECTED_RUN_AS_ROOT}; + + if unsafe { libc::geteuid() } == 0 { + error_eprintln!("Espanso is being run as root, but this can create unwanted side-effects. Please run it as a normal user."); + std::process::exit(UNEXPECTED_RUN_AS_ROOT); + } +} + +#[cfg(not(target_os = "macos"))] +pub fn prevent_running_as_root_on_macos() { + // Do nothing on other platforms +} diff --git a/espanso/src/cli/worker/mod.rs b/espanso/src/cli/worker/mod.rs index f5dd997..b2cf019 100644 --- a/espanso/src/cli/worker/mod.rs +++ b/espanso/src/cli/worker/mod.rs @@ -22,6 +22,7 @@ use espanso_engine::event::ExitMode; use log::{debug, error, info}; use crate::{ + cli::util::prevent_running_as_root_on_macos, exit_code::{ WORKER_ALREADY_RUNNING, WORKER_EXIT_ALL_PROCESSES, WORKER_GENERAL_ERROR, WORKER_LEGACY_ALREADY_RUNNING, WORKER_RESTART, WORKER_SUCCESS, @@ -58,6 +59,8 @@ pub fn new() -> CliModule { } fn worker_main(args: CliModuleArgs) -> i32 { + prevent_running_as_root_on_macos(); + let paths = args.paths.expect("missing paths in worker main"); let cli_args = args.cli_args.expect("missing cli_args in worker main"); diff --git a/espanso/src/exit_code.rs b/espanso/src/exit_code.rs index 01ade17..15be31b 100644 --- a/espanso/src/exit_code.rs +++ b/espanso/src/exit_code.rs @@ -68,6 +68,9 @@ pub const PACKAGE_LIST_FAILED: i32 = 4; pub const PACKAGE_UPDATE_FAILED: i32 = 5; pub const PACKAGE_UPDATE_PARTIAL_FAILURE: i32 = 6; +#[allow(dead_code)] +pub const UNEXPECTED_RUN_AS_ROOT: i32 = 42; + use std::sync::Mutex; use crate::error_eprintln;