From 244069cf43c28ee017959116430ec480b434dbd0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Oct 2017 20:12:08 -0600 Subject: [PATCH 1/2] Implement a capability namespace with no available schemes --- src/scheme/mod.rs | 3 +- src/syscall/privilege.rs | 198 ++++++++++++++++++++++++++++----------- 2 files changed, 146 insertions(+), 55 deletions(-) diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 887828c..74f0e49 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -99,7 +99,8 @@ impl SchemeList { let mut list = SchemeList { map: BTreeMap::new(), names: BTreeMap::new(), - next_ns: 0, + // Scheme namespaces always start at 1. 0 is a reserved namespace, the null namespace + next_ns: 1, next_id: 1 }; list.new_root(); diff --git a/src/syscall/privilege.rs b/src/syscall/privilege.rs index e718196..4351262 100644 --- a/src/syscall/privilege.rs +++ b/src/syscall/privilege.rs @@ -73,25 +73,51 @@ pub fn setregid(rgid: u32, egid: u32) -> Result { let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let mut context = context_lock.write(); - if (context.euid == 0 - || rgid as i32 == -1 - || rgid == context.egid - || rgid == context.rgid) - && (context.euid == 0 - || egid as i32 == -1 - || egid == context.egid - || egid == context.rgid) - { - if rgid as i32 != -1 { - context.rgid = rgid; - } - if egid as i32 != -1 { - context.egid = egid; - } - Ok(0) - } else { - Err(Error::new(EPERM)) + let setrgid = + if context.euid == 0 { + // Allow changing RGID if root + true + } else if rgid == context.egid { + /// Allow changing RGID if used for EGID + true + } else if rgid == context.rgid { + /// Allow changing RGID if used for RGID + true + } else if rgid as i32 == -1 { + // Ignore RGID if -1 is passed + false + } else { + // Not permitted otherwise + return Err(Error::new(EPERM)); + }; + + let setegid = + if context.euid == 0 { + // Allow changing EGID if root + true + } else if egid == context.egid { + /// Allow changing EGID if used for EGID + true + } else if egid == context.rgid { + /// Allow changing EGID if used for RGID + true + } else if egid as i32 == -1 { + // Ignore EGID if -1 is passed + false + } else { + // Not permitted otherwise + return Err(Error::new(EPERM)); + }; + + if setrgid { + context.rgid = rgid; } + + if setegid { + context.egid = egid; + } + + Ok(0) } pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { @@ -99,25 +125,63 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let mut context = context_lock.write(); - if (context.euid == 0 - || rns.into() as isize == -1 - || rns == context.ens - || rns == context.rns) - && (context.euid == 0 - || ens.into() as isize == -1 - || ens == context.ens - || ens == context.rns) - { - if rns.into() as isize != -1 { - context.rns = rns; - } - if ens.into() as isize != -1 { - context.ens = ens; - } - Ok(0) - } else { - Err(Error::new(EPERM)) + let setrns = + if rns.into() == 0 { + // Allow entering capability mode + true + } else if context.rns.into() == 0 { + // Do not allow leaving capability mode + return Err(Error::new(EPERM)); + } else if context.euid == 0 { + // Allow setting RNS if root + true + } else if rns == context.ens { + // Allow setting RNS if used for ENS + true + } else if rns == context.rns { + // Allow setting RNS if used for RNS + true + } else if rns.into() as isize == -1 { + // Ignore RNS if -1 is passed + false + } else { + // Not permitted otherwise + return Err(Error::new(EPERM)); + }; + + let setens = + if ens.into() == 0 { + // Allow entering capability mode + true + } else if context.ens.into() == 0 { + // Do not allow leaving capability mode + return Err(Error::new(EPERM)); + } else if context.euid == 0 { + // Allow setting ENS if root + true + } else if ens == context.ens { + // Allow setting ENS if used for ENS + true + } else if ens == context.rns { + // Allow setting ENS if used for RNS + true + } else if ens.into() as isize == -1 { + // Ignore ENS if -1 is passed + false + } else { + // Not permitted otherwise + return Err(Error::new(EPERM)); + }; + + if setrns { + context.rns = rns; } + + if setens { + context.ens = ens; + } + + Ok(0) } pub fn setreuid(ruid: u32, euid: u32) -> Result { @@ -125,23 +189,49 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result { let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let mut context = context_lock.write(); - if (context.euid == 0 - || ruid as i32 == -1 - || ruid == context.euid - || ruid == context.ruid) - && (context.euid == 0 - || euid as i32 == -1 - || euid == context.euid - || euid == context.ruid) - { - if ruid as i32 != -1 { - context.ruid = ruid; - } - if euid as i32 != -1 { - context.euid = euid; - } - Ok(0) - } else { - Err(Error::new(EPERM)) + let setruid = + if context.euid == 0 { + // Allow setting RUID if root + true + } else if ruid == context.euid { + // Allow setting RUID if used for EUID + true + } else if ruid == context.ruid { + // Allow setting RUID if used for RUID + true + } else if ruid as i32 == -1 { + // Ignore RUID if -1 is passed + false + } else { + // Not permitted otherwise + return Err(Error::new(EPERM)); + }; + + let seteuid = + if context.euid == 0 { + // Allow setting EUID if root + true + } else if euid == context.euid { + // Allow setting EUID if used for EUID + true + } else if euid == context.ruid { + // Allow setting EUID if used for RUID + true + } else if euid as i32 == -1 { + // Ignore EUID if -1 is passed + false + } else { + // Not permitted otherwise + return Err(Error::new(EPERM)); + }; + + if setruid { + context.ruid = ruid; } + + if seteuid { + context.euid = euid; + } + + Ok(0) } From e07c3ac0b95ad7510bbe3c08a38f55803ce45710 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Oct 2017 20:20:38 -0600 Subject: [PATCH 2/2] Set init namespace to 1 --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 56ec8f1..ffde36a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,7 @@ use alloc::arc::Arc; use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use spin::Mutex; -use scheme::FileHandle; +use scheme::{FileHandle, SchemeNamespace}; pub use consts::*; @@ -146,6 +146,8 @@ pub fn kmain(cpus: usize, env: &[u8]) -> ! { match context::contexts_mut().spawn(userspace_init) { Ok(context_lock) => { let mut context = context_lock.write(); + context.rns = SchemeNamespace::from(1); + context.ens = SchemeNamespace::from(1); context.status = context::Status::Runnable; let mut context_env = context.env.lock();