Add ability to contain a process in a scheme sandbox

This commit is contained in:
Jeremy Soller 2016-11-16 20:54:38 -07:00
parent 6b8a576a21
commit d294d56b52
16 changed files with 186 additions and 73 deletions

View file

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

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, 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;