Implement unix permissions
This commit is contained in:
parent
10c88e7424
commit
f38426e458
19 changed files with 99 additions and 76 deletions
|
@ -33,7 +33,7 @@ pub extern fn debug_input(b: u8) {
|
|||
pub struct DebugScheme;
|
||||
|
||||
impl Scheme for DebugScheme {
|
||||
fn open(&self, _path: &[u8], _flags: usize) -> Result<usize> {
|
||||
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ impl EnvScheme {
|
|||
}
|
||||
|
||||
impl Scheme for EnvScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?.trim_matches('/');
|
||||
|
||||
let env_lock = {
|
||||
|
|
|
@ -24,7 +24,7 @@ impl EventScheme {
|
|||
}
|
||||
|
||||
impl Scheme for EventScheme {
|
||||
fn open(&self, _path: &[u8], _flags: usize) -> Result<usize> {
|
||||
fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let handle = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
|
|
|
@ -35,7 +35,7 @@ impl InitFsScheme {
|
|||
}
|
||||
|
||||
impl Scheme for InitFsScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_utf8 = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?;
|
||||
let path_trimmed = path_utf8.trim_matches('/');
|
||||
|
||||
|
@ -46,7 +46,7 @@ impl Scheme for InitFsScheme {
|
|||
self.handles.write().insert(id, Handle {
|
||||
path: entry.0,
|
||||
data: (entry.1).0,
|
||||
mode: if (entry.1).1 { MODE_DIR } else { MODE_FILE },
|
||||
mode: if (entry.1).1 { MODE_DIR | 0o755 } else { MODE_FILE | 0o744 },
|
||||
seek: 0
|
||||
});
|
||||
|
||||
|
@ -130,6 +130,8 @@ impl Scheme for InitFsScheme {
|
|||
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
stat.st_mode = handle.mode;
|
||||
stat.st_uid = 0;
|
||||
stat.st_gid = 0;
|
||||
stat.st_size = handle.data.len() as u64;
|
||||
|
||||
Ok(0)
|
||||
|
|
|
@ -7,7 +7,7 @@ use syscall::scheme::Scheme;
|
|||
pub struct IrqScheme;
|
||||
|
||||
impl Scheme for IrqScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
|
||||
|
||||
let id = path_str.parse::<usize>().or(Err(Error::new(ENOENT)))?;
|
||||
|
|
|
@ -25,7 +25,7 @@ impl RootScheme {
|
|||
}
|
||||
|
||||
impl Scheme for RootScheme {
|
||||
fn open(&self, path: &[u8], _flags: usize) -> Result<usize> {
|
||||
fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let context = {
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
|
|
|
@ -218,7 +218,7 @@ impl UserScheme {
|
|||
}
|
||||
|
||||
impl Scheme for UserScheme {
|
||||
fn open(&self, path: &[u8], flags: usize) -> Result<usize> {
|
||||
fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let result = inner.call(SYS_OPEN, address, path.len(), flags);
|
||||
|
@ -226,15 +226,15 @@ impl Scheme for UserScheme {
|
|||
result
|
||||
}
|
||||
|
||||
fn mkdir(&self, path: &[u8], mode: usize) -> Result<usize> {
|
||||
fn mkdir(&self, path: &[u8], mode: u16, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let result = inner.call(SYS_MKDIR, address, path.len(), mode);
|
||||
let result = inner.call(SYS_MKDIR, address, path.len(), mode as usize);
|
||||
let _ = inner.release(address);
|
||||
result
|
||||
}
|
||||
|
||||
fn rmdir(&self, path: &[u8]) -> Result<usize> {
|
||||
fn rmdir(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let result = inner.call(SYS_RMDIR, address, path.len(), 0);
|
||||
|
@ -242,7 +242,7 @@ impl Scheme for UserScheme {
|
|||
result
|
||||
}
|
||||
|
||||
fn unlink(&self, path: &[u8]) -> Result<usize> {
|
||||
fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address = inner.capture(path)?;
|
||||
let result = inner.call(SYS_UNLINK, address, path.len(), 0);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue