Add ability to contain a process in a scheme sandbox
This commit is contained in:
		
							parent
							
								
									6b8a576a21
								
							
						
					
					
						commit
						d294d56b52
					
				
					 16 changed files with 186 additions and 73 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								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 \
 | ||||
|  |  | |||
|  | @ -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<Mutex<Vec<Grant>>>, | ||||
|     /// The name of the context
 | ||||
|     pub name: Arc<Mutex<Vec<u8>>>, | ||||
|     /// The scheme namespace of this context
 | ||||
|     pub scheme_ns: SchemeNamespace, | ||||
|     /// The current working directory
 | ||||
|     pub cwd: Arc<Mutex<Vec<u8>>>, | ||||
|     /// 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())), | ||||
|  |  | |||
|  | @ -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) { | |||
|             } | ||||
|         } | ||||
|     } | ||||
| */ | ||||
| } | ||||
|  |  | |||
|  | @ -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<usize> { | ||||
|         Ok(0) | ||||
|  |  | |||
|  | @ -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<usize> { | ||||
|         if uid == 0 { | ||||
|  |  | |||
|  | @ -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<SchemeId, Arc<Box<Scheme + Send + Sync>>>, | ||||
|     names: BTreeMap<Box<[u8]>, SchemeId>, | ||||
|     names: BTreeMap<SchemeNamespace, BTreeMap<Box<[u8]>, 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<SchemeId, Arc<Box<Scheme + Send + Sync>>> { | ||||
|         self.map.iter() | ||||
|     } | ||||
| 
 | ||||
|     pub fn iter_name(&self) -> ::collections::btree_map::Iter<Box<[u8]>, SchemeId> { | ||||
|         self.names.iter() | ||||
|     pub fn iter_name(&self, ns: SchemeNamespace) -> ::collections::btree_map::Iter<Box<[u8]>, 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<Box<Scheme + Send + Sync>>)> { | ||||
|         if let Some(&id) = self.names.get(name) { | ||||
|     pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> { | ||||
|         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<Box<Scheme + Send + Sync>>) -> Result<SchemeId> { | ||||
|         if self.names.contains_key(&name) { | ||||
|     pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId> | ||||
|         where F: Fn(SchemeId) -> Arc<Box<Scheme + Send + Sync>> | ||||
|     { | ||||
|         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<RwLock<SchemeList>> = Once::new(); | |||
| /// Initialize schemes, called if needed
 | ||||
| fn init_schemes() -> RwLock<SchemeList> { | ||||
|     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) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<usize> { | ||||
|         let mut pipes = pipes_mut(); | ||||
|  |  | |||
|  | @ -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<BTreeMap<usize, Arc<UserInner>>> | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
|             }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Vec<u8>> { | ||||
|     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'); | ||||
|     } | ||||
|  |  | |||
|  | @ -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<RwLock<Context>>) -> UserInner { | ||||
|     pub fn new(root_id: SchemeId, handle_id: usize, flags: usize, context: Weak<RwLock<Context>>) -> 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::<Packet>() * len); | ||||
|         context::event::trigger(self.root_id, self.handle_id, EVENT_READ, mem::size_of::<Packet>() * len); | ||||
| 
 | ||||
|         Error::demux(self.done.receive(&id)) | ||||
|     } | ||||
|  |  | |||
|  | @ -82,22 +82,22 @@ pub fn getcwd(buf: &mut [u8]) -> Result<usize> { | |||
| 
 | ||||
| /// Open syscall
 | ||||
| pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> { | ||||
|     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<usize> { | |||
| 
 | ||||
| /// mkdir syscall
 | ||||
| pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> { | ||||
|     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<usize> { | |||
| 
 | ||||
| /// chmod syscall
 | ||||
| pub fn chmod(path: &[u8], mode: u16) -> Result<usize> { | ||||
|     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<usize> { | |||
| 
 | ||||
| /// rmdir syscall
 | ||||
| pub fn rmdir(path: &[u8]) -> Result<usize> { | ||||
|     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<usize> { | |||
| 
 | ||||
| /// Unlink syscall
 | ||||
| pub fn unlink(path: &[u8]) -> Result<usize> { | ||||
|     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) | ||||
|  |  | |||
|  | @ -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<usize> { | ||||
|  | @ -74,6 +74,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> { | |||
|         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<ContextId> { | |||
|                 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<ContextId> { | |||
| 
 | ||||
|             context.name = name; | ||||
| 
 | ||||
|             context.scheme_ns = scheme_ns; | ||||
| 
 | ||||
|             context.cwd = cwd; | ||||
| 
 | ||||
|             context.env = env; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								libstd
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								libstd
									
										
									
									
									
								
							|  | @ -1 +1 @@ | |||
| Subproject commit 166a1f0a468205c7166791563d00e663559a8e93 | ||||
| Subproject commit 18d61d7e8a469fb0a05a9db4d00970b7e45954ad | ||||
							
								
								
									
										6
									
								
								programs/contain/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								programs/contain/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| [package] | ||||
| name = "contain" | ||||
| version = "0.1.0" | ||||
| 
 | ||||
| [dependencies] | ||||
| redox_syscall = { path = "../../syscall" } | ||||
							
								
								
									
										28
									
								
								programs/contain/src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								programs/contain/src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -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!(""); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										2
									
								
								syscall
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								syscall
									
										
									
									
									
								
							|  | @ -1 +1 @@ | |||
| Subproject commit 3e39d46f969a0576120994ea13530e5712773cf5 | ||||
| Subproject commit f87cbb53130a6a9652e2ed8dd066fa7fa97c8e42 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller