Add ability to contain a process in a scheme sandbox
This commit is contained in:
parent
6b8a576a21
commit
d294d56b52
4
Makefile
4
Makefile
|
@ -36,6 +36,7 @@ clean:
|
||||||
cargo clean --manifest-path drivers/rtl8168d/Cargo.toml
|
cargo clean --manifest-path drivers/rtl8168d/Cargo.toml
|
||||||
cargo clean --manifest-path drivers/vesad/Cargo.toml
|
cargo clean --manifest-path drivers/vesad/Cargo.toml
|
||||||
cargo clean --manifest-path programs/acid/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/init/Cargo.toml
|
||||||
cargo clean --manifest-path programs/ion/Cargo.toml
|
cargo clean --manifest-path programs/ion/Cargo.toml
|
||||||
cargo clean --manifest-path programs/coreutils/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/rtl8168d/Cargo.toml
|
||||||
cargo test --manifest-path drivers/vesad/Cargo.toml
|
cargo test --manifest-path drivers/vesad/Cargo.toml
|
||||||
cargo test --manifest-path programs/acid/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/init/Cargo.toml
|
||||||
cargo test --manifest-path programs/ion/Cargo.toml
|
cargo test --manifest-path programs/ion/Cargo.toml
|
||||||
cargo test --manifest-path programs/coreutils/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/rtl8168d/Cargo.toml
|
||||||
cargo update --manifest-path drivers/vesad/Cargo.toml
|
cargo update --manifest-path drivers/vesad/Cargo.toml
|
||||||
cargo update --manifest-path programs/acid/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/init/Cargo.toml
|
||||||
cargo update --manifest-path programs/ion/Cargo.toml
|
cargo update --manifest-path programs/ion/Cargo.toml
|
||||||
cargo update --manifest-path programs/coreutils/Cargo.toml
|
cargo update --manifest-path programs/coreutils/Cargo.toml
|
||||||
|
@ -520,6 +523,7 @@ $(BUILD)/filesystem.bin: \
|
||||||
userutils \
|
userutils \
|
||||||
schemes \
|
schemes \
|
||||||
filesystem/bin/acid \
|
filesystem/bin/acid \
|
||||||
|
filesystem/bin/contain \
|
||||||
filesystem/bin/ion \
|
filesystem/bin/ion \
|
||||||
filesystem/bin/sh \
|
filesystem/bin/sh \
|
||||||
filesystem/bin/smith \
|
filesystem/bin/smith \
|
||||||
|
|
|
@ -6,7 +6,7 @@ use spin::Mutex;
|
||||||
use arch;
|
use arch;
|
||||||
use context::file::File;
|
use context::file::File;
|
||||||
use context::memory::{Grant, Memory, SharedMemory, Tls};
|
use context::memory::{Grant, Memory, SharedMemory, Tls};
|
||||||
use scheme::FileHandle;
|
use scheme::{SchemeNamespace, FileHandle};
|
||||||
use syscall::data::Event;
|
use syscall::data::Event;
|
||||||
use sync::{WaitMap, WaitQueue};
|
use sync::{WaitMap, WaitQueue};
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ pub struct Context {
|
||||||
pub grants: Arc<Mutex<Vec<Grant>>>,
|
pub grants: Arc<Mutex<Vec<Grant>>>,
|
||||||
/// The name of the context
|
/// The name of the context
|
||||||
pub name: Arc<Mutex<Vec<u8>>>,
|
pub name: Arc<Mutex<Vec<u8>>>,
|
||||||
|
/// The scheme namespace of this context
|
||||||
|
pub scheme_ns: SchemeNamespace,
|
||||||
/// The current working directory
|
/// The current working directory
|
||||||
pub cwd: Arc<Mutex<Vec<u8>>>,
|
pub cwd: Arc<Mutex<Vec<u8>>>,
|
||||||
/// Kernel events
|
/// Kernel events
|
||||||
|
@ -79,7 +81,6 @@ pub struct Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Create a new context
|
|
||||||
pub fn new(id: ContextId) -> Context {
|
pub fn new(id: ContextId) -> Context {
|
||||||
Context {
|
Context {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -103,6 +104,7 @@ impl Context {
|
||||||
tls: None,
|
tls: None,
|
||||||
grants: Arc::new(Mutex::new(Vec::new())),
|
grants: Arc::new(Mutex::new(Vec::new())),
|
||||||
name: 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())),
|
cwd: Arc::new(Mutex::new(Vec::new())),
|
||||||
events: Arc::new(WaitQueue::new()),
|
events: Arc::new(WaitQueue::new()),
|
||||||
env: Arc::new(Mutex::new(BTreeMap::new())),
|
env: Arc::new(Mutex::new(BTreeMap::new())),
|
||||||
|
|
|
@ -163,7 +163,7 @@ pub extern fn kmain_ap(id: usize) {
|
||||||
loop {
|
loop {
|
||||||
unsafe { interrupt::enable_and_halt(); }
|
unsafe { interrupt::enable_and_halt(); }
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
interrupt::disable();
|
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;
|
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 {
|
impl Scheme for DebugScheme {
|
||||||
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use spin::Mutex;
|
||||||
|
|
||||||
use arch::interrupt::irq::acknowledge;
|
use arch::interrupt::irq::acknowledge;
|
||||||
use context;
|
use context;
|
||||||
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
|
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
|
||||||
use syscall::error::*;
|
use syscall::error::*;
|
||||||
use syscall::flag::EVENT_READ;
|
use syscall::flag::EVENT_READ;
|
||||||
use syscall::scheme::Scheme;
|
use syscall::scheme::Scheme;
|
||||||
|
@ -24,6 +24,13 @@ pub extern fn irq_trigger(irq: u8) {
|
||||||
|
|
||||||
pub struct IrqScheme;
|
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 {
|
impl Scheme for IrqScheme {
|
||||||
fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||||
if uid == 0 {
|
if uid == 0 {
|
||||||
|
|
|
@ -9,20 +9,20 @@
|
||||||
use alloc::arc::Arc;
|
use alloc::arc::Arc;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use collections::BTreeMap;
|
use collections::BTreeMap;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::AtomicUsize;
|
||||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
|
||||||
use syscall::error::*;
|
use syscall::error::*;
|
||||||
use syscall::scheme::Scheme;
|
use syscall::scheme::Scheme;
|
||||||
|
|
||||||
use self::debug::{DEBUG_SCHEME_ID, DebugScheme};
|
use self::debug::DebugScheme;
|
||||||
use self::event::EventScheme;
|
use self::event::EventScheme;
|
||||||
use self::env::EnvScheme;
|
use self::env::EnvScheme;
|
||||||
use self::initfs::InitFsScheme;
|
use self::initfs::InitFsScheme;
|
||||||
use self::irq::{IRQ_SCHEME_ID, IrqScheme};
|
use self::irq::IrqScheme;
|
||||||
use self::null::NullScheme;
|
use self::null::NullScheme;
|
||||||
use self::pipe::{PIPE_SCHEME_ID, PipeScheme};
|
use self::pipe::PipeScheme;
|
||||||
use self::root::{ROOT_SCHEME_ID, RootScheme};
|
use self::root::RootScheme;
|
||||||
use self::sys::SysScheme;
|
use self::sys::SysScheme;
|
||||||
use self::zero::ZeroScheme;
|
use self::zero::ZeroScheme;
|
||||||
|
|
||||||
|
@ -62,6 +62,9 @@ pub mod zero;
|
||||||
/// Limit on number of schemes
|
/// Limit on number of schemes
|
||||||
pub const SCHEME_MAX_SCHEMES: usize = 65536;
|
pub const SCHEME_MAX_SCHEMES: usize = 65536;
|
||||||
|
|
||||||
|
/// Unique identifier for a scheme namespace.
|
||||||
|
int_like!(SchemeNamespace, AtomicSchemeNamespace, usize, AtomicUsize);
|
||||||
|
|
||||||
/// Unique identifier for a scheme.
|
/// Unique identifier for a scheme.
|
||||||
int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize);
|
int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize);
|
||||||
|
|
||||||
|
@ -70,11 +73,11 @@ pub const ATOMIC_SCHEMEID_INIT: AtomicSchemeId = AtomicSchemeId::default();
|
||||||
/// Unique identifier for a file descriptor.
|
/// Unique identifier for a file descriptor.
|
||||||
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);
|
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);
|
||||||
|
|
||||||
|
|
||||||
/// Scheme list type
|
/// Scheme list type
|
||||||
pub struct SchemeList {
|
pub struct SchemeList {
|
||||||
map: BTreeMap<SchemeId, Arc<Box<Scheme + Send + Sync>>>,
|
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
|
next_id: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,16 +87,44 @@ impl SchemeList {
|
||||||
SchemeList {
|
SchemeList {
|
||||||
map: BTreeMap::new(),
|
map: BTreeMap::new(),
|
||||||
names: BTreeMap::new(),
|
names: BTreeMap::new(),
|
||||||
|
next_ns: 0,
|
||||||
next_id: 1
|
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>>> {
|
pub fn iter(&self) -> ::collections::btree_map::Iter<SchemeId, Arc<Box<Scheme + Send + Sync>>> {
|
||||||
self.map.iter()
|
self.map.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_name(&self) -> ::collections::btree_map::Iter<Box<[u8]>, SchemeId> {
|
pub fn iter_name(&self, ns: SchemeNamespace) -> ::collections::btree_map::Iter<Box<[u8]>, SchemeId> {
|
||||||
self.names.iter()
|
self.names[&ns].iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the nth scheme.
|
/// Get the nth scheme.
|
||||||
|
@ -101,8 +132,8 @@ impl SchemeList {
|
||||||
self.map.get(&id)
|
self.map.get(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_name(&self, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> {
|
pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> {
|
||||||
if let Some(&id) = self.names.get(name) {
|
if let Some(&id) = self.names[&ns].get(name) {
|
||||||
self.get(id).map(|scheme| (id, scheme))
|
self.get(id).map(|scheme| (id, scheme))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -110,8 +141,10 @@ impl SchemeList {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new scheme.
|
/// Create a new scheme.
|
||||||
pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Box<Scheme + Send + Sync>>) -> Result<SchemeId> {
|
pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId>
|
||||||
if self.names.contains_key(&name) {
|
where F: Fn(SchemeId) -> Arc<Box<Scheme + Send + Sync>>
|
||||||
|
{
|
||||||
|
if self.names[&ns].contains_key(&name) {
|
||||||
return Err(Error::new(EEXIST));
|
return Err(Error::new(EEXIST));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,15 +156,23 @@ impl SchemeList {
|
||||||
self.next_id += 1;
|
self.next_id += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allow scheme list to grow if required
|
||||||
if self.next_id >= SCHEME_MAX_SCHEMES {
|
if self.next_id >= SCHEME_MAX_SCHEMES {
|
||||||
return Err(Error::new(EAGAIN));
|
return Err(Error::new(EAGAIN));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
let id = SchemeId(self.next_id);
|
let id = SchemeId(self.next_id);
|
||||||
self.next_id += 1;
|
self.next_id += 1;
|
||||||
|
|
||||||
|
let scheme = scheme_fn(id);
|
||||||
|
|
||||||
assert!(self.map.insert(id, scheme).is_none());
|
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)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,16 +183,7 @@ static SCHEMES: Once<RwLock<SchemeList>> = Once::new();
|
||||||
/// Initialize schemes, called if needed
|
/// Initialize schemes, called if needed
|
||||||
fn init_schemes() -> RwLock<SchemeList> {
|
fn init_schemes() -> RwLock<SchemeList> {
|
||||||
let mut list: SchemeList = SchemeList::new();
|
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);
|
list.init();
|
||||||
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");
|
|
||||||
RwLock::new(list)
|
RwLock::new(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use alloc::arc::{Arc, Weak};
|
||||||
use collections::{BTreeMap, VecDeque};
|
use collections::{BTreeMap, VecDeque};
|
||||||
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
|
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
|
||||||
|
|
||||||
use sync::WaitCondition;
|
use sync::WaitCondition;
|
||||||
use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE};
|
use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE};
|
||||||
|
@ -42,6 +42,13 @@ pub fn pipe(flags: usize) -> (usize, usize) {
|
||||||
|
|
||||||
pub struct PipeScheme;
|
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 {
|
impl Scheme for PipeScheme {
|
||||||
fn dup(&self, id: usize, buf: &[u8]) -> Result<usize> {
|
fn dup(&self, id: usize, buf: &[u8]) -> Result<usize> {
|
||||||
let mut pipes = pipes_mut();
|
let mut pipes = pipes_mut();
|
||||||
|
|
|
@ -7,19 +7,21 @@ use spin::RwLock;
|
||||||
use context;
|
use context;
|
||||||
use syscall::error::*;
|
use syscall::error::*;
|
||||||
use syscall::scheme::Scheme;
|
use syscall::scheme::Scheme;
|
||||||
use scheme::{self, AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
|
use scheme::{self, SchemeNamespace, SchemeId};
|
||||||
use scheme::user::{UserInner, UserScheme};
|
use scheme::user::{UserInner, UserScheme};
|
||||||
|
|
||||||
pub static ROOT_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
|
|
||||||
|
|
||||||
pub struct RootScheme {
|
pub struct RootScheme {
|
||||||
|
scheme_ns: SchemeNamespace,
|
||||||
|
scheme_id: SchemeId,
|
||||||
next_id: AtomicUsize,
|
next_id: AtomicUsize,
|
||||||
handles: RwLock<BTreeMap<usize, Arc<UserInner>>>
|
handles: RwLock<BTreeMap<usize, Arc<UserInner>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RootScheme {
|
impl RootScheme {
|
||||||
pub fn new() -> RootScheme {
|
pub fn new(scheme_ns: SchemeNamespace, scheme_id: SchemeId) -> RootScheme {
|
||||||
RootScheme {
|
RootScheme {
|
||||||
|
scheme_ns: scheme_ns,
|
||||||
|
scheme_id: scheme_id,
|
||||||
next_id: AtomicUsize::new(0),
|
next_id: AtomicUsize::new(0),
|
||||||
handles: RwLock::new(BTreeMap::new())
|
handles: RwLock::new(BTreeMap::new())
|
||||||
}
|
}
|
||||||
|
@ -39,12 +41,11 @@ impl Scheme for RootScheme {
|
||||||
|
|
||||||
let inner = {
|
let inner = {
|
||||||
let mut schemes = scheme::schemes_mut();
|
let mut schemes = scheme::schemes_mut();
|
||||||
if schemes.get_name(path).is_some() {
|
let inner = Arc::new(UserInner::new(self.scheme_id, id, flags, context));
|
||||||
return Err(Error::new(EEXIST));
|
schemes.insert(self.scheme_ns, path.to_vec().into_boxed_slice(), |scheme_id| {
|
||||||
}
|
|
||||||
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);
|
inner.scheme_id.store(scheme_id, Ordering::SeqCst);
|
||||||
|
Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner))))
|
||||||
|
})?;
|
||||||
inner
|
inner
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
use collections::Vec;
|
use collections::Vec;
|
||||||
|
|
||||||
|
use context;
|
||||||
use scheme;
|
use scheme;
|
||||||
use syscall::error::Result;
|
use syscall::error::{Error, ESRCH, Result};
|
||||||
|
|
||||||
pub fn resource() -> Result<Vec<u8>> {
|
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 mut data = Vec::new();
|
||||||
|
|
||||||
let schemes = scheme::schemes();
|
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.extend_from_slice(name);
|
||||||
data.push(b'\n');
|
data.push(b'\n');
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ use arch::paging::{InactivePageTable, Page, VirtualAddress, entry};
|
||||||
use arch::paging::temporary_page::TemporaryPage;
|
use arch::paging::temporary_page::TemporaryPage;
|
||||||
use context::{self, Context};
|
use context::{self, Context};
|
||||||
use context::memory::Grant;
|
use context::memory::Grant;
|
||||||
use scheme::root::ROOT_SCHEME_ID;
|
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId};
|
||||||
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
|
|
||||||
use sync::{WaitQueue, WaitMap};
|
use sync::{WaitQueue, WaitMap};
|
||||||
use syscall::data::{Packet, Stat};
|
use syscall::data::{Packet, Stat};
|
||||||
use syscall::error::*;
|
use syscall::error::*;
|
||||||
|
@ -19,6 +18,7 @@ use syscall::number::*;
|
||||||
use syscall::scheme::Scheme;
|
use syscall::scheme::Scheme;
|
||||||
|
|
||||||
pub struct UserInner {
|
pub struct UserInner {
|
||||||
|
root_id: SchemeId,
|
||||||
handle_id: usize,
|
handle_id: usize,
|
||||||
flags: usize,
|
flags: usize,
|
||||||
pub scheme_id: AtomicSchemeId,
|
pub scheme_id: AtomicSchemeId,
|
||||||
|
@ -30,8 +30,9 @@ pub struct UserInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
UserInner {
|
||||||
|
root_id: root_id,
|
||||||
handle_id: handle_id,
|
handle_id: handle_id,
|
||||||
flags: flags,
|
flags: flags,
|
||||||
scheme_id: ATOMIC_SCHEMEID_INIT,
|
scheme_id: ATOMIC_SCHEMEID_INIT,
|
||||||
|
@ -67,7 +68,7 @@ impl UserInner {
|
||||||
let id = packet.id;
|
let id = packet.id;
|
||||||
|
|
||||||
let len = self.todo.send(packet);
|
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))
|
Error::demux(self.done.receive(&id))
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,22 +82,22 @@ pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
|
||||||
|
|
||||||
/// Open syscall
|
/// Open syscall
|
||||||
pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
|
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 contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let context = context_lock.read();
|
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 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 reference_opt = parts.next();
|
||||||
|
|
||||||
let (scheme_id, file_id) = {
|
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 (scheme_id, scheme) = {
|
||||||
let schemes = scheme::schemes();
|
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())
|
(scheme_id, scheme.clone())
|
||||||
};
|
};
|
||||||
let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?;
|
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
|
/// mkdir syscall
|
||||||
pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> {
|
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 contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let context = context_lock.read();
|
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 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 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 scheme = {
|
||||||
let schemes = scheme::schemes();
|
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.clone()
|
||||||
};
|
};
|
||||||
scheme.mkdir(reference_opt.unwrap_or(b""), mode, uid, gid)
|
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
|
/// chmod syscall
|
||||||
pub fn chmod(path: &[u8], mode: u16) -> Result<usize> {
|
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 contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let context = context_lock.read();
|
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 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 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 scheme = {
|
||||||
let schemes = scheme::schemes();
|
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.clone()
|
||||||
};
|
};
|
||||||
scheme.chmod(reference_opt.unwrap_or(b""), mode, uid, gid)
|
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
|
/// rmdir syscall
|
||||||
pub fn rmdir(path: &[u8]) -> Result<usize> {
|
pub fn rmdir(path: &[u8]) -> Result<usize> {
|
||||||
let (path_canon, uid, gid) = {
|
let (path_canon, uid, gid, scheme_ns) = {
|
||||||
let contexts = context::contexts();
|
let contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let context = context_lock.read();
|
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 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 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 scheme = {
|
||||||
let schemes = scheme::schemes();
|
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.clone()
|
||||||
};
|
};
|
||||||
scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
|
scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
|
||||||
|
@ -212,21 +212,21 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
|
||||||
|
|
||||||
/// Unlink syscall
|
/// Unlink syscall
|
||||||
pub fn unlink(path: &[u8]) -> Result<usize> {
|
pub fn unlink(path: &[u8]) -> Result<usize> {
|
||||||
let (path_canon, uid, gid) = {
|
let (path_canon, uid, gid, scheme_ns) = {
|
||||||
let contexts = context::contexts();
|
let contexts = context::contexts();
|
||||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||||
let context = context_lock.read();
|
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 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 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 scheme = {
|
||||||
let schemes = scheme::schemes();
|
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.clone()
|
||||||
};
|
};
|
||||||
scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
|
scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
|
||||||
|
|
|
@ -19,7 +19,7 @@ use scheme::{self, FileHandle};
|
||||||
use syscall;
|
use syscall;
|
||||||
use syscall::data::Stat;
|
use syscall::data::Stat;
|
||||||
use syscall::error::*;
|
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};
|
use syscall::validate::{validate_slice, validate_slice_mut};
|
||||||
|
|
||||||
pub fn brk(address: usize) -> Result<usize> {
|
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 mut tls_option = None;
|
||||||
let grants;
|
let grants;
|
||||||
let name;
|
let name;
|
||||||
|
let scheme_ns;
|
||||||
let cwd;
|
let cwd;
|
||||||
let env;
|
let env;
|
||||||
let files;
|
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()));
|
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 {
|
if flags & CLONE_FS == CLONE_FS {
|
||||||
cwd = context.cwd.clone();
|
cwd = context.cwd.clone();
|
||||||
} else {
|
} else {
|
||||||
|
@ -433,6 +440,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
|
||||||
|
|
||||||
context.name = name;
|
context.name = name;
|
||||||
|
|
||||||
|
context.scheme_ns = scheme_ns;
|
||||||
|
|
||||||
context.cwd = cwd;
|
context.cwd = cwd;
|
||||||
|
|
||||||
context.env = env;
|
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…
Reference in a new issue