Implement rfc 4

This commit is contained in:
Jeremy Soller 2016-11-25 12:09:54 -07:00
parent ecf9128fb0
commit 657394a7cb
10 changed files with 106 additions and 59 deletions

View file

@ -34,10 +34,14 @@ pub struct Context {
pub ruid: u32, pub ruid: u32,
/// The real group id /// The real group id
pub rgid: u32, pub rgid: u32,
/// The real namespace id
pub rns: SchemeNamespace,
/// The effective user id /// The effective user id
pub euid: u32, pub euid: u32,
/// The effective group id /// The effective group id
pub egid: u32, pub egid: u32,
/// The effective namespace id
pub ens: SchemeNamespace,
/// Status of context /// Status of context
pub status: Status, pub status: Status,
/// Context running or not /// Context running or not
@ -70,8 +74,6 @@ 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
@ -89,8 +91,10 @@ impl Context {
ppid: ContextId::from(0), ppid: ContextId::from(0),
ruid: 0, ruid: 0,
rgid: 0, rgid: 0,
rns: SchemeNamespace::from(0),
euid: 0, euid: 0,
egid: 0, egid: 0,
ens: SchemeNamespace::from(0),
status: Status::Blocked, status: Status::Blocked,
running: false, running: false,
cpu_id: None, cpu_id: None,
@ -107,7 +111,6 @@ 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())),

View file

@ -141,7 +141,7 @@ impl SchemeList {
self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::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> { pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result<SchemeNamespace> {
// Create an empty namespace // Create an empty namespace
let to = self.new_ns(); let to = self.new_ns();

View file

@ -5,17 +5,18 @@ use context;
use syscall::error::Result; use syscall::error::Result;
pub fn resource() -> Result<Vec<u8>> { pub fn resource() -> Result<Vec<u8>> {
let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<6}{}\n", let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
"PID", "PID",
"PPID", "PPID",
"RUID", "RUID",
"RGID", "RGID",
"RNS",
"EUID", "EUID",
"EGID", "EGID",
"ENS",
"STAT", "STAT",
"CPU", "CPU",
"MEM", "MEM",
"SNS",
"NAME"); "NAME");
{ {
let contexts = context::contexts(); let contexts = context::contexts();
@ -85,17 +86,18 @@ pub fn resource() -> Result<Vec<u8>> {
let name_bytes = context.name.lock(); let name_bytes = context.name.lock();
let name = str::from_utf8(&name_bytes).unwrap_or(""); let name = str::from_utf8(&name_bytes).unwrap_or("");
string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<6}{}\n", string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
context.id.into(), context.id.into(),
context.ppid.into(), context.ppid.into(),
context.ruid, context.ruid,
context.rgid, context.rgid,
context.rns.into(),
context.euid, context.euid,
context.egid, context.egid,
context.ens.into(),
stat_string, stat_string,
cpu_string, cpu_string,
memory_string, memory_string,
context.scheme_ns.into(),
name)); name));
} }
} }

View file

@ -9,7 +9,7 @@ pub fn resource() -> Result<Vec<u8>> {
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.scheme_ns context.ens
}; };
let mut data = Vec::new(); let mut data = Vec::new();

View file

@ -86,7 +86,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
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.scheme_ns) (context.canonicalize(path), context.euid, context.egid, context.ens)
}; };
let mut parts = path_canon.splitn(2, |&b| b == b':'); let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -150,7 +150,7 @@ pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> {
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.scheme_ns) (context.canonicalize(path), context.euid, context.egid, context.ens)
}; };
let mut parts = path_canon.splitn(2, |&b| b == b':'); let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -172,7 +172,7 @@ pub fn chmod(path: &[u8], mode: u16) -> Result<usize> {
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.scheme_ns) (context.canonicalize(path), context.euid, context.egid, context.ens)
}; };
let mut parts = path_canon.splitn(2, |&b| b == b':'); let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -194,7 +194,7 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
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.scheme_ns) (context.canonicalize(path), context.euid, context.egid, context.ens)
}; };
let mut parts = path_canon.splitn(2, |&b| b == b':'); let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -216,7 +216,7 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
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.scheme_ns) (context.canonicalize(path), context.euid, context.egid, context.ens)
}; };
let mut parts = path_canon.splitn(2, |&b| b == b':'); let mut parts = path_canon.splitn(2, |&b| b == b':');

View file

@ -17,7 +17,7 @@ use self::error::{Error, Result, ENOSYS};
use self::number::*; use self::number::*;
use context::ContextId; use context::ContextId;
use scheme::FileHandle; use scheme::{FileHandle, SchemeNamespace};
/// Driver syscalls /// Driver syscalls
pub mod driver; pub mod driver;
@ -82,13 +82,16 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?),
SYS_IOPL => iopl(b, stack), SYS_IOPL => iopl(b, stack),
SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
SYS_GETUID => getuid(),
SYS_GETGID => getgid(),
SYS_GETEUID => geteuid(),
SYS_GETEGID => getegid(), SYS_GETEGID => getegid(),
SYS_GETENS => getens(),
SYS_GETEUID => geteuid(),
SYS_GETGID => getgid(),
SYS_GETNS => getns(),
SYS_GETUID => getuid(),
SYS_MKNS => mkns(validate_slice(b as *const [usize; 2], c)?),
SYS_SETREUID => setreuid(b as u32, c as u32), SYS_SETREUID => setreuid(b as u32, c as u32),
SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)),
SYS_SETREGID => setregid(b as u32, c as u32), SYS_SETREGID => setregid(b as u32, c as u32),
SYS_SETNS => setns(validate_slice(b as *const [usize; 2], c)?),
SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c), SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c),
SYS_PHYSALLOC => physalloc(b), SYS_PHYSALLOC => physalloc(b),
SYS_PHYSFREE => physfree(b, c), SYS_PHYSFREE => physfree(b, c),

View file

@ -1,7 +1,7 @@
use collections::Vec; use collections::Vec;
use context; use context;
use scheme; use scheme::{self, SchemeNamespace};
use syscall::error::*; use syscall::error::*;
use syscall::validate::validate_slice; use syscall::validate::validate_slice;
@ -12,6 +12,13 @@ pub fn getegid() -> Result<usize> {
Ok(context.egid as usize) Ok(context.egid as usize)
} }
pub fn getens() -> Result<usize> {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
Ok(context.ens.into())
}
pub fn geteuid() -> Result<usize> { pub fn geteuid() -> Result<usize> {
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))?;
@ -26,6 +33,13 @@ pub fn getgid() -> Result<usize> {
Ok(context.rgid as usize) Ok(context.rgid as usize)
} }
pub fn getns() -> Result<usize> {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
Ok(context.rns.into())
}
pub fn getuid() -> Result<usize> { pub fn getuid() -> Result<usize> {
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))?;
@ -33,6 +47,27 @@ pub fn getuid() -> Result<usize> {
Ok(context.ruid as usize) Ok(context.ruid as usize)
} }
pub fn mkns(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 (uid, from) = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
(context.euid, context.ens)
};
if uid == 0 {
let to = scheme::schemes_mut().make_ns(from, &names)?;
Ok(to.into())
} else {
Err(Error::new(EACCES))
}
}
pub fn setregid(rgid: u32, egid: u32) -> Result<usize> { pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
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))?;
@ -59,6 +94,32 @@ pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
} }
} }
pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let mut context = context_lock.write();
if (context.euid == 0
|| rns.into() as isize == -1
|| rns == context.ens
|| rns == context.rns)
&& (context.euid == 0
|| ens.into() as isize == -1
|| ens == context.ens
|| ens == context.rns)
{
if rns.into() as isize != -1 {
context.rns = rns;
}
if ens.into() as isize != -1 {
context.ens = ens;
}
Ok(0)
} else {
Err(Error::new(EPERM))
}
}
pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> { pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
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))?;
@ -84,28 +145,3 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
Err(Error::new(EPERM)) Err(Error::new(EPERM))
} }
} }
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)
}

View file

@ -59,8 +59,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
{ {
let ruid; let ruid;
let rgid; let rgid;
let rns;
let euid; let euid;
let egid; let egid;
let ens;
let mut cpu_id = None; let mut cpu_id = None;
let arch; let arch;
let vfork; let vfork;
@ -73,7 +75,6 @@ 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;
@ -87,8 +88,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
ppid = context.id; ppid = context.id;
ruid = context.ruid; ruid = context.ruid;
rgid = context.rgid; rgid = context.rgid;
rns = context.rns;
euid = context.euid; euid = context.euid;
egid = context.egid; egid = context.egid;
ens = context.ens;
if flags & CLONE_VM == CLONE_VM { if flags & CLONE_VM == CLONE_VM {
cpu_id = context.cpu_id; cpu_id = context.cpu_id;
@ -222,8 +225,6 @@ 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()));
} }
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 {
@ -304,8 +305,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
context.ppid = ppid; context.ppid = ppid;
context.ruid = ruid; context.ruid = ruid;
context.rgid = rgid; context.rgid = rgid;
context.rns = rns;
context.euid = euid; context.euid = euid;
context.egid = egid; context.egid = egid;
context.ens = ens;
context.cpu_id = cpu_id; context.cpu_id = cpu_id;
@ -434,8 +437,6 @@ 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;

View file

@ -13,16 +13,18 @@ pub fn main() {
let command = "sh"; let command = "sh";
let pid = unsafe { syscall::clone(0).unwrap() };
if pid == 0 {
let mut name_ptrs = Vec::new(); let mut name_ptrs = Vec::new();
for name in names.iter() { for name in names.iter() {
name_ptrs.push([name.as_ptr() as usize, name.len()]); name_ptrs.push([name.as_ptr() as usize, name.len()]);
} }
syscall::setns(&name_ptrs).unwrap(); let new_ns = syscall::mkns(&name_ptrs).unwrap();
println!("Container enter: {}", command); let pid = unsafe { syscall::clone(0).unwrap() };
if pid == 0 {
syscall::setrens(new_ns, new_ns).unwrap();
println!("Container {}: enter: {}", new_ns, command);
let err = Command::new(command).exec(); let err = Command::new(command).exec();
@ -41,6 +43,6 @@ pub fn main() {
} }
} }
println!("Container exited: {:X}", status); println!("Container {}: exit: {:X}", new_ns, status);
} }
} }

@ -1 +1 @@
Subproject commit cc90408d147cc1d23b0e820d5b47522bd7dfc847 Subproject commit 2835586ee671b0777ef1a98ced9237269c472941