diff --git a/kernel/context/context.rs b/kernel/context/context.rs index 5e053ca..a7d41d4 100644 --- a/kernel/context/context.rs +++ b/kernel/context/context.rs @@ -34,10 +34,14 @@ pub struct Context { pub ruid: u32, /// The real group id pub rgid: u32, + /// The real namespace id + pub rns: SchemeNamespace, /// The effective user id pub euid: u32, /// The effective group id pub egid: u32, + /// The effective namespace id + pub ens: SchemeNamespace, /// Status of context pub status: Status, /// Context running or not @@ -70,8 +74,6 @@ pub struct Context { pub grants: Arc>>, /// The name of the context pub name: Arc>>, - /// The scheme namespace of this context - pub scheme_ns: SchemeNamespace, /// The current working directory pub cwd: Arc>>, /// Kernel events @@ -89,8 +91,10 @@ impl Context { ppid: ContextId::from(0), ruid: 0, rgid: 0, + rns: SchemeNamespace::from(0), euid: 0, egid: 0, + ens: SchemeNamespace::from(0), status: Status::Blocked, running: false, cpu_id: None, @@ -107,7 +111,6 @@ impl Context { tls: None, grants: Arc::new(Mutex::new(Vec::new())), name: Arc::new(Mutex::new(Vec::new())), - scheme_ns: SchemeNamespace::from(0), cwd: Arc::new(Mutex::new(Vec::new())), events: Arc::new(WaitQueue::new()), env: Arc::new(Mutex::new(BTreeMap::new())), diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index 1c2fbd2..abb9e12 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -141,7 +141,7 @@ impl SchemeList { self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap(); } - pub fn setns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result { + pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result { // Create an empty namespace let to = self.new_ns(); diff --git a/kernel/scheme/sys/context.rs b/kernel/scheme/sys/context.rs index 26e3e2d..a28820d 100644 --- a/kernel/scheme/sys/context.rs +++ b/kernel/scheme/sys/context.rs @@ -5,17 +5,18 @@ use context; use syscall::error::Result; pub fn resource() -> Result> { - let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<6}{}\n", + let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", "PID", "PPID", "RUID", "RGID", + "RNS", "EUID", "EGID", + "ENS", "STAT", "CPU", "MEM", - "SNS", "NAME"); { let contexts = context::contexts(); @@ -85,17 +86,18 @@ pub fn resource() -> Result> { let name_bytes = context.name.lock(); let name = str::from_utf8(&name_bytes).unwrap_or(""); - string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<6}{}\n", + string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", context.id.into(), context.ppid.into(), context.ruid, context.rgid, + context.rns.into(), context.euid, context.egid, + context.ens.into(), stat_string, cpu_string, memory_string, - context.scheme_ns.into(), name)); } } diff --git a/kernel/scheme/sys/scheme.rs b/kernel/scheme/sys/scheme.rs index 04df3d3..b0f0c7d 100644 --- a/kernel/scheme/sys/scheme.rs +++ b/kernel/scheme/sys/scheme.rs @@ -9,7 +9,7 @@ pub fn resource() -> Result> { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - context.scheme_ns + context.ens }; let mut data = Vec::new(); diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index 12d1885..30bd291 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -86,7 +86,7 @@ pub fn open(path: &[u8], flags: usize) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.scheme_ns) + (context.canonicalize(path), context.euid, context.egid, context.ens) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); @@ -150,7 +150,7 @@ pub fn mkdir(path: &[u8], mode: u16) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.scheme_ns) + (context.canonicalize(path), context.euid, context.egid, context.ens) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); @@ -172,7 +172,7 @@ pub fn chmod(path: &[u8], mode: u16) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.scheme_ns) + (context.canonicalize(path), context.euid, context.egid, context.ens) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); @@ -194,7 +194,7 @@ pub fn rmdir(path: &[u8]) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.scheme_ns) + (context.canonicalize(path), context.euid, context.egid, context.ens) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); @@ -216,7 +216,7 @@ pub fn unlink(path: &[u8]) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.scheme_ns) + (context.canonicalize(path), context.euid, context.egid, context.ens) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index c4e30ae..f197f84 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -17,7 +17,7 @@ use self::error::{Error, Result, ENOSYS}; use self::number::*; use context::ContextId; -use scheme::FileHandle; +use scheme::{FileHandle, SchemeNamespace}; /// Driver syscalls pub mod driver; @@ -82,13 +82,16 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_IOPL => iopl(b, stack), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), - SYS_GETUID => getuid(), - SYS_GETGID => getgid(), - SYS_GETEUID => geteuid(), SYS_GETEGID => getegid(), + SYS_GETENS => getens(), + SYS_GETEUID => geteuid(), + SYS_GETGID => getgid(), + SYS_GETNS => getns(), + SYS_GETUID => getuid(), + SYS_MKNS => mkns(validate_slice(b as *const [usize; 2], c)?), SYS_SETREUID => setreuid(b as u32, c as u32), + SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)), SYS_SETREGID => setregid(b as u32, c as u32), - SYS_SETNS => setns(validate_slice(b as *const [usize; 2], c)?), SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c), SYS_PHYSALLOC => physalloc(b), SYS_PHYSFREE => physfree(b, c), diff --git a/kernel/syscall/privilege.rs b/kernel/syscall/privilege.rs index e1abd8a..e718196 100644 --- a/kernel/syscall/privilege.rs +++ b/kernel/syscall/privilege.rs @@ -1,7 +1,7 @@ use collections::Vec; use context; -use scheme; +use scheme::{self, SchemeNamespace}; use syscall::error::*; use syscall::validate::validate_slice; @@ -12,6 +12,13 @@ pub fn getegid() -> Result { Ok(context.egid as usize) } +pub fn getens() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.ens.into()) +} + pub fn geteuid() -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -26,6 +33,13 @@ pub fn getgid() -> Result { Ok(context.rgid as usize) } +pub fn getns() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.rns.into()) +} + pub fn getuid() -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -33,6 +47,27 @@ pub fn getuid() -> Result { Ok(context.ruid as usize) } +pub fn mkns(name_ptrs: &[[usize; 2]]) -> Result { + let mut names = Vec::new(); + for name_ptr in name_ptrs { + names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?); + } + + let (uid, from) = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + (context.euid, context.ens) + }; + + if uid == 0 { + let to = scheme::schemes_mut().make_ns(from, &names)?; + Ok(to.into()) + } else { + Err(Error::new(EACCES)) + } +} + pub fn setregid(rgid: u32, egid: u32) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -59,6 +94,32 @@ pub fn setregid(rgid: u32, egid: u32) -> Result { } } +pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { + let contexts = context::contexts(); + 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)) + } +} + pub fn setreuid(ruid: u32, euid: u32) -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -84,28 +145,3 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result { Err(Error::new(EPERM)) } } - -pub fn setns(name_ptrs: &[[usize; 2]]) -> Result { - let mut names = Vec::new(); - for name_ptr in name_ptrs { - names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?); - } - - let from = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.scheme_ns - }; - - let to = scheme::schemes_mut().setns(from, &names)?; - - { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - context.scheme_ns = to; - } - - Ok(0) -} diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 3763341..9c1c69a 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -59,8 +59,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { { let ruid; let rgid; + let rns; let euid; let egid; + let ens; let mut cpu_id = None; let arch; let vfork; @@ -73,7 +75,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let mut tls_option = None; let grants; let name; - let scheme_ns; let cwd; let env; let files; @@ -87,8 +88,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { ppid = context.id; ruid = context.ruid; rgid = context.rgid; + rns = context.rns; euid = context.euid; egid = context.egid; + ens = context.ens; if flags & CLONE_VM == CLONE_VM { cpu_id = context.cpu_id; @@ -222,8 +225,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { name = Arc::new(Mutex::new(context.name.lock().clone())); } - scheme_ns = context.scheme_ns; - if flags & CLONE_FS == CLONE_FS { cwd = context.cwd.clone(); } else { @@ -304,8 +305,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { context.ppid = ppid; context.ruid = ruid; context.rgid = rgid; + context.rns = rns; context.euid = euid; context.egid = egid; + context.ens = ens; context.cpu_id = cpu_id; @@ -434,8 +437,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { context.name = name; - context.scheme_ns = scheme_ns; - context.cwd = cwd; context.env = env; diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index 8ec63ba..0a14eca 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -13,16 +13,18 @@ pub fn main() { let command = "sh"; + let mut name_ptrs = Vec::new(); + for name in names.iter() { + name_ptrs.push([name.as_ptr() as usize, name.len()]); + } + + let new_ns = syscall::mkns(&name_ptrs).unwrap(); + let pid = unsafe { syscall::clone(0).unwrap() }; if pid == 0 { - let mut name_ptrs = Vec::new(); - for name in names.iter() { - name_ptrs.push([name.as_ptr() as usize, name.len()]); - } + syscall::setrens(new_ns, new_ns).unwrap(); - syscall::setns(&name_ptrs).unwrap(); - - println!("Container enter: {}", command); + println!("Container {}: enter: {}", new_ns, command); let err = Command::new(command).exec(); @@ -41,6 +43,6 @@ pub fn main() { } } - println!("Container exited: {:X}", status); + println!("Container {}: exit: {:X}", new_ns, status); } } diff --git a/syscall b/syscall index cc90408..2835586 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit cc90408d147cc1d23b0e820d5b47522bd7dfc847 +Subproject commit 2835586ee671b0777ef1a98ced9237269c472941