From bbbcb0c08f4a6a63230288485d88492465e2a593 Mon Sep 17 00:00:00 2001 From: renoseven Date: Sat, 11 May 2024 10:21:58 +0800 Subject: [PATCH] security: change daemon socket permission 1. add socket uid & gid to config file default uid: 0 default gid: 0 2. set socket permission by its uid & gid uid == gid: 0600 uid != gid: 0660 Signed-off-by: renoseven --- Cargo.lock | 2 + syscared/Cargo.toml | 1 + syscared/src/args.rs | 8 ++- syscared/src/config.rs | 88 ++++++++++++++++++++++++++++++ syscared/src/main.rs | 70 ++++++++++++++++++------ upatchd/Cargo.toml | 2 +- upatchd/src/config.rs | 91 ++++++++++++++++++++++++++++++++ upatchd/src/hijacker/config.rs | 85 +++++------------------------ upatchd/src/hijacker/mod.rs | 47 +++-------------- upatchd/src/main.rs | 55 ++++++++++++++----- upatchd/src/rpc/skeleton_impl.rs | 8 +-- 11 files changed, 310 insertions(+), 147 deletions(-) create mode 100644 syscared/src/config.rs create mode 100644 upatchd/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index e6d830b..e3074a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -511,6 +511,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] @@ -1185,6 +1186,7 @@ dependencies = [ "object", "parking_lot", "serde", + "serde_yaml", "signal-hook", "syscare-abi", "syscare-common", diff --git a/syscared/Cargo.toml b/syscared/Cargo.toml index 2b148e7..27f27e2 100644 --- a/syscared/Cargo.toml +++ b/syscared/Cargo.toml @@ -26,5 +26,6 @@ nix = { version = "0.26" } object = { version = "0.29" } parking_lot = { version = "0.11" } serde = { version = "1.0", features = ["derive"] } +serde_yaml = { version = "0.8" } signal-hook = { version = "0.3" } uuid = { version = "0.8", features = ["v4", "serde"] } diff --git a/syscared/src/args.rs b/syscared/src/args.rs index 71cdf95..4c28dff 100644 --- a/syscared/src/args.rs +++ b/syscared/src/args.rs @@ -22,6 +22,7 @@ use syscare_common::fs; use super::{DAEMON_ABOUT, DAEMON_NAME, DAEMON_VERSION}; +const DEFAULT_CONFIG_DIR: &str = "/etc/syscare"; const DEFAULT_DATA_ROOT: &str = "/usr/lib/syscare"; const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; const DEFAULT_LOG_DIR: &str = "/var/log/syscare"; @@ -42,6 +43,10 @@ pub struct Arguments { #[clap(short, long)] pub daemon: bool, + /// Daemon config directory + #[clap(long, default_value=DEFAULT_CONFIG_DIR)] + pub config_dir: PathBuf, + /// Daemon data directory #[clap(long, default_value = DEFAULT_DATA_ROOT)] pub data_dir: PathBuf, @@ -65,8 +70,9 @@ impl Arguments { } fn normalize_path(mut self) -> Result { - self.work_dir = fs::normalize(&self.work_dir)?; + self.config_dir = fs::normalize(&self.config_dir)?; self.data_dir = fs::normalize(&self.data_dir)?; + self.work_dir = fs::normalize(&self.work_dir)?; self.log_dir = fs::normalize(&self.log_dir)?; Ok(self) diff --git a/syscared/src/config.rs b/syscared/src/config.rs new file mode 100644 index 0000000..af98a51 --- /dev/null +++ b/syscared/src/config.rs @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Mulan PSL v2 +/* + * Copyright (c) 2024 Huawei Technologies Co., Ltd. + * upatchd is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +use std::path::Path; + +use anyhow::{anyhow, Result}; +use serde::{Deserialize, Serialize}; +use syscare_common::fs; + +const DEFAULT_SOCKET_UID: u32 = 0; +const DEFAULT_SOCKET_GID: u32 = 0; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SocketConfig { + pub uid: u32, + pub gid: u32, +} + +impl Default for SocketConfig { + fn default() -> Self { + Self { + uid: DEFAULT_SOCKET_UID, + gid: DEFAULT_SOCKET_GID, + } + } +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct DaemonConfig { + pub socket: SocketConfig, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct Config { + pub daemon: DaemonConfig, +} + +impl Config { + pub fn parse>(path: P) -> Result { + let config_path = path.as_ref(); + let instance = serde_yaml::from_reader(fs::open_file(config_path)?) + .map_err(|_| anyhow!("Failed to parse config {}", config_path.display()))?; + + Ok(instance) + } + + pub fn write>(&self, path: P) -> Result<()> { + let config_path = path.as_ref(); + let config_file = fs::create_file(config_path)?; + serde_yaml::to_writer(config_file, self) + .map_err(|_| anyhow!("Failed to write config {}", config_path.display()))?; + + Ok(()) + } +} + +#[test] +fn test() -> Result<()> { + use anyhow::{ensure, Context}; + use std::path::PathBuf; + + let tmp_file = PathBuf::from("/tmp/syscared.yaml"); + + let orig_cfg = Config::default(); + println!("{:#?}", orig_cfg); + + orig_cfg + .write(&tmp_file) + .context("Failed to write config")?; + + let new_cfg = Config::parse(tmp_file).context("Failed to read config")?; + println!("{:#?}", new_cfg); + + ensure!(orig_cfg == new_cfg, "Config does not match"); + + Ok(()) +} diff --git a/syscared/src/main.rs b/syscared/src/main.rs index 22f01df..b840abf 100644 --- a/syscared/src/main.rs +++ b/syscared/src/main.rs @@ -22,7 +22,8 @@ use flexi_logger::{ }; use jsonrpc_core::IoHandler; use jsonrpc_ipc_server::{Server, ServerBuilder}; -use log::{error, info, LevelFilter, Record}; +use log::{debug, error, info, warn, LevelFilter, Record}; +use nix::unistd::{chown, Gid, Uid}; use parking_lot::RwLock; use patch::manager::PatchManager; use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_name}; @@ -30,38 +31,45 @@ use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_nam use syscare_common::{fs, os}; mod args; +mod config; mod fast_reboot; mod patch; mod rpc; use args::Arguments; +use config::Config; +use patch::monitor::PatchMonitor; use rpc::{ skeleton::{FastRebootSkeleton, PatchSkeleton}, skeleton_impl::{FastRebootSkeletonImpl, PatchSkeletonImpl}, }; -use crate::patch::monitor::PatchMonitor; - const DAEMON_NAME: &str = env!("CARGO_PKG_NAME"); const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); const DAEMON_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); const DAEMON_UMASK: u32 = 0o077; +const CONFIG_FILE_NAME: &str = "syscared.yaml"; +const PID_FILE_NAME: &str = "syscared.pid"; +const SOCKET_FILE_NAME: &str = "syscared.sock"; + +const CONFIG_DIR_PERM: u32 = 0o700; const DATA_DIR_PERM: u32 = 0o700; const WORK_DIR_PERM: u32 = 0o755; const LOG_DIR_PERM: u32 = 0o700; -const PID_FILE_NAME: &str = "syscared.pid"; -const SOCKET_FILE_NAME: &str = "syscared.sock"; +const SOCKET_FILE_PERM: u32 = 0o660; +const SOCKET_FILE_PERM_STRICT: u32 = 0o600; const MAIN_THREAD_NAME: &str = "main"; const UNNAMED_THREAD_NAME: &str = ""; const LOG_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.6f"; -struct SyscareDaemon { +struct Daemon { args: Arguments, + config: Config, } -impl SyscareDaemon { +impl Daemon { fn format_log( w: &mut dyn std::io::Write, now: &mut DeferredNow, @@ -101,9 +109,11 @@ impl SyscareDaemon { os::umask::set_umask(DAEMON_UMASK); let args = Arguments::new()?; + fs::create_dir_all(&args.config_dir)?; fs::create_dir_all(&args.data_dir)?; fs::create_dir_all(&args.work_dir)?; fs::create_dir_all(&args.log_dir)?; + fs::set_permissions(&args.config_dir, Permissions::from_mode(CONFIG_DIR_PERM))?; fs::set_permissions(&args.data_dir, Permissions::from_mode(DATA_DIR_PERM))?; fs::set_permissions(&args.work_dir, Permissions::from_mode(WORK_DIR_PERM))?; fs::set_permissions(&args.log_dir, Permissions::from_mode(LOG_DIR_PERM))?; @@ -138,14 +148,29 @@ impl SyscareDaemon { .start() .context("Failed to initialize logger")?; + // Initialize config + debug!("Initializing configuation..."); + let config_file = args.config_dir.join(CONFIG_FILE_NAME); + let config = match Config::parse(&config_file) { + Ok(config) => config, + Err(e) => { + warn!("{:?}", e); + info!("Using default configuration..."); + let config = Config::default(); + config.write(&config_file)?; + + config + } + }; + // Print panic to log incase it really happens panic::set_hook(Box::new(|info| error!("{}", info))); - Ok(Self { args }) + Ok(Self { args, config }) } } -impl SyscareDaemon { +impl Daemon { fn daemonize(&self) -> Result<()> { if !self.args.daemon { return Ok(()); @@ -171,13 +196,24 @@ impl SyscareDaemon { fn start_rpc_server(&self, io_handler: IoHandler) -> Result { let socket_file = self.args.work_dir.join(SOCKET_FILE_NAME); - let server = ServerBuilder::new(io_handler) - .set_client_buffer_size(1) - .start( - socket_file - .to_str() - .context("Failed to convert socket path to string")?, - )?; + let builder = ServerBuilder::new(io_handler).set_client_buffer_size(1); + let server = builder.start( + socket_file + .to_str() + .context("Failed to convert socket path to string")?, + )?; + + let socket_owner = Uid::from_raw(self.config.daemon.socket.uid); + let socket_group = Gid::from_raw(self.config.daemon.socket.gid); + chown(&socket_file, Some(socket_owner), Some(socket_group))?; + + fs::set_permissions( + &socket_file, + match socket_owner.as_raw() == socket_group.as_raw() { + true => Permissions::from_mode(SOCKET_FILE_PERM_STRICT), + false => Permissions::from_mode(SOCKET_FILE_PERM), + }, + )?; Ok(server) } @@ -227,7 +263,7 @@ impl SyscareDaemon { } fn main() { - let daemon = match SyscareDaemon::new() { + let daemon = match Daemon::new() { Ok(instance) => instance, Err(e) => { eprintln!("Error: {:?}", e); diff --git a/upatchd/Cargo.toml b/upatchd/Cargo.toml index dd9f5ca..fea0859 100644 --- a/upatchd/Cargo.toml +++ b/upatchd/Cargo.toml @@ -14,7 +14,7 @@ anyhow = { version = "1.0" } clap = { version = "3.2", features = ["cargo", "derive"] } daemonize = { version = "0.5" } flexi_logger = { version = "0.24", features = ["compress"] } -indexmap = { version = "1.9" } +indexmap = { version = "1.9", features = ["serde"] } jsonrpc-core = { version = "18.0" } jsonrpc-derive = { version = "18.0" } jsonrpc-ipc-server = { version = "18.0" } diff --git a/upatchd/src/config.rs b/upatchd/src/config.rs new file mode 100644 index 0000000..125770d --- /dev/null +++ b/upatchd/src/config.rs @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: Mulan PSL v2 +/* + * Copyright (c) 2024 Huawei Technologies Co., Ltd. + * upatchd is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +use std::path::Path; + +use anyhow::{anyhow, Result}; +use serde::{Deserialize, Serialize}; +use syscare_common::fs; + +use crate::hijacker::HijackerConfig; + +const DEFAULT_SOCKET_UID: u32 = 0; +const DEFAULT_SOCKET_GID: u32 = 0; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SocketConfig { + pub uid: u32, + pub gid: u32, +} + +impl Default for SocketConfig { + fn default() -> Self { + Self { + uid: DEFAULT_SOCKET_UID, + gid: DEFAULT_SOCKET_GID, + } + } +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct DaemonConfig { + pub socket: SocketConfig, +} + +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct Config { + pub daemon: DaemonConfig, + pub hijacker: HijackerConfig, +} + +impl Config { + pub fn parse>(path: P) -> Result { + let config_path = path.as_ref(); + let instance = serde_yaml::from_reader(fs::open_file(config_path)?) + .map_err(|_| anyhow!("Failed to parse config {}", config_path.display()))?; + + Ok(instance) + } + + pub fn write>(&self, path: P) -> Result<()> { + let config_path = path.as_ref(); + let config_file = fs::create_file(config_path)?; + serde_yaml::to_writer(config_file, self) + .map_err(|_| anyhow!("Failed to write config {}", config_path.display()))?; + + Ok(()) + } +} + +#[test] +fn test() -> Result<()> { + use anyhow::{ensure, Context}; + use std::path::PathBuf; + + let tmp_file = PathBuf::from("/tmp/upatchd.yaml"); + + let orig_cfg = Config::default(); + println!("{:#?}", orig_cfg); + + orig_cfg + .write(&tmp_file) + .context("Failed to write config")?; + + let new_cfg = Config::parse(tmp_file).context("Failed to read config")?; + println!("{:#?}", new_cfg); + + ensure!(orig_cfg == new_cfg, "Config does not match"); + + Ok(()) +} diff --git a/upatchd/src/hijacker/config.rs b/upatchd/src/hijacker/config.rs index f96cc05..5f97fb1 100644 --- a/upatchd/src/hijacker/config.rs +++ b/upatchd/src/hijacker/config.rs @@ -12,15 +12,10 @@ * See the Mulan PSL v2 for more details. */ -use std::{ - collections::HashMap, - ops::Deref, - path::{Path, PathBuf}, -}; +use std::path::PathBuf; -use anyhow::{anyhow, Result}; +use indexmap::{indexmap, IndexMap}; use serde::{Deserialize, Serialize}; -use syscare_common::fs; const CC_BINARY: &str = "/usr/bin/cc"; const CXX_BINARY: &str = "/usr/bin/c++"; @@ -34,73 +29,21 @@ const GCC_HIJACKER: &str = "/usr/libexec/syscare/gcc-hijacker"; const GXX_HIJACKER: &str = "/usr/libexec/syscare/g++-hijacker"; const AS_HIJACKER: &str = "/usr/libexec/syscare/as-hijacker"; -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct HijackerConfig(HashMap); - -impl HijackerConfig { - pub fn parse_from>(path: P) -> Result { - let config_path = path.as_ref(); - let config_file = fs::open_file(config_path)?; - let instance: Self = serde_yaml::from_reader(config_file) - .map_err(|_| anyhow!("Failed to parse config {}", config_path.display()))?; - - Ok(instance) - } - - pub fn write_to>(&self, path: P) -> Result<()> { - let config_path = path.as_ref(); - let config_file = fs::create_file(config_path)?; - serde_yaml::to_writer(config_file, self) - .map_err(|_| anyhow!("Failed to write config {}", config_path.display()))?; - - Ok(()) - } -} - -impl Deref for HijackerConfig { - type Target = HashMap; - - fn deref(&self) -> &Self::Target { - &self.0 - } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct HijackerConfig { + pub mapping: IndexMap, } impl Default for HijackerConfig { fn default() -> Self { - let mut map = HashMap::new(); - map.insert(PathBuf::from(CC_BINARY), PathBuf::from(CC_HIJACKER)); - map.insert(PathBuf::from(CXX_BINARY), PathBuf::from(CXX_HIJACKER)); - map.insert(PathBuf::from(GCC_BINARY), PathBuf::from(GCC_HIJACKER)); - map.insert(PathBuf::from(GXX_BINARY), PathBuf::from(GXX_HIJACKER)); - map.insert(PathBuf::from(AS_BINARY), PathBuf::from(AS_HIJACKER)); - - Self(map) + Self { + mapping: indexmap! { + PathBuf::from(CC_BINARY) => PathBuf::from(CC_HIJACKER), + PathBuf::from(CXX_BINARY) => PathBuf::from(CXX_HIJACKER), + PathBuf::from(GCC_BINARY) => PathBuf::from(GCC_HIJACKER), + PathBuf::from(GXX_BINARY) => PathBuf::from(GXX_HIJACKER), + PathBuf::from(AS_BINARY) => PathBuf::from(AS_HIJACKER), + }, + } } } - -impl std::fmt::Display for HijackerConfig { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("{:#?}", &self.0)) - } -} - -#[test] -fn test() -> Result<()> { - use anyhow::{ensure, Context}; - - let tmp_file = PathBuf::from("/tmp/upatch_hijacker_config.yaml"); - - let orig_cfg = HijackerConfig::default(); - println!("{}", orig_cfg); - - orig_cfg - .write_to(&tmp_file) - .context("Failed to write config")?; - - let new_cfg = HijackerConfig::parse_from(tmp_file).context("Failed to read config")?; - println!("{}", new_cfg); - - ensure!(orig_cfg == new_cfg, "Config does not match"); - - Ok(()) -} diff --git a/upatchd/src/hijacker/mod.rs b/upatchd/src/hijacker/mod.rs index 8ac12e7..d0f2c4d 100644 --- a/upatchd/src/hijacker/mod.rs +++ b/upatchd/src/hijacker/mod.rs @@ -12,7 +12,6 @@ * See the Mulan PSL v2 for more details. */ -use std::os::unix::prelude::MetadataExt; use std::path::{Path, PathBuf}; use anyhow::{bail, Context, Result}; @@ -25,14 +24,14 @@ mod elf_resolver; mod ioctl; mod kmod; -use config::HijackerConfig; +pub use config::HijackerConfig; use elf_resolver::ElfResolver; use ioctl::HijackerIoctl; use kmod::HijackerKmodGuard; const KMOD_NAME: &str = "upatch_hijacker"; const KMOD_DEV_PATH: &str = "/dev/upatch-hijacker"; -const KMOD_FILE_PATH: &str = "/usr/libexec/syscare/upatch_hijacker.ko"; +const KMOD_PATH: &str = "/usr/libexec/syscare/upatch_hijacker.ko"; const HIJACK_SYMBOL_NAME: &str = "execve"; @@ -43,36 +42,6 @@ pub struct Hijacker { } impl Hijacker { - fn initialize_config>(config_path: P) -> Result { - const MODE_EXEC_MASK: u32 = 0o111; - - let config = match config_path.as_ref().exists() { - true => HijackerConfig::parse_from(config_path)?, - false => { - info!("Generating default configuration..."); - let config = HijackerConfig::default(); - config.write_to(config_path)?; - - config - } - }; - - for hijacker in config.values() { - let is_executable_file = hijacker - .symlink_metadata() - .map(|m| m.is_file() && (m.mode() & MODE_EXEC_MASK != 0)) - .with_context(|| format!("Failed to read {} metadata", hijacker.display()))?; - if !is_executable_file { - bail!( - "Hijack program {} is not an executable file", - hijacker.display() - ); - } - } - - Ok(config) - } - fn find_symbol_addr(symbol_name: &str) -> Result<(PathBuf, u64)> { let exec_file = MappedFile::open(os::process::path())?; let exec_resolver = ElfResolver::new(exec_file.as_bytes())?; @@ -91,14 +60,9 @@ impl Hijacker { } impl Hijacker { - pub fn new>(config_path: P) -> Result { - debug!("Initializing hijacker configuation..."); - let config = Self::initialize_config(config_path) - .context("Failed to initialize hijacker configuration")?; - info!("Using elf mapping: {}", config); - + pub fn new(config: HijackerConfig) -> Result { debug!("Initializing hijacker kernel module..."); - let kmod = HijackerKmodGuard::new(KMOD_NAME, KMOD_FILE_PATH)?; + let kmod = HijackerKmodGuard::new(KMOD_NAME, KMOD_PATH)?; debug!("Initializing hijacker ioctl channel..."); let ioctl = HijackerIoctl::new(KMOD_DEV_PATH)?; @@ -113,9 +77,9 @@ impl Hijacker { ioctl.enable_hijacker(lib_path, offset)?; Ok(Self { + config, _kmod: kmod, ioctl, - config, }) } } @@ -124,6 +88,7 @@ impl Hijacker { fn get_hijacker>(&self, exec_path: P) -> Result<&Path> { let hijacker = self .config + .mapping .get(exec_path.as_ref()) .with_context(|| format!("Cannot find hijacker for {}", exec_path.as_ref().display()))? .as_path(); diff --git a/upatchd/src/main.rs b/upatchd/src/main.rs index 1007ebb..066e53e 100644 --- a/upatchd/src/main.rs +++ b/upatchd/src/main.rs @@ -22,16 +22,19 @@ use flexi_logger::{ }; use jsonrpc_core::IoHandler; use jsonrpc_ipc_server::{Server, ServerBuilder}; -use log::{error, info, LevelFilter, Record}; +use log::{debug, error, info, warn, LevelFilter, Record}; +use nix::unistd::{chown, Gid, Uid}; use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_name}; use syscare_common::{fs, os}; mod args; +mod config; mod hijacker; mod rpc; use args::Arguments; +use config::Config; use rpc::{Skeleton, SkeletonImpl}; const DAEMON_NAME: &str = env!("CARGO_PKG_NAME"); @@ -46,17 +49,19 @@ const SOCKET_FILE_NAME: &str = "upatchd.sock"; const CONFIG_DIR_PERM: u32 = 0o700; const WORK_DIR_PERM: u32 = 0o755; const LOG_DIR_PERM: u32 = 0o700; -const SOCKET_FILE_PERM: u32 = 0o666; +const SOCKET_FILE_PERM: u32 = 0o660; +const SOCKET_FILE_PERM_STRICT: u32 = 0o600; const MAIN_THREAD_NAME: &str = "main"; const UNNAMED_THREAD_NAME: &str = ""; const LOG_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.6f"; -struct UpatchDaemon { +struct Daemon { args: Arguments, + config: Config, } -impl UpatchDaemon { +impl Daemon { fn format_log( w: &mut dyn std::io::Write, now: &mut DeferredNow, @@ -133,14 +138,28 @@ impl UpatchDaemon { .start() .context("Failed to initialize logger")?; + // Initialize config + debug!("Initializing configuation..."); + let config_file = args.config_dir.join(CONFIG_FILE_NAME); + let config = match Config::parse(&config_file) { + Ok(config) => config, + Err(e) => { + warn!("{:?}", e); + info!("Using default configuration..."); + let config = Config::default(); + config.write(&config_file)?; + + config + } + }; + // Print panic to log incase it really happens panic::set_hook(Box::new(|info| error!("{}", info))); - - Ok(Self { args }) + Ok(Self { args, config }) } } -impl UpatchDaemon { +impl Daemon { fn daemonize(&self) -> Result<()> { if !self.args.daemon { return Ok(()); @@ -156,10 +175,11 @@ impl UpatchDaemon { } fn initialize_skeleton(&self) -> Result { - let mut io_handler = IoHandler::new(); + let config = self.config.hijacker.clone(); + let methods = SkeletonImpl::new(config)?.to_delegate(); - let config_file = self.args.config_dir.join(CONFIG_FILE_NAME); - io_handler.extend_with(SkeletonImpl::new(config_file)?.to_delegate()); + let mut io_handler = IoHandler::new(); + io_handler.extend_with(methods); Ok(io_handler) } @@ -173,7 +193,17 @@ impl UpatchDaemon { .context("Failed to convert socket path to string")?, )?; - fs::set_permissions(&socket_file, Permissions::from_mode(SOCKET_FILE_PERM))?; + let socket_owner = Uid::from_raw(self.config.daemon.socket.uid); + let socket_group = Gid::from_raw(self.config.daemon.socket.gid); + chown(&socket_file, Some(socket_owner), Some(socket_group))?; + + fs::set_permissions( + &socket_file, + match socket_owner.as_raw() == socket_group.as_raw() { + true => Permissions::from_mode(SOCKET_FILE_PERM_STRICT), + false => Permissions::from_mode(SOCKET_FILE_PERM), + }, + )?; Ok(server) } @@ -183,6 +213,7 @@ impl UpatchDaemon { info!("Upatch Daemon - {}", DAEMON_VERSION); info!("================================"); info!("Start with {:#?}", self.args); + info!("Using {:#?}", self.config); self.daemonize()?; info!("Initializing skeleton..."); @@ -213,7 +244,7 @@ impl UpatchDaemon { } fn main() { - let daemon = match UpatchDaemon::new() { + let daemon = match Daemon::new() { Ok(instance) => instance, Err(e) => { eprintln!("Error: {:?}", e); diff --git a/upatchd/src/rpc/skeleton_impl.rs b/upatchd/src/rpc/skeleton_impl.rs index a334120..d725166 100644 --- a/upatchd/src/rpc/skeleton_impl.rs +++ b/upatchd/src/rpc/skeleton_impl.rs @@ -12,12 +12,12 @@ * See the Mulan PSL v2 for more details. */ -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use anyhow::{Context, Result}; use log::{debug, info}; -use crate::hijacker::Hijacker; +use crate::hijacker::{Hijacker, HijackerConfig}; use super::{ function::{RpcFunction, RpcResult}, @@ -29,10 +29,10 @@ pub struct SkeletonImpl { } impl SkeletonImpl { - pub fn new>(config_path: P) -> Result { + pub fn new(config: HijackerConfig) -> Result { debug!("Initializing hijacker..."); Ok(Self { - hijacker: Hijacker::new(config_path).context("Failed to initialize hijacker")?, + hijacker: Hijacker::new(config).context("Failed to initialize hijacker")?, }) } } -- 2.34.1