diff --git a/Makefile b/Makefile index f4d15a1..3faa115 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ clean: cargo clean --manifest-path drivers/rtl8168d/Cargo.toml cargo clean --manifest-path drivers/vesad/Cargo.toml cargo clean --manifest-path programs/acid/Cargo.toml + cargo clean --manifest-path programs/contain/Cargo.toml cargo clean --manifest-path programs/init/Cargo.toml cargo clean --manifest-path programs/ion/Cargo.toml cargo clean --manifest-path programs/coreutils/Cargo.toml @@ -89,6 +90,7 @@ test: cargo test --manifest-path drivers/rtl8168d/Cargo.toml cargo test --manifest-path drivers/vesad/Cargo.toml cargo test --manifest-path programs/acid/Cargo.toml + cargo test --manifest-path programs/contain/Cargo.toml cargo test --manifest-path programs/init/Cargo.toml cargo test --manifest-path programs/ion/Cargo.toml cargo test --manifest-path programs/coreutils/Cargo.toml @@ -120,6 +122,7 @@ update: cargo update --manifest-path drivers/rtl8168d/Cargo.toml cargo update --manifest-path drivers/vesad/Cargo.toml cargo update --manifest-path programs/acid/Cargo.toml + cargo update --manifest-path programs/contain/Cargo.toml cargo update --manifest-path programs/init/Cargo.toml cargo update --manifest-path programs/ion/Cargo.toml cargo update --manifest-path programs/coreutils/Cargo.toml @@ -520,6 +523,7 @@ $(BUILD)/filesystem.bin: \ userutils \ schemes \ filesystem/bin/acid \ + filesystem/bin/contain \ filesystem/bin/ion \ filesystem/bin/sh \ filesystem/bin/smith \ diff --git a/kernel/context/context.rs b/kernel/context/context.rs index f80f675..46e456b 100644 --- a/kernel/context/context.rs +++ b/kernel/context/context.rs @@ -6,7 +6,7 @@ use spin::Mutex; use arch; use context::file::File; use context::memory::{Grant, Memory, SharedMemory, Tls}; -use scheme::FileHandle; +use scheme::{SchemeNamespace, FileHandle}; use syscall::data::Event; use sync::{WaitMap, WaitQueue}; @@ -68,6 +68,8 @@ 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 @@ -79,7 +81,6 @@ pub struct Context { } impl Context { - /// Create a new context pub fn new(id: ContextId) -> Context { Context { id: id, @@ -103,6 +104,7 @@ 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/lib.rs b/kernel/lib.rs index 193e4c2..6c03cfa 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -163,7 +163,7 @@ pub extern fn kmain_ap(id: usize) { loop { unsafe { interrupt::enable_and_halt(); } } - +/* loop { unsafe { interrupt::disable(); @@ -175,4 +175,5 @@ pub extern fn kmain_ap(id: usize) { } } } +*/ } diff --git a/kernel/scheme/debug.rs b/kernel/scheme/debug.rs index f4b88db..3845670 100644 --- a/kernel/scheme/debug.rs +++ b/kernel/scheme/debug.rs @@ -29,6 +29,13 @@ pub extern fn debug_input(b: u8) { pub struct DebugScheme; +impl DebugScheme { + pub fn new(scheme_id: SchemeId) -> DebugScheme { + DEBUG_SCHEME_ID.store(scheme_id, Ordering::SeqCst); + DebugScheme + } +} + impl Scheme for DebugScheme { fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { Ok(0) diff --git a/kernel/scheme/irq.rs b/kernel/scheme/irq.rs index bde521d..4817df0 100644 --- a/kernel/scheme/irq.rs +++ b/kernel/scheme/irq.rs @@ -4,7 +4,7 @@ use spin::Mutex; use arch::interrupt::irq::acknowledge; use context; -use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT}; +use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId}; use syscall::error::*; use syscall::flag::EVENT_READ; use syscall::scheme::Scheme; @@ -24,6 +24,13 @@ pub extern fn irq_trigger(irq: u8) { pub struct IrqScheme; +impl IrqScheme { + pub fn new(scheme_id: SchemeId) -> IrqScheme { + IRQ_SCHEME_ID.store(scheme_id, Ordering::SeqCst); + IrqScheme + } +} + impl Scheme for IrqScheme { fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { if uid == 0 { diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index c1ad0cb..cd00f30 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -9,20 +9,20 @@ use alloc::arc::Arc; use alloc::boxed::Box; use collections::BTreeMap; -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::AtomicUsize; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use syscall::error::*; use syscall::scheme::Scheme; -use self::debug::{DEBUG_SCHEME_ID, DebugScheme}; +use self::debug::DebugScheme; use self::event::EventScheme; use self::env::EnvScheme; use self::initfs::InitFsScheme; -use self::irq::{IRQ_SCHEME_ID, IrqScheme}; +use self::irq::IrqScheme; use self::null::NullScheme; -use self::pipe::{PIPE_SCHEME_ID, PipeScheme}; -use self::root::{ROOT_SCHEME_ID, RootScheme}; +use self::pipe::PipeScheme; +use self::root::RootScheme; use self::sys::SysScheme; use self::zero::ZeroScheme; @@ -62,6 +62,9 @@ pub mod zero; /// Limit on number of schemes pub const SCHEME_MAX_SCHEMES: usize = 65536; +/// Unique identifier for a scheme namespace. +int_like!(SchemeNamespace, AtomicSchemeNamespace, usize, AtomicUsize); + /// Unique identifier for a scheme. int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize); @@ -70,11 +73,11 @@ pub const ATOMIC_SCHEMEID_INIT: AtomicSchemeId = AtomicSchemeId::default(); /// Unique identifier for a file descriptor. int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize); - /// Scheme list type pub struct SchemeList { map: BTreeMap>>, - names: BTreeMap, SchemeId>, + names: BTreeMap, SchemeId>>, + next_ns: usize, next_id: usize } @@ -84,16 +87,44 @@ impl SchemeList { 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(); + } + + /// Initialize a new namespace + pub fn new_ns(&mut self) -> SchemeNamespace { + let ns = SchemeNamespace(self.next_ns); + self.next_ns += 1; + self.names.insert(ns, BTreeMap::new()); + + self.insert(ns, Box::new(*b""), |scheme_id| Arc::new(Box::new(RootScheme::new(ns, scheme_id)))).unwrap(); + self.insert(ns, Box::new(*b"event"), |_| Arc::new(Box::new(EventScheme::new()))).unwrap(); + self.insert(ns, Box::new(*b"env"), |_| Arc::new(Box::new(EnvScheme::new()))).unwrap(); + self.insert(ns, Box::new(*b"null"), |_| Arc::new(Box::new(NullScheme))).unwrap(); + self.insert(ns, Box::new(*b"sys"), |_| Arc::new(Box::new(SysScheme::new()))).unwrap(); + self.insert(ns, Box::new(*b"zero"), |_| Arc::new(Box::new(ZeroScheme))).unwrap(); + + ns + } + pub fn iter(&self) -> ::collections::btree_map::Iter>> { self.map.iter() } - pub fn iter_name(&self) -> ::collections::btree_map::Iter, SchemeId> { - self.names.iter() + pub fn iter_name(&self, ns: SchemeNamespace) -> ::collections::btree_map::Iter, SchemeId> { + self.names[&ns].iter() } /// Get the nth scheme. @@ -101,8 +132,8 @@ impl SchemeList { self.map.get(&id) } - pub fn get_name(&self, name: &[u8]) -> Option<(SchemeId, &Arc>)> { - if let Some(&id) = self.names.get(name) { + pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc>)> { + if let Some(&id) = self.names[&ns].get(name) { self.get(id).map(|scheme| (id, scheme)) } else { None @@ -110,8 +141,10 @@ impl SchemeList { } /// Create a new scheme. - pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc>) -> Result { - if self.names.contains_key(&name) { + pub fn insert(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result + where F: Fn(SchemeId) -> Arc> + { + if self.names[&ns].contains_key(&name) { return Err(Error::new(EEXIST)); } @@ -123,15 +156,23 @@ impl SchemeList { self.next_id += 1; } + /* Allow scheme list to grow if required if self.next_id >= SCHEME_MAX_SCHEMES { return Err(Error::new(EAGAIN)); } + */ let id = SchemeId(self.next_id); self.next_id += 1; + let scheme = scheme_fn(id); + assert!(self.map.insert(id, scheme).is_none()); - assert!(self.names.insert(name, id).is_none()); + if let Some(ref mut names) = self.names.get_mut(&ns) { + assert!(names.insert(name, id).is_none()); + } else { + panic!("scheme namespace not found"); + } Ok(id) } } @@ -142,16 +183,7 @@ static SCHEMES: Once> = Once::new(); /// Initialize schemes, called if needed fn init_schemes() -> RwLock { let mut list: SchemeList = SchemeList::new(); - ROOT_SCHEME_ID.store(list.insert(Box::new(*b""), Arc::new(Box::new(RootScheme::new()))).expect("failed to insert root scheme"), Ordering::SeqCst); - DEBUG_SCHEME_ID.store(list.insert(Box::new(*b"debug"), Arc::new(Box::new(DebugScheme))).expect("failed to insert debug scheme"), Ordering::SeqCst); - list.insert(Box::new(*b"event"), Arc::new(Box::new(EventScheme::new()))).expect("failed to insert event scheme"); - list.insert(Box::new(*b"env"), Arc::new(Box::new(EnvScheme::new()))).expect("failed to insert env scheme"); - list.insert(Box::new(*b"initfs"), Arc::new(Box::new(InitFsScheme::new()))).expect("failed to insert initfs scheme"); - IRQ_SCHEME_ID.store(list.insert(Box::new(*b"irq"), Arc::new(Box::new(IrqScheme))).expect("failed to insert irq scheme"), Ordering::SeqCst); - list.insert(Box::new(*b"null"), Arc::new(Box::new(NullScheme))).expect("failed to insert null scheme"); - PIPE_SCHEME_ID.store(list.insert(Box::new(*b"pipe"), Arc::new(Box::new(PipeScheme))).expect("failed to insert pipe scheme"), Ordering::SeqCst); - list.insert(Box::new(*b"sys"), Arc::new(Box::new(SysScheme::new()))).expect("failed to insert sys scheme"); - list.insert(Box::new(*b"zero"), Arc::new(Box::new(ZeroScheme))).expect("failed to insert zero scheme"); + list.init(); RwLock::new(list) } diff --git a/kernel/scheme/pipe.rs b/kernel/scheme/pipe.rs index c608ed5..5e64350 100644 --- a/kernel/scheme/pipe.rs +++ b/kernel/scheme/pipe.rs @@ -2,7 +2,7 @@ use alloc::arc::{Arc, Weak}; use collections::{BTreeMap, VecDeque}; use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT}; +use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId}; use sync::WaitCondition; use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE}; @@ -42,6 +42,13 @@ pub fn pipe(flags: usize) -> (usize, usize) { pub struct PipeScheme; +impl PipeScheme { + pub fn new(scheme_id: SchemeId) -> PipeScheme { + PIPE_SCHEME_ID.store(scheme_id, Ordering::SeqCst); + PipeScheme + } +} + impl Scheme for PipeScheme { fn dup(&self, id: usize, buf: &[u8]) -> Result { let mut pipes = pipes_mut(); diff --git a/kernel/scheme/root.rs b/kernel/scheme/root.rs index bc1ec42..1860998 100644 --- a/kernel/scheme/root.rs +++ b/kernel/scheme/root.rs @@ -7,19 +7,21 @@ use spin::RwLock; use context; use syscall::error::*; use syscall::scheme::Scheme; -use scheme::{self, AtomicSchemeId, ATOMIC_SCHEMEID_INIT}; +use scheme::{self, SchemeNamespace, SchemeId}; use scheme::user::{UserInner, UserScheme}; -pub static ROOT_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT; - pub struct RootScheme { + scheme_ns: SchemeNamespace, + scheme_id: SchemeId, next_id: AtomicUsize, handles: RwLock>> } impl RootScheme { - pub fn new() -> RootScheme { + pub fn new(scheme_ns: SchemeNamespace, scheme_id: SchemeId) -> RootScheme { RootScheme { + scheme_ns: scheme_ns, + scheme_id: scheme_id, next_id: AtomicUsize::new(0), handles: RwLock::new(BTreeMap::new()) } @@ -39,12 +41,11 @@ impl Scheme for RootScheme { let inner = { let mut schemes = scheme::schemes_mut(); - if schemes.get_name(path).is_some() { - return Err(Error::new(EEXIST)); - } - let inner = Arc::new(UserInner::new(id, flags, context)); - let scheme_id = schemes.insert(path.to_vec().into_boxed_slice(), Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner))))).expect("failed to insert user scheme"); - inner.scheme_id.store(scheme_id, Ordering::SeqCst); + let inner = Arc::new(UserInner::new(self.scheme_id, id, flags, context)); + schemes.insert(self.scheme_ns, path.to_vec().into_boxed_slice(), |scheme_id| { + inner.scheme_id.store(scheme_id, Ordering::SeqCst); + Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner)))) + })?; inner }; diff --git a/kernel/scheme/sys/scheme.rs b/kernel/scheme/sys/scheme.rs index 76c33b9..04df3d3 100644 --- a/kernel/scheme/sys/scheme.rs +++ b/kernel/scheme/sys/scheme.rs @@ -1,13 +1,21 @@ use collections::Vec; +use context; use scheme; -use syscall::error::Result; +use syscall::error::{Error, ESRCH, Result}; pub fn resource() -> Result> { + let scheme_ns = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + context.scheme_ns + }; + let mut data = Vec::new(); let schemes = scheme::schemes(); - for (name, _scheme_lock) in schemes.iter_name() { + for (name, _scheme_lock) in schemes.iter_name(scheme_ns) { data.extend_from_slice(name); data.push(b'\n'); } diff --git a/kernel/scheme/user.rs b/kernel/scheme/user.rs index 5c1d8dd..b396391 100644 --- a/kernel/scheme/user.rs +++ b/kernel/scheme/user.rs @@ -9,8 +9,7 @@ use arch::paging::{InactivePageTable, Page, VirtualAddress, entry}; use arch::paging::temporary_page::TemporaryPage; use context::{self, Context}; use context::memory::Grant; -use scheme::root::ROOT_SCHEME_ID; -use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT}; +use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId}; use sync::{WaitQueue, WaitMap}; use syscall::data::{Packet, Stat}; use syscall::error::*; @@ -19,6 +18,7 @@ use syscall::number::*; use syscall::scheme::Scheme; pub struct UserInner { + root_id: SchemeId, handle_id: usize, flags: usize, pub scheme_id: AtomicSchemeId, @@ -30,8 +30,9 @@ pub struct UserInner { } impl UserInner { - pub fn new(handle_id: usize, flags: usize, context: Weak>) -> UserInner { + pub fn new(root_id: SchemeId, handle_id: usize, flags: usize, context: Weak>) -> UserInner { UserInner { + root_id: root_id, handle_id: handle_id, flags: flags, scheme_id: ATOMIC_SCHEMEID_INIT, @@ -67,7 +68,7 @@ impl UserInner { let id = packet.id; let len = self.todo.send(packet); - context::event::trigger(ROOT_SCHEME_ID.load(Ordering::SeqCst), self.handle_id, EVENT_READ, mem::size_of::() * len); + context::event::trigger(self.root_id, self.handle_id, EVENT_READ, mem::size_of::() * len); Error::demux(self.done.receive(&id)) } diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs index b10a34a..12d1885 100644 --- a/kernel/syscall/fs.rs +++ b/kernel/syscall/fs.rs @@ -82,22 +82,22 @@ pub fn getcwd(buf: &mut [u8]) -> Result { /// Open syscall pub fn open(path: &[u8], flags: usize) -> Result { - let (path_canon, uid, gid) = { + let (path_canon, uid, gid, scheme_ns) = { 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.canonicalize(path), context.euid, context.egid, context.scheme_ns) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); - let namespace_opt = parts.next(); + let scheme_name_opt = parts.next(); let reference_opt = parts.next(); let (scheme_id, file_id) = { - let namespace = namespace_opt.ok_or(Error::new(ENODEV))?; + let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let (scheme_id, scheme) = { let schemes = scheme::schemes(); - let (scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?; + let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; (scheme_id, scheme.clone()) }; let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?; @@ -146,21 +146,21 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result { /// mkdir syscall pub fn mkdir(path: &[u8], mode: u16) -> Result { - let (path_canon, uid, gid) = { + let (path_canon, uid, gid, scheme_ns) = { 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.canonicalize(path), context.euid, context.egid, context.scheme_ns) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); - let namespace_opt = parts.next(); + let scheme_name_opt = parts.next(); let reference_opt = parts.next(); - let namespace = namespace_opt.ok_or(Error::new(ENODEV))?; + let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let scheme = { let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?; + let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; scheme.clone() }; scheme.mkdir(reference_opt.unwrap_or(b""), mode, uid, gid) @@ -168,21 +168,21 @@ pub fn mkdir(path: &[u8], mode: u16) -> Result { /// chmod syscall pub fn chmod(path: &[u8], mode: u16) -> Result { - let (path_canon, uid, gid) = { + let (path_canon, uid, gid, scheme_ns) = { 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.canonicalize(path), context.euid, context.egid, context.scheme_ns) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); - let namespace_opt = parts.next(); + let scheme_name_opt = parts.next(); let reference_opt = parts.next(); - let namespace = namespace_opt.ok_or(Error::new(ENODEV))?; + let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let scheme = { let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?; + let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; scheme.clone() }; scheme.chmod(reference_opt.unwrap_or(b""), mode, uid, gid) @@ -190,21 +190,21 @@ pub fn chmod(path: &[u8], mode: u16) -> Result { /// rmdir syscall pub fn rmdir(path: &[u8]) -> Result { - let (path_canon, uid, gid) = { + let (path_canon, uid, gid, scheme_ns) = { 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.canonicalize(path), context.euid, context.egid, context.scheme_ns) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); - let namespace_opt = parts.next(); + let scheme_name_opt = parts.next(); let reference_opt = parts.next(); - let namespace = namespace_opt.ok_or(Error::new(ENODEV))?; + let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let scheme = { let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?; + let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; scheme.clone() }; scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid) @@ -212,21 +212,21 @@ pub fn rmdir(path: &[u8]) -> Result { /// Unlink syscall pub fn unlink(path: &[u8]) -> Result { - let (path_canon, uid, gid) = { + let (path_canon, uid, gid, scheme_ns) = { 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.canonicalize(path), context.euid, context.egid, context.scheme_ns) }; let mut parts = path_canon.splitn(2, |&b| b == b':'); - let namespace_opt = parts.next(); + let scheme_name_opt = parts.next(); let reference_opt = parts.next(); - let namespace = namespace_opt.ok_or(Error::new(ENODEV))?; + let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; let scheme = { let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?; + let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; scheme.clone() }; scheme.unlink(reference_opt.unwrap_or(b""), uid, gid) diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 3a6f660..353c564 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, MAP_WRITE, MAP_WRITE_COMBINE, WNOHANG}; +use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_NEWNS, MAP_WRITE, MAP_WRITE_COMBINE, WNOHANG}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -74,6 +74,7 @@ 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; @@ -222,6 +223,12 @@ 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; + } + if flags & CLONE_FS == CLONE_FS { cwd = context.cwd.clone(); } else { @@ -433,6 +440,8 @@ 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/libstd b/libstd index 166a1f0..18d61d7 160000 --- a/libstd +++ b/libstd @@ -1 +1 @@ -Subproject commit 166a1f0a468205c7166791563d00e663559a8e93 +Subproject commit 18d61d7e8a469fb0a05a9db4d00970b7e45954ad diff --git a/programs/contain/Cargo.toml b/programs/contain/Cargo.toml new file mode 100644 index 0000000..ad46eb0 --- /dev/null +++ b/programs/contain/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "contain" +version = "0.1.0" + +[dependencies] +redox_syscall = { path = "../../syscall" } diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs new file mode 100644 index 0000000..f0ec7b1 --- /dev/null +++ b/programs/contain/src/main.rs @@ -0,0 +1,28 @@ +extern crate syscall; + +use std::fs::File; +use std::io::{BufRead, BufReader}; + +pub fn main() { + let pid = unsafe { syscall::clone(syscall::CLONE_NEWNS).unwrap() }; + if pid == 0 { + println!("Child Namespace:"); + let file = BufReader::new(File::open("sys:scheme").unwrap()); + for line in file.lines() { + let line = line.unwrap(); + println!("{}", line); + } + println!(""); + } else { + let mut status = 0; + syscall::waitpid(pid, &mut status, 0).unwrap(); + + println!("Parent Namespace:"); + let file = BufReader::new(File::open("sys:scheme").unwrap()); + for line in file.lines() { + let line = line.unwrap(); + println!("{}", line); + } + println!(""); + } +} diff --git a/syscall b/syscall index 3e39d46..f87cbb5 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 3e39d46f969a0576120994ea13530e5712773cf5 +Subproject commit f87cbb53130a6a9652e2ed8dd066fa7fa97c8e42