More advanced setns syscall
This commit is contained in:
		
							parent
							
								
									d294d56b52
								
							
						
					
					
						commit
						b551b30300
					
				
					 7 changed files with 88 additions and 35 deletions
				
			
		|  | @ -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<SchemeNamespace> { | ||||
|         // 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<SchemeId, Arc<Box<Scheme + Send + Sync>>> { | ||||
|         self.map.iter() | ||||
|     } | ||||
|  | @ -182,9 +207,7 @@ static SCHEMES: Once<RwLock<SchemeList>> = Once::new(); | |||
| 
 | ||||
| /// Initialize schemes, called if needed
 | ||||
| fn init_schemes() -> RwLock<SchemeList> { | ||||
|     let mut list: SchemeList = SchemeList::new(); | ||||
|     list.init(); | ||||
|     RwLock::new(list) | ||||
|     RwLock::new(SchemeList::new()) | ||||
| } | ||||
| 
 | ||||
| /// Get the global schemes list, const
 | ||||
|  |  | |||
|  | @ -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), | ||||
|  |  | |||
|  | @ -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<usize> { | ||||
|  | @ -223,11 +223,7 @@ 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; | ||||
|             } | ||||
|             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<usize> { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn setns(name_ptrs: &[[usize; 2]]) -> Result<usize> { | ||||
|     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<usize> { | ||||
|     let active_table = unsafe { ActivePageTable::new() }; | ||||
|     match active_table.translate(VirtualAddress::new(virtual_address)) { | ||||
|  |  | |||
|  | @ -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!(""); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| Subproject commit 425b264ed7f1df10eeaff7c71191f0e2989da719 | ||||
| Subproject commit b9db33d81aea2d40cc88432926558d146363b4a1 | ||||
|  | @ -1 +1 @@ | |||
| Subproject commit d44639145bbadeae57066aecaec146f7d3e8c645 | ||||
| Subproject commit 5f9ff4d19ec299cd9cc70e4c04e0b6a8ee1fa57f | ||||
							
								
								
									
										2
									
								
								syscall
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								syscall
									
										
									
									
									
								
							|  | @ -1 +1 @@ | |||
| Subproject commit f87cbb53130a6a9652e2ed8dd066fa7fa97c8e42 | ||||
| Subproject commit 7b8cc598909189526d8c0caa8057e4a6b23f0fdc | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller