Implement unix permissions

This commit is contained in:
Jeremy Soller 2016-10-05 18:01:05 -06:00
parent 10c88e7424
commit f38426e458
19 changed files with 99 additions and 76 deletions

View file

@ -2,7 +2,7 @@
use context;
use scheme;
use syscall::data::{Packet, Stat};
use syscall::data::Packet;
use syscall::error::*;
pub fn file_op(a: usize, fd: usize, c: usize, d: usize) -> Result<usize> {
@ -70,11 +70,11 @@ pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
/// Open syscall
pub fn open(path: &[u8], flags: usize) -> Result<usize> {
let path_canon = {
let (path_canon, uid, gid) = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.canonicalize(path)
(context.canonicalize(path), context.uid, context.gid)
};
let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -88,7 +88,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
let (scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
(scheme_id, scheme.clone())
};
let file_id = scheme.open(reference_opt.unwrap_or(b""), flags)?;
let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?;
(scheme_id, file_id)
};
@ -102,12 +102,12 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
}
/// mkdir syscall
pub fn mkdir(path: &[u8], mode: usize) -> Result<usize> {
let path_canon = {
pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> {
let (path_canon, uid, gid) = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.canonicalize(path)
(context.canonicalize(path), context.uid, context.gid)
};
let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -120,16 +120,16 @@ pub fn mkdir(path: &[u8], mode: usize) -> Result<usize> {
let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
scheme.clone()
};
scheme.mkdir(reference_opt.unwrap_or(b""), mode)
scheme.mkdir(reference_opt.unwrap_or(b""), mode, uid, gid)
}
/// rmdir syscall
pub fn rmdir(path: &[u8]) -> Result<usize> {
let path_canon = {
let (path_canon, uid, gid) = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.canonicalize(path)
(context.canonicalize(path), context.uid, context.gid)
};
let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -142,16 +142,16 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
scheme.clone()
};
scheme.rmdir(reference_opt.unwrap_or(b""))
scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
}
/// Unlink syscall
pub fn unlink(path: &[u8]) -> Result<usize> {
let path_canon = {
let (path_canon, uid, gid) = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.canonicalize(path)
(context.canonicalize(path), context.uid, context.gid)
};
let mut parts = path_canon.splitn(2, |&b| b == b':');
@ -164,7 +164,7 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
scheme.clone()
};
scheme.unlink(reference_opt.unwrap_or(b""))
scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
}
/// Close syscall

View file

@ -37,6 +37,9 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
},
SYS_CLASS_PATH => match a {
SYS_OPEN => open(validate_slice(b as *const u8, c)?, d),
SYS_MKDIR => mkdir(validate_slice(b as *const u8, c)?, d as u16),
SYS_RMDIR => rmdir(validate_slice(b as *const u8, c)?),
SYS_UNLINK => unlink(validate_slice(b as *const u8, c)?),
_ => unreachable!()
},
_ => match a {

View file

@ -432,9 +432,33 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory
}
let (uid, gid) = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
(context.uid, context.gid)
};
let file = syscall::open(path, 0)?;
let mut stat = Stat::default();
syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file, &mut stat)?;
let mut perm = stat.st_mode & 0o7;
if stat.st_uid == uid {
perm |= (stat.st_mode >> 6) & 0o7;
}
if stat.st_gid == gid {
perm |= (stat.st_mode >> 3) & 0o7;
}
if uid == 0 {
perm |= 0o7;
}
if perm & 0o1 != 0o1 {
let _ = syscall::close(file);
return Err(Error::new(EACCES));
}
//TODO: Only read elf header, not entire file. Then read required segments
let mut data = vec![0; stat.st_size as usize];
syscall::file_op_mut_slice(syscall::number::SYS_READ, file, &mut data)?;
@ -458,6 +482,14 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
drop(context.stack.take());
context.grants = Arc::new(Mutex::new(Vec::new()));
if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID {
context.uid = stat.st_uid;
}
if stat.st_mode & syscall::flag::MODE_SETGID == syscall::flag::MODE_SETGID {
context.gid = stat.st_gid;
}
// Map and copy new segments
for segment in elf.segments() {
if segment.p_type == program_header::PT_LOAD {