More advanced setns syscall

This commit is contained in:
Jeremy Soller 2016-11-16 22:14:02 -07:00
parent d294d56b52
commit b551b30300
7 changed files with 88 additions and 35 deletions

View file

@ -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

View file

@ -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),

View file

@ -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;
}
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)) {

View file

@ -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

@ -1 +1 @@
Subproject commit f87cbb53130a6a9652e2ed8dd066fa7fa97c8e42
Subproject commit 7b8cc598909189526d8c0caa8057e4a6b23f0fdc