From 244069cf43c28ee017959116430ec480b434dbd0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Mon, 9 Oct 2017 20:12:08 -0600 Subject: [PATCH] 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 887828cc..74f0e492 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 e718196f..4351262d 100644 --- a/src/syscall/privilege.rs +++ b/src/syscall/privilege.rs @@ -73,25 +73,51 @@ pub fn setregid(rgid: u32, egid: u32) -> Result<usize> { 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<usize> { @@ -99,25 +125,63 @@ pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> { 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<usize> { @@ -125,23 +189,49 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> { 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) } -- GitLab