Elimited Daemonize dependency

This commit is contained in:
Mathias Hall-Andersen
2020-05-17 22:07:59 +02:00
parent 8d53b0f5c1
commit 16f21989b4
5 changed files with 117 additions and 37 deletions

View File

@@ -13,9 +13,9 @@ mod configuration;
mod platform;
mod wireguard;
use log;
mod util;
use daemonize::Daemonize;
use log;
use std::env;
use std::process::exit;
@@ -62,14 +62,14 @@ fn main() {
let mut foreground = false;
let mut args = env::args();
args.next(); // skip path (argv[0])
// skip path (argv[0])
args.next();
for arg in args {
match arg.as_str() {
"--foreground" | "-f" => {
foreground = true;
}
"--root" => {
"--disable-drop-privileges" => {
drop_privileges = false;
}
dev => name = Some(dev.to_owned()),
@@ -97,16 +97,26 @@ fn main() {
exit(-3);
});
// daemonize
// drop privileges
if drop_privileges {
match util::drop_privileges() {
Ok(_) => (),
Err(e) => {
eprintln!("Failed to drop privileges: {}", e);
exit(-4);
}
}
}
// daemonize to background
if !foreground {
let daemonize = Daemonize::new()
.pid_file(format!("/tmp/wireguard-rs-{}.pid", name))
.chown_pid_file(true)
.working_directory("/tmp")
.user("nobody")
.group("daemon")
.umask(0o777);
daemonize.start().expect("Failed to daemonize");
match util::daemonize() {
Ok(_) => (),
Err(e) => {
eprintln!("Failed to daemonize: {}", e);
exit(-5);
}
}
}
// start logging
@@ -114,10 +124,7 @@ fn main() {
.try_init()
.expect("Failed to initialize event logger");
log::info!("starting {} wireguard device", name);
// drop privileges
if drop_privileges {}
log::info!("Starting {} WireGuard device.", name);
// start profiler (if enabled)
#[cfg(feature = "profiler")]

86
src/util.rs Normal file
View File

@@ -0,0 +1,86 @@
use std::fmt;
use std::process::exit;
use libc::{c_char, chdir, chroot, fork, getpwnam, getuid, setgid, setsid, setuid, umask};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum DaemonizeError {
Fork,
SetSession,
SetGroup,
SetUser,
Chroot,
Chdir,
}
impl fmt::Display for DaemonizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
DaemonizeError::Fork => "unable to fork",
DaemonizeError::SetSession => "unable to create new process session",
DaemonizeError::SetGroup => "unable to set group (drop privileges)",
DaemonizeError::SetUser => "unable to set user (drop privileges)",
DaemonizeError::Chroot => "unable to enter chroot jail",
DaemonizeError::Chdir => "failed to change directory",
}
.fmt(f)
}
}
fn fork_and_exit() -> Result<(), DaemonizeError> {
let pid = unsafe { fork() };
if pid < 0 {
Err(DaemonizeError::Fork)
} else if pid == 0 {
Ok(())
} else {
exit(0);
}
}
pub fn daemonize() -> Result<(), DaemonizeError> {
// fork from the original parent
fork_and_exit()?;
// avoid killing the child when this parent dies
if unsafe { setsid() } < 0 {
return Err(DaemonizeError::SetSession);
}
// fork again to create orphan
fork_and_exit()
}
pub fn drop_privileges() -> Result<(), DaemonizeError> {
// retrieve nobody's uid & gid
let usr = unsafe { getpwnam("nobody\x00".as_ptr() as *const c_char) };
if usr.is_null() {
return Err(DaemonizeError::SetGroup);
}
// change root directory
let uid = unsafe { getuid() };
if uid == 0 && unsafe { chroot("/tmp\x00".as_ptr() as *const c_char) } != 0 {
return Err(DaemonizeError::Chroot);
}
// set umask for files
unsafe { umask(0) };
// change directory
if unsafe { chdir("/\x00".as_ptr() as *const c_char) } != 0 {
return Err(DaemonizeError::Chdir);
}
// set group id to nobody
if unsafe { setgid((*usr).pw_gid) } != 0 {
return Err(DaemonizeError::SetGroup);
}
// set user id to nobody
if unsafe { setuid((*usr).pw_uid) } != 0 {
Err(DaemonizeError::SetUser)
} else {
Ok(())
}
}