From bb8de3b6c7fdbc3c4e89208d2965a0104de0e316 Mon Sep 17 00:00:00 2001 From: Albert S Date: Thu, 22 Aug 2019 13:08:50 +0200 Subject: [PATCH] also set dumpable to 0, minor improvements --- Cargo.lock | 2 ++ src/main.rs | 79 ++++++++++++++++++++--------------------------------- 2 files changed, 32 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d9169f..a01c3b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "libc" version = "0.2.43" diff --git a/src/main.rs b/src/main.rs index e9b5c2f..3b84dcd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ use std::env::Args; -use std::io::{Error, ErrorKind}; -use std::fs::File; -use std::io::BufReader; -use std::io::BufRead; -use std::ffi::CString; use std::ffi::CStr; +use std::ffi::CString; +use std::fs::File; +use std::io::BufRead; +use std::io::BufReader; +use std::io::{Error, ErrorKind}; extern crate libc; use libc::passwd; @@ -35,7 +35,6 @@ impl Entry { } } - struct Passwd { pw_name: String, pw_passwd: String, @@ -46,15 +45,11 @@ struct Passwd { pw_shell: String, } - fn initgroups(user: &str, group: libc::gid_t) -> std::io::Result<()> { let userarg = CString::new(user); - return errnowrapper(unsafe { - libc::initgroups(userarg.unwrap().as_ptr(), group) - }); + return errnowrapper(unsafe { libc::initgroups(userarg.unwrap().as_ptr(), group) }); } - fn errnowrapper(ret: libc::c_int) -> std::io::Result<()> { if ret != 0 { return Err(Error::last_os_error()); @@ -95,7 +90,6 @@ fn getpwnam(username: &str) -> std::io::Result { pw_shell: getstr((*pwnamresult).pw_shell), }) } - } fn ensure_allowed(userid: libc::uid_t, entry: &Entry) -> std::io::Result<()> { @@ -119,7 +113,6 @@ fn ensure_allowed(userid: libc::uid_t, entry: &Entry) -> std::io::Result<()> { )); } - fn usage() { println!("Usage: raou ENRTYNAME"); } @@ -141,13 +134,12 @@ fn assign(entry: &mut Entry, key: &str, value: &str) { "env_vars" => add_multi(&mut entry.inherit_envs, val), "argv0" => entry.argv0 = val, "target_user" => entry.dest_user = val, - "allow_args" => entry.arbitrary_args = (val == "1" || val == "true"), + "allow_args" => entry.arbitrary_args = val == "1" || val == "true", "args" => entry.args = val, - "no_new_privs" => entry.no_new_privs = (val == "1" || val == "true"), + "no_new_privs" => entry.no_new_privs = val == "1" || val == "true", _ => { eprintln!("Ignoring invalid key {}", key); } - } } fn assign_from_line(entry: &mut Entry, line: &str) { @@ -159,7 +151,6 @@ fn assign_from_line(entry: &mut Entry, line: &str) { return; } assign(entry, key.unwrap(), value.unwrap()) - } fn create_entry_from_file(filepath: &str) -> std::io::Result { let mut entry: Entry = Entry::new(); @@ -179,7 +170,8 @@ fn clearenv() -> std::io::Result<()> { } //TODO: AsRef for envs? fn setup_environment(passwd: &Passwd, envs: &[String]) -> std::io::Result<()> { - let saved_envs: Vec = envs.iter() + let saved_envs: Vec = envs + .iter() .map(|s| std::env::var(s).expect("No such var")) .collect(); clearenv()?; @@ -194,7 +186,6 @@ fn setup_environment(passwd: &Passwd, envs: &[String]) -> std::io::Result<()> { std::env::set_var(&envs[i], item); } Ok(()) - } fn become_user(passwd: &Passwd) -> std::io::Result<()> { @@ -204,13 +195,12 @@ fn become_user(passwd: &Passwd) -> std::io::Result<()> { std::env::set_current_dir(&passwd.pw_dir)?; Ok(()) } -fn init_sandbox(entry: &Entry) -> std::io::Result<()> { - if (entry.no_new_privs) { - errnowrapper(unsafe { - libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) - })?; - } +fn drop_privs(entry: &Entry) -> std::io::Result<()> { + if entry.no_new_privs { + errnowrapper(unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0) })?; + errnowrapper(unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) })?; + } Ok(()) } @@ -220,8 +210,6 @@ fn to_cstring>(s: T) -> *const libc::c_char { } fn create_execv_args(entry: &Entry, cmdargs: &Vec) -> Vec<*const libc::c_char> { - - let mut args: Vec<*const libc::c_char>; if entry.arbitrary_args && cmdargs.len() > 2 { args = cmdargs.iter().skip(2).map(to_cstring).collect(); @@ -256,11 +244,8 @@ fn exec(entryname: &str, cmdargs: &Vec) -> std::io::Result<()> { let destuserpasswd: Passwd = getpwnam(&entry.dest_user)?; let currentuser: u32 = geteuid(); - let args = create_execv_args(&entry, &cmdargs); - - ensure_allowed(currentuser, &entry)?; become_user(&destuserpasswd).or_else(|e| { return Err(Error::new( @@ -268,39 +253,35 @@ fn exec(entryname: &str, cmdargs: &Vec) -> std::io::Result<()> { "Failed to switch user: ".to_owned() + &e.to_string(), )); })?; - setup_environment(&destuserpasswd, &entry.inherit_envs) - .or_else(|e| { - return Err(Error::new( - ErrorKind::Other, - "Environment setup failure: ".to_owned() + &e.to_string(), - )); - })?; - init_sandbox(&entry).or_else(|e| { + setup_environment(&destuserpasswd, &entry.inherit_envs).or_else(|e| { return Err(Error::new( ErrorKind::Other, - "Sandbox init failure: ".to_owned() + &e.to_string(), + "Environment setup failure: ".to_owned() + &e.to_string(), + )); + })?; + + drop_privs(&entry).or_else(|e| { + return Err(Error::new( + ErrorKind::Other, + "Failed to drop priviliges: ".to_owned() + &e.to_string(), )); })?; unsafe { - errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr())) - .or_else(|e| { - return Err(Error::new( - ErrorKind::Other, - "execv failed: ".to_owned() + &e.to_string(), - )); - })?; + errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr())).or_else(|e| { + return Err(Error::new( + ErrorKind::Other, + "execv failed: ".to_owned() + &e.to_string(), + )); + })?; } std::process::exit(0); - Ok(()) } fn main() -> Result<(), std::io::Error> { - let argv: Args = std::env::args(); let cmdargs: Vec = argv.collect(); let entryname = cmdargs.get(1); if entryname.is_some() { - match exec(&entryname.unwrap(), &cmdargs) { Err(e) => { eprintln!("The following error ocurred:");