From b551b30300b52aff71fc25b86fd96572f5dab5d1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 16 Nov 2016 22:14:02 -0700 Subject: [PATCH] More advanced setns syscall --- kernel/scheme/mod.rs | 57 +++++++++++++++++++++++++----------- kernel/syscall/mod.rs | 11 +++---- kernel/syscall/process.rs | 33 +++++++++++++++++---- programs/contain/src/main.rs | 16 +++++++--- programs/pkgutils | 2 +- programs/userutils | 2 +- syscall | 2 +- 7 files changed, 88 insertions(+), 35 deletions(-) diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index cd00f30..09590ae 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -84,27 +84,18 @@ pub struct SchemeList { impl SchemeList { /// Create a new scheme list. pub fn new() -> Self { - SchemeList { + let mut list = SchemeList { map: BTreeMap::new(), names: BTreeMap::new(), next_ns: 0, next_id: 1 - } - } - - /// Initialize the root namespace - fn init(&mut self) { - // Do common namespace initialization - let ns = self.new_ns(); - // Debug, Initfs and IRQ are only available in the root namespace. Pipe is special - self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap(); + }; + list.new_root(); + list } /// Initialize a new namespace - pub fn new_ns(&mut self) -> SchemeNamespace { + fn new_ns(&mut self) -> SchemeNamespace { let ns = SchemeNamespace(self.next_ns); self.next_ns += 1; self.names.insert(ns, BTreeMap::new()); @@ -119,6 +110,40 @@ impl SchemeList { ns } + /// Initialize the root namespace + fn new_root(&mut self) { + // Do common namespace initialization + let ns = self.new_ns(); + + // Debug, Initfs and IRQ are only available in the root namespace. Pipe is special + self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap(); + self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap(); + self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap(); + 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 { + // Create an empty namespace + let to = self.new_ns(); + + // Copy requested scheme IDs + for name in names.iter() { + let id = if let Some((id, _scheme)) = self.get_name(from, name) { + id + } else { + return Err(Error::new(ENODEV)); + }; + + if let Some(ref mut names) = self.names.get_mut(&to) { + assert!(names.insert(name.to_vec().into_boxed_slice(), id).is_none()); + } else { + panic!("scheme namespace not found"); + } + } + + Ok(to) + } + pub fn iter(&self) -> ::collections::btree_map::Iter>> { self.map.iter() } @@ -182,9 +207,7 @@ static SCHEMES: Once> = Once::new(); /// Initialize schemes, called if needed fn init_schemes() -> RwLock { - let mut list: SchemeList = SchemeList::new(); - list.init(); - RwLock::new(list) + RwLock::new(SchemeList::new()) } /// Get the global schemes list, const diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 89058df..952cd93 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -60,16 +60,18 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize _ => unreachable!() }, _ => match a { + SYS_YIELD => sched_yield(), + SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])), + SYS_CLOCK_GETTIME => clock_gettime(b, validate_slice_mut(c as *mut TimeSpec, 1).map(|time| &mut time[0])?), + SYS_FUTEX => futex(validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0])?, c, d as i32, e, f as *mut i32), + SYS_BRK => brk(b), SYS_EXIT => exit(b), SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into), SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), SYS_GETPID => getpid().map(ContextId::into), - SYS_BRK => brk(b), SYS_IOPL => iopl(b), SYS_CLONE => clone(b, stack).map(ContextId::into), - SYS_YIELD => sched_yield(), - SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), SYS_GETUID => getuid(), SYS_GETGID => getgid(), @@ -77,8 +79,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_GETEGID => getegid(), SYS_SETUID => setuid(b as u32), SYS_SETGID => setgid(b as u32), - SYS_CLOCK_GETTIME => clock_gettime(b, validate_slice_mut(c as *mut TimeSpec, 1).map(|time| &mut time[0])?), - SYS_FUTEX => futex(validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0])?, c, d as i32, e, f as *mut i32), + 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/process.rs b/kernel/syscall/process.rs index 353c564..b103365 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -19,7 +19,7 @@ use scheme::{self, FileHandle}; use syscall; use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_NEWNS, MAP_WRITE, MAP_WRITE_COMBINE, WNOHANG}; +use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, MAP_WRITE, MAP_WRITE_COMBINE, WNOHANG}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -223,11 +223,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { name = Arc::new(Mutex::new(context.name.lock().clone())); } - if flags & CLONE_NEWNS == CLONE_NEWNS { - scheme_ns = scheme::schemes_mut().new_ns(); - } else { - scheme_ns = context.scheme_ns; - } + scheme_ns = context.scheme_ns; if flags & CLONE_FS == CLONE_FS { cwd = context.cwd.clone(); @@ -1058,6 +1054,31 @@ pub fn setuid(uid: u32) -> Result { } } +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) +} + pub fn virttophys(virtual_address: usize) -> Result { let active_table = unsafe { ActivePageTable::new() }; match active_table.translate(VirtualAddress::new(virtual_address)) { diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index f0ec7b1..898bb6b 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -1,18 +1,27 @@ extern crate syscall; use std::fs::File; -use std::io::{BufRead, BufReader}; +use std::io::{BufRead, BufReader, Read}; pub fn main() { - let pid = unsafe { syscall::clone(syscall::CLONE_NEWNS).unwrap() }; + let pid = unsafe { syscall::clone(0).unwrap() }; if pid == 0 { + let rand = b"rand"; + syscall::setns(&[[rand.as_ptr() as usize, rand.len()]]).unwrap(); + println!("Child Namespace:"); let file = BufReader::new(File::open("sys:scheme").unwrap()); for line in file.lines() { let line = line.unwrap(); println!("{}", line); } - println!(""); + + let mut rand = File::open("rand:").unwrap(); + + let mut byte = [0]; + rand.read(&mut byte).unwrap(); + + println!("Rand: {}", byte[0]); } else { let mut status = 0; syscall::waitpid(pid, &mut status, 0).unwrap(); @@ -23,6 +32,5 @@ pub fn main() { let line = line.unwrap(); println!("{}", line); } - println!(""); } } diff --git a/programs/pkgutils b/programs/pkgutils index 425b264..b9db33d 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 425b264ed7f1df10eeaff7c71191f0e2989da719 +Subproject commit b9db33d81aea2d40cc88432926558d146363b4a1 diff --git a/programs/userutils b/programs/userutils index d446391..5f9ff4d 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit d44639145bbadeae57066aecaec146f7d3e8c645 +Subproject commit 5f9ff4d19ec299cd9cc70e4c04e0b6a8ee1fa57f diff --git a/syscall b/syscall index f87cbb5..7b8cc59 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit f87cbb53130a6a9652e2ed8dd066fa7fa97c8e42 +Subproject commit 7b8cc598909189526d8c0caa8057e4a6b23f0fdc