From 82d2c49543fa0c0d85360b45c58049adc64ff108 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 5 Oct 2016 14:24:08 -0600 Subject: [PATCH] Add permissions to the filesystem, preliminary permissions to the syscalls --- context/context.rs | 9 +++++++++ lib.rs | 1 + scheme/user.rs | 18 +++++++++++++---- syscall/mod.rs | 4 ++++ syscall/process.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/context/context.rs b/context/context.rs index 8f63755..512c66e 100644 --- a/context/context.rs +++ b/context/context.rs @@ -22,6 +22,10 @@ pub struct Context { pub id: usize, /// The ID of the parent context pub ppid: usize, + /// The user id + pub uid: u32, + /// The group id + pub gid: u32, /// Status of context pub status: Status, /// Context running or not @@ -58,6 +62,8 @@ impl Context { Context { id: id, ppid: 0, + uid: 0, + gid: 0, status: Status::Blocked, running: false, vfork: false, @@ -87,6 +93,9 @@ impl Context { .to_vec() } else if path.starts_with(b"./") { let mut canon = cwd.clone(); + if ! canon.ends_with(b"/") { + canon.push(b'/'); + } canon.extend_from_slice(&path[2..]); canon } else if path.starts_with(b"../") { diff --git a/lib.rs b/lib.rs index fee417c..f77da77 100644 --- a/lib.rs +++ b/lib.rs @@ -70,6 +70,7 @@ #![feature(const_fn)] #![feature(drop_types_in_const)] #![feature(heap_api)] +#![feature(integer_atomics)] #![feature(question_mark)] #![feature(never_type)] #![feature(thread_local)] diff --git a/scheme/user.rs b/scheme/user.rs index dd415cc..96ba87e 100644 --- a/scheme/user.rs +++ b/scheme/user.rs @@ -1,6 +1,6 @@ use alloc::arc::Weak; use collections::{BTreeMap, VecDeque}; -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::{AtomicUsize, AtomicU64, Ordering}; use core::{mem, usize}; use spin::{Mutex, RwLock}; @@ -16,17 +16,17 @@ use syscall::scheme::Scheme; pub struct UserInner { pub scheme_id: AtomicUsize, - next_id: AtomicUsize, + next_id: AtomicU64, context: Weak>, todo: Mutex>, - done: Mutex> + done: Mutex> } impl UserInner { pub fn new(context: Weak>) -> UserInner { UserInner { scheme_id: AtomicUsize::new(0), - next_id: AtomicUsize::new(1), + next_id: AtomicU64::new(1), context: context, todo: Mutex::new(VecDeque::new()), done: Mutex::new(BTreeMap::new()) @@ -34,10 +34,20 @@ impl UserInner { } pub fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result { + let (pid, uid, gid) = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + (context.id, context.uid, context.gid) + }; + let id = self.next_id.fetch_add(1, Ordering::SeqCst); let packet = Packet { id: id, + pid: pid, + uid: uid, + gid: gid, a: a, b: b, c: c, diff --git a/syscall/mod.rs b/syscall/mod.rs index d799da0..3c2523f 100644 --- a/syscall/mod.rs +++ b/syscall/mod.rs @@ -48,6 +48,10 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_CLONE => clone(b, stack), SYS_YIELD => sched_yield(), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), + SYS_GETUID => getuid(), + SYS_GETGID => getgid(), + SYS_SETUID => setuid(b as u32), + SYS_SETGID => setgid(b as u32), SYS_FEVENT => fevent(b, c), SYS_FPATH => fpath(b, validate_slice_mut(c as *mut u8, d)?), SYS_PHYSALLOC => physalloc(b), diff --git a/syscall/process.rs b/syscall/process.rs index d6da9f2..e8d001f 100644 --- a/syscall/process.rs +++ b/syscall/process.rs @@ -58,6 +58,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let ppid; let pid; { + let uid; + let gid; let arch; let vfork; let mut kfx_option = None; @@ -78,6 +80,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let context = context_lock.read(); ppid = context.id; + uid = context.uid; + gid = context.gid; arch = context.arch.clone(); @@ -249,6 +253,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { pid = context.id; context.ppid = ppid; + context.uid = uid; + context.gid = gid; context.status = context::Status::Runnable; @@ -452,6 +458,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { drop(context.stack.take()); context.grants = Arc::new(Mutex::new(Vec::new())); + // Map and copy new segments for segment in elf.segments() { if segment.p_type == program_header::PT_LOAD { let mut memory = context::memory::Memory::new( @@ -488,6 +495,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { } } + // Map heap context.heap = Some(context::memory::Memory::new( VirtualAddress::new(arch::USER_HEAP_OFFSET), 0, @@ -572,6 +580,13 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { unsafe { usermode(entry, sp); } } +pub fn getgid() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.gid as usize) +} + pub fn getpid() -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -579,6 +594,13 @@ pub fn getpid() -> Result { Ok(context.id) } +pub fn getuid() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.uid as usize) +} + pub fn iopl(_level: usize) -> Result { //TODO Ok(0) @@ -676,6 +698,34 @@ pub fn sched_yield() -> Result { Ok(0) } +pub fn setgid(gid: u32) -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let mut context = context_lock.write(); + if context.gid == 0 { + context.gid = gid; + Ok(0) + } else if context.gid == gid { + Ok(0) + } else { + Err(Error::new(EPERM)) + } +} + +pub fn setuid(uid: u32) -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let mut context = context_lock.write(); + if context.uid == 0 { + context.uid = uid; + Ok(0) + } else if context.uid == uid { + Ok(0) + } else { + Err(Error::new(EPERM)) + } +} + pub fn virttophys(virtual_address: usize) -> Result { let active_table = unsafe { ActivePageTable::new() }; match active_table.translate(VirtualAddress::new(virtual_address)) {