diff --git a/src/context/context.rs b/src/context/context.rs index 43cb667e1c..23819cff1b 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -20,7 +20,7 @@ use crate::context::memory::AddrSpace; use crate::ipi::{ipi, IpiKind, IpiTarget}; use crate::paging::{RmmA, RmmArch}; use crate::memory::{RaiiFrame, Frame}; -use crate::scheme::{SchemeNamespace, FileHandle}; +use crate::scheme::{SchemeNamespace, FileHandle, CallerCtx}; use crate::sync::WaitMap; use crate::syscall::data::SigAction; @@ -472,6 +472,9 @@ impl Context { 0 ); 128])) } + pub fn caller_ctx(&self) -> CallerCtx { + CallerCtx { pid: self.id.into(), uid: self.euid, gid: self.egid } + } } /// Wrapper struct for borrowing the syscall head or tail buf. diff --git a/src/context/file.rs b/src/context/file.rs index 85433b3781..fb87a3c470 100644 --- a/src/context/file.rs +++ b/src/context/file.rs @@ -32,7 +32,7 @@ pub struct FileDescriptor { impl FileDescription { /// Try closing a file, although at this point the description will be destroyed anyway, if /// doing so fails. - pub fn try_close(self) -> Result { + pub fn try_close(self) -> Result<()> { event::unregister_file(self.scheme, self.number); let scheme = Arc::clone( @@ -44,11 +44,10 @@ impl FileDescription { } impl FileDescriptor { - pub fn close(self) -> Result { - let Ok(file) = Arc::try_unwrap(self.description) else { - return Ok(0); - }; - - file.into_inner().try_close() + pub fn close(self) -> Result<()> { + if let Ok(file) = Arc::try_unwrap(self.description) { + file.into_inner().try_close()?; + } + Ok(()) } } diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index 1800f40e53..eded6a6951 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -20,10 +20,11 @@ use crate::syscall::flag::{ O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_STAT, O_SYMLINK, SEEK_SET, SEEK_CUR, SEEK_END, }; -use crate::syscall::scheme::Scheme; use crate::syscall::error::{Error, Result}; use crate::syscall::usercopy::{UserSliceRo, UserSliceWo}; +use super::{KernelScheme, CallerCtx, OpenResult}; + /// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function. pub struct AcpiScheme; @@ -113,11 +114,11 @@ impl AcpiScheme { } } -impl Scheme for AcpiScheme { - fn open(&self, path: &str, flags: usize, opener_uid: u32, _opener_gid: u32) -> Result { +impl KernelScheme for AcpiScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { let path = path.trim_start_matches('/'); - if opener_uid != 0 { + if ctx.uid != 0 { return Err(Error::new(EACCES)); } if flags & O_CREAT == O_CREAT { @@ -161,9 +162,9 @@ impl Scheme for AcpiScheme { stat: flags & O_STAT == O_STAT, }); - Ok(fd) + Ok(OpenResult::SchemeLocal(fd)) } - fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { + fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { let mut handles = HANDLES.write(); let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; @@ -194,7 +195,7 @@ impl Scheme for AcpiScheme { handle.offset = new_offset; - Ok(new_offset as isize) + Ok(new_offset) } // TODO fn fevent(&self, id: usize, _flags: EventFlags) -> Result { @@ -207,14 +208,12 @@ impl Scheme for AcpiScheme { Ok(EventFlags::empty()) } - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { if HANDLES.write().remove(&id).is_none() { return Err(Error::new(EBADF)); } - Ok(0) + Ok(()) } -} -impl crate::scheme::KernelScheme for AcpiScheme { fn kwrite(&self, _id: usize, _buf: UserSliceRo) -> Result { Err(Error::new(EBADF)) } @@ -260,7 +259,7 @@ impl crate::scheme::KernelScheme for AcpiScheme { Ok(bytes_copied) } - fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result { + fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> { let handles = HANDLES.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; @@ -286,6 +285,6 @@ impl crate::scheme::KernelScheme for AcpiScheme { }, })?; - Ok(0) + Ok(()) } } diff --git a/src/scheme/debug.rs b/src/scheme/debug.rs index e232cc9a2a..f849400969 100644 --- a/src/scheme/debug.rs +++ b/src/scheme/debug.rs @@ -1,12 +1,11 @@ use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use spin::{Once, RwLock}; use crate::arch::debug::Writer; use crate::event; use crate::scheme::*; use crate::sync::WaitQueue; use crate::syscall::flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::UserSliceRo; use crate::syscall::usercopy::UserSliceWo; @@ -22,19 +21,7 @@ struct Handle { flags: usize, } -static HANDLES: Once>> = Once::new(); - -fn init_handles() -> RwLock> { - RwLock::new(BTreeMap::new()) -} - -fn handles() -> RwLockReadGuard<'static, BTreeMap> { - HANDLES.call_once(init_handles).read() -} - -fn handles_mut() -> RwLockWriteGuard<'static, BTreeMap> { - HANDLES.call_once(init_handles).write() -} +static HANDLES: RwLock> = RwLock::new(BTreeMap::new()); /// Add to the input queue pub fn debug_input(data: u8) { @@ -47,7 +34,7 @@ pub fn debug_notify() { return; }; - for (id, _handle) in handles().iter() { + for (id, _handle) in HANDLES.read().iter() { event::trigger(scheme_id, *id, EVENT_READ); } } @@ -61,9 +48,9 @@ impl DebugScheme { } } -impl Scheme for DebugScheme { - fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { - if uid != 0 { +impl KernelScheme for DebugScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { + if ctx.uid != 0 { return Err(Error::new(EPERM)); } @@ -71,16 +58,16 @@ impl Scheme for DebugScheme { return Err(Error::new(ENOENT)); } - let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); - handles_mut().insert(id, Handle { + let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); + HANDLES.write().insert(id, Handle { flags: flags & ! O_ACCMODE }); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { - let mut handles = handles_mut(); + let mut handles = HANDLES.write(); if let Some(handle) = handles.get_mut(&id) { match cmd { F_GETFL => Ok(handle.flags), @@ -97,36 +84,34 @@ impl Scheme for DebugScheme { fn fevent(&self, id: usize, _flags: EventFlags) -> Result { let _handle = { - let handles = handles(); + let handles = HANDLES.read(); *handles.get(&id).ok_or(Error::new(EBADF))? }; Ok(EventFlags::empty()) } - fn fsync(&self, id: usize) -> Result { + fn fsync(&self, id: usize) -> Result<()> { let _handle = { - let handles = handles(); + let handles = HANDLES.read(); *handles.get(&id).ok_or(Error::new(EBADF))? }; - Ok(0) + Ok(()) } /// Close the file `number` - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { let _handle = { - let mut handles = handles_mut(); + let mut handles = HANDLES.write(); handles.remove(&id).ok_or(Error::new(EBADF))? }; - Ok(0) + Ok(()) } -} -impl crate::scheme::KernelScheme for DebugScheme { fn kread(&self, id: usize, buf: UserSliceWo) -> Result { let handle = { - let handles = handles(); + let handles = HANDLES.read(); *handles.get(&id).ok_or(Error::new(EBADF))? }; @@ -136,7 +121,7 @@ impl crate::scheme::KernelScheme for DebugScheme { fn kwrite(&self, id: usize, buf: UserSliceRo) -> Result { let _handle = { - let handles = handles(); + let handles = HANDLES.read(); *handles.get(&id).ok_or(Error::new(EBADF))? }; @@ -156,7 +141,7 @@ impl crate::scheme::KernelScheme for DebugScheme { } fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result { let _handle = { - let handles = handles(); + let handles = HANDLES.read(); *handles.get(&id).ok_or(Error::new(EBADF))? }; diff --git a/src/scheme/event.rs b/src/scheme/event.rs index 73ff9b88ac..2bcc2c5ae7 100644 --- a/src/scheme/event.rs +++ b/src/scheme/event.rs @@ -4,20 +4,20 @@ use core::mem; use crate::event::{EventQueue, EventQueueId, next_queue_id, queues, queues_mut}; use crate::syscall::data::Event; use crate::syscall::error::*; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::{UserSliceWo, UserSliceRo}; +use super::{KernelScheme, CallerCtx, OpenResult}; + pub struct EventScheme; -impl Scheme for EventScheme { - fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { +impl KernelScheme for EventScheme { + fn kopen(&self, _path: &str, _flags: usize, _ctx: CallerCtx) -> Result { let id = next_queue_id(); queues_mut().insert(id, Arc::new(EventQueue::new(id))); - Ok(id.into()) + Ok(OpenResult::SchemeLocal(id.get())) } - fn fcntl(&self, id: usize, _cmd: usize, _arg: usize) -> Result { let id = EventQueueId::from(id); @@ -25,19 +25,17 @@ impl Scheme for EventScheme { handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0)) } - fn fsync(&self, id: usize) -> Result { + fn fsync(&self, id: usize) -> Result<()> { let id = EventQueueId::from(id); let handles = queues(); - handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(())) } - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { let id = EventQueueId::from(id); - queues_mut().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + queues_mut().remove(&id).ok_or(Error::new(EBADF)).and(Ok(())) } -} -impl crate::scheme::KernelScheme for EventScheme { fn kread(&self, id: usize, buf: UserSliceWo) -> Result { let id = EventQueueId::from(id); diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 749560cfd9..fd75baae0b 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -16,9 +16,10 @@ use crate::scheme::SchemeId; use crate::syscall::data::Stat; use crate::syscall::error::*; use crate::syscall::flag::{EventFlags, EVENT_READ, O_DIRECTORY, O_CREAT, O_STAT, MODE_CHR, MODE_DIR}; -use crate::syscall::scheme::{calc_seek_offset_usize, Scheme}; use crate::syscall::usercopy::{UserSliceWo, UserSliceRo}; +use super::{OpenResult, CallerCtx, calc_seek_offset}; + pub static IRQ_SCHEME_ID: Once = Once::new(); /// IRQ queues @@ -146,9 +147,9 @@ const fn vector_to_irq(vector: u8) -> u8 { vector - 32 } -impl Scheme for IrqScheme { - fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { - if uid != 0 { return Err(Error::new(EACCES)) } +impl crate::scheme::KernelScheme for IrqScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { + if ctx.uid != 0 { return Err(Error::new(EACCES)) } let path_str = path.trim_start_matches('/'); @@ -213,21 +214,21 @@ impl Scheme for IrqScheme { return Err(Error::new(ENOENT)); } }; - let fd = self.next_fd.fetch_add(1, Ordering::SeqCst); + let fd = self.next_fd.fetch_add(1, Ordering::Relaxed); HANDLES.write().as_mut().unwrap().insert(fd, handle); - Ok(fd) + Ok(OpenResult::SchemeLocal(fd)) } - fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { + fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { let handles_guard = HANDLES.read(); let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; match handle { &Handle::Avail(_, ref buf, ref offset) | &Handle::TopLevel(ref buf, ref offset) => { let cur_offset = offset.load(Ordering::SeqCst); - let new_offset = calc_seek_offset_usize(cur_offset, pos, whence, buf.len())?; + let new_offset = calc_seek_offset(cur_offset, pos, whence, buf.len())?; offset.store(new_offset as usize, Ordering::SeqCst); - Ok(new_offset) + Ok(new_offset as usize) } _ => Err(Error::new(ESPIPE)), } @@ -243,11 +244,11 @@ impl Scheme for IrqScheme { } - fn fsync(&self, _file: usize) -> Result { - Ok(0) + fn fsync(&self, _file: usize) -> Result<()> { + Ok(()) } - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { let handles_guard = HANDLES.read(); let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; @@ -256,10 +257,8 @@ impl Scheme for IrqScheme { set_reserved(LogicalCpuId::BSP, irq_to_vector(handle_irq), false); } } - Ok(0) + Ok(()) } -} -impl crate::scheme::KernelScheme for IrqScheme { fn kwrite(&self, file: usize, buffer: UserSliceRo) -> Result { let handles_guard = HANDLES.read(); let handle = handles_guard.as_ref().unwrap().get(&file).ok_or(Error::new(EBADF))?; @@ -283,7 +282,7 @@ impl crate::scheme::KernelScheme for IrqScheme { } } - fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result { + fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> { let handles_guard = HANDLES.read(); let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?; @@ -321,7 +320,8 @@ impl crate::scheme::KernelScheme for IrqScheme { ..Default::default() }, })?; - Ok(0) + + Ok(()) } fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result { let handles_guard = HANDLES.read(); diff --git a/src/scheme/itimer.rs b/src/scheme/itimer.rs index bccc7c6f28..d8babc306a 100644 --- a/src/scheme/itimer.rs +++ b/src/scheme/itimer.rs @@ -6,9 +6,10 @@ use spin::RwLock; use crate::syscall::data::ITimerSpec; use crate::syscall::error::*; use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC, EventFlags}; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::{UserSliceWo, UserSliceRo}; +use super::{KernelScheme, CallerCtx, OpenResult}; + pub struct ITimerScheme { next_id: AtomicUsize, handles: RwLock> @@ -23,8 +24,8 @@ impl ITimerScheme { } } -impl Scheme for ITimerScheme { - fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { +impl KernelScheme for ITimerScheme { + fn kopen(&self, path: &str, _flags: usize, _ctx: CallerCtx) -> Result { let clock = path.parse::().or(Err(Error::new(ENOENT)))?; match clock { @@ -33,10 +34,10 @@ impl Scheme for ITimerScheme { _ => return Err(Error::new(ENOENT)) } - let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let id = self.next_id.fetch_add(1, Ordering::Relaxed); self.handles.write().insert(id, clock); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result { @@ -48,16 +49,14 @@ impl Scheme for ITimerScheme { handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(EventFlags::empty())) } - fn fsync(&self, id: usize) -> Result { + fn fsync(&self, id: usize) -> Result<()> { let handles = self.handles.read(); - handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(())) } - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + fn close(&self, id: usize) -> Result<()> { + self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(())) } -} -impl crate::scheme::KernelScheme for ITimerScheme { fn kread(&self, id: usize, buf: UserSliceWo) -> Result { let _clock = { let handles = self.handles.read(); diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index 8ff5b6ebd4..fb4c3d2d30 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -15,10 +15,9 @@ use crate::paging::entry::EntryFlags; use crate::syscall::data::{Map, StatVfs}; use crate::syscall::flag::MapFlags; use crate::syscall::error::*; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::UserSliceWo; -use super::KernelScheme; +use super::{KernelScheme, CallerCtx, OpenResult}; pub struct MemoryScheme; @@ -118,8 +117,8 @@ impl MemoryScheme { } } -impl Scheme for MemoryScheme { - fn open(&self, path: &str, _flags: usize, uid: u32, _gid: u32) -> Result { +impl KernelScheme for MemoryScheme { + fn kopen(&self, path: &str, _flags: usize, ctx: CallerCtx) -> Result { let intended_handle = match path.trim_start_matches('/') { "" => Handle::Anonymous, "physical" | "physical@wb" => Handle::PhysicalWb, @@ -129,22 +128,20 @@ impl Scheme for MemoryScheme { _ => return Err(Error::new(ENOENT)), }; - if uid != 0 && !matches!(intended_handle, Handle::Anonymous) { + if ctx.uid != 0 && !matches!(intended_handle, Handle::Anonymous) { return Err(Error::new(EACCES)); } - Ok(intended_handle as usize) + Ok(OpenResult::SchemeLocal(intended_handle as usize)) } fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result { Ok(0) } - fn close(&self, _id: usize) -> Result { - Ok(0) + fn close(&self, _id: usize) -> Result<()> { + Ok(()) } -} -impl KernelScheme for MemoryScheme { fn kfmap(&self, id: usize, addr_space: &Arc>, map: &Map, _consume: bool) -> Result { match Handle::from_raw(id).ok_or(Error::new(EBADF))? { Handle::Anonymous => Self::fmap_anonymous(addr_space, map), @@ -163,7 +160,7 @@ impl KernelScheme for MemoryScheme { }; dst.copy_common_bytes_from_slice(src.as_bytes()) } - fn kfstatvfs(&self, _file: usize, dst: UserSliceWo) -> Result { + fn kfstatvfs(&self, _file: usize, dst: UserSliceWo) -> Result<()> { let used = used_frames() as u64; let free = free_frames() as u64; @@ -175,6 +172,6 @@ impl KernelScheme for MemoryScheme { }; dst.copy_exactly(&stat)?; - Ok(0) + Ok(()) } } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 2b1ef18f0c..9c29da2b38 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -13,14 +13,13 @@ use alloc::{ sync::Arc, vec::Vec, }; -use syscall::{CallerCtx, MunmapFlags, SendFdFlags}; +use syscall::{MunmapFlags, SendFdFlags, EventFlags, SEEK_SET, SEEK_CUR, SEEK_END}; use core::sync::atomic::AtomicUsize; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::context::file::FileDescription; use crate::context::{memory::AddrSpace, file::FileDescriptor}; use crate::syscall::error::*; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::{UserSliceRo, UserSliceWo}; #[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))] @@ -299,7 +298,11 @@ pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> { } #[allow(unused_variables)] -pub trait KernelScheme: Scheme + Send + Sync + 'static { +pub trait KernelScheme: Send + Sync + 'static { + fn kopen(&self, path: &str, flags: usize, _ctx: CallerCtx) -> Result { + Err(Error::new(ENOENT)) + } + fn as_filetable(&self, number: usize) -> Result>>>> { Err(Error::new(EBADF)) } @@ -317,9 +320,6 @@ pub trait KernelScheme: Scheme + Send + Sync + 'static { Err(Error::new(EOPNOTSUPP)) } - fn kopen(&self, path: &str, flags: usize, caller: CallerCtx) -> Result { - self.open(path, flags, caller.uid, caller.gid).map(OpenResult::SchemeLocal) - } fn kdup(&self, old_id: usize, buf: UserSliceRo, _caller: CallerCtx) -> Result { Err(Error::new(EOPNOTSUPP)) } @@ -335,10 +335,10 @@ pub trait KernelScheme: Scheme + Send + Sync + 'static { fn kfutimens(&self, id: usize, buf: UserSliceRo) -> Result { Err(Error::new(EBADF)) } - fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result { + fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> { Err(Error::new(EBADF)) } - fn kfstatvfs(&self, id: usize, buf: UserSliceWo) -> Result { + fn kfstatvfs(&self, id: usize, buf: UserSliceWo) -> Result<()> { Err(Error::new(EBADF)) } @@ -346,6 +346,40 @@ pub trait KernelScheme: Scheme + Send + Sync + 'static { Err(Error::new(EOPNOTSUPP)) } + fn fsync(&self, id: usize) -> Result<()> { + Err(Error::new(EBADF)) + } + fn ftruncate(&self, id: usize, len: usize) -> Result<()> { + Err(Error::new(EBADF)) + } + fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { + Err(Error::new(ESPIPE)) + } + fn fchmod(&self, id: usize, new_mode: u16) -> Result<()> { + Err(Error::new(EBADF)) + } + fn fchown(&self, id: usize, new_uid: u32, new_gid: u32) -> Result<()> { + Err(Error::new(EBADF)) + } + fn fevent(&self, id: usize, flags: EventFlags) -> Result { + Err(Error::new(EBADF)) + } + fn frename(&self, id: usize, new_path: &str, caller_ctx: CallerCtx) -> Result<()> { + Err(Error::new(EBADF)) + } + fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { + Err(Error::new(EBADF)) + } + fn rmdir(&self, path: &str, ctx: CallerCtx) -> Result<()> { + Err(Error::new(ENOENT)) + } + fn unlink(&self, path: &str, ctx: CallerCtx) -> Result<()> { + Err(Error::new(ENOENT)) + } + fn close(&self, id: usize) -> Result<()> { + Err(Error::new(EBADF)) + } + // TODO: This demonstrates why we need to transition away from a dyn trait. fn as_user_inner(&self) -> Option>> { None } } @@ -355,9 +389,18 @@ pub enum OpenResult { SchemeLocal(usize), External(Arc>), } +pub struct CallerCtx { + pub pid: usize, + pub uid: u32, + pub gid: u32, +} -pub fn current_caller_ctx() -> Result { - match crate::context::current()?.read() { - ref context => Ok(CallerCtx { pid: context.id.into(), uid: context.euid, gid: context.egid }), +pub fn calc_seek_offset(cur_pos: usize, rel_pos: isize, whence: usize, len: usize) -> Result { + match whence { + SEEK_SET => usize::try_from(rel_pos).map_err(|_| Error::new(EINVAL)), + SEEK_CUR => cur_pos.checked_add_signed(rel_pos).ok_or(Error::new(EOVERFLOW)), + SEEK_END => len.checked_add_signed(rel_pos).ok_or(Error::new(EOVERFLOW)), + + _ => return Err(Error::new(EINVAL)), } } diff --git a/src/scheme/pipe.rs b/src/scheme/pipe.rs index edfd6ed565..5cd1503ba3 100644 --- a/src/scheme/pipe.rs +++ b/src/scheme/pipe.rs @@ -10,11 +10,10 @@ use crate::scheme::SchemeId; use crate::sync::WaitCondition; use crate::syscall::error::{Error, Result, EAGAIN, EBADF, EINTR, EINVAL, ENOENT, EPIPE, ESPIPE}; use crate::syscall::flag::{EventFlags, EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_FIFO}; -use crate::syscall::scheme::{CallerCtx, Scheme}; use crate::syscall::data::Stat; use crate::syscall::usercopy::{UserSliceWo, UserSliceRo}; -use super::{KernelScheme, OpenResult}; +use super::{KernelScheme, OpenResult, CallerCtx}; // TODO: Preallocate a number of scheme IDs, since there can only be *one* root namespace, and // therefore only *one* pipe scheme. @@ -65,8 +64,7 @@ impl PipeScheme { } } -impl Scheme for PipeScheme { - +impl KernelScheme for PipeScheme { fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { let (is_writer_not_reader, key) = from_raw_id(id); let pipe = Arc::clone(PIPES.read().get(&key).ok_or(Error::new(EBADF))?); @@ -106,11 +104,11 @@ impl Scheme for PipeScheme { Err(Error::new(EBADF)) } - fn fsync(&self, _id: usize) -> Result { - Ok(0) + fn fsync(&self, _id: usize) -> Result<()> { + Ok(()) } - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { let (is_write_not_read, key) = from_raw_id(id); let pipe = Arc::clone(PIPES.read().get(&key).ok_or(Error::new(EBADF))?); @@ -136,26 +134,12 @@ impl Scheme for PipeScheme { let _ = PIPES.write().remove(&key); } - Ok(0) + Ok(()) } - fn seek(&self, _id: usize, _pos: isize, _whence: usize) -> Result { + fn seek(&self, _id: usize, _pos: isize, _whence: usize) -> Result { Err(Error::new(ESPIPE)) } -} - -pub struct Pipe { - read_flags: AtomicUsize, // fcntl read flags - write_flags: AtomicUsize, // fcntl write flags - read_condition: WaitCondition, // signals whether there are available bytes to read - write_condition: WaitCondition, // signals whether there is room for additional bytes - queue: Mutex>, - reader_is_alive: AtomicBool, // starts set, unset when reader closes - writer_is_alive: AtomicBool, // starts set, unset when writer closes - has_run_dup: AtomicBool, -} - -impl KernelScheme for PipeScheme { fn kdup(&self, old_id: usize, user_buf: UserSliceRo, _ctx: CallerCtx) -> Result { let (is_writer_not_reader, key) = from_raw_id(old_id); @@ -277,12 +261,23 @@ impl KernelScheme for PipeScheme { } } } - fn kfstat(&self, _id: usize, buf: UserSliceWo) -> Result { + fn kfstat(&self, _id: usize, buf: UserSliceWo) -> Result<()> { buf.copy_exactly(&Stat { st_mode: MODE_FIFO | 0o666, ..Default::default() })?; - Ok(0) + Ok(()) } } + +pub struct Pipe { + read_flags: AtomicUsize, // fcntl read flags + write_flags: AtomicUsize, // fcntl write flags + read_condition: WaitCondition, // signals whether there are available bytes to read + write_condition: WaitCondition, // signals whether there is room for additional bytes + queue: Mutex>, + reader_is_alive: AtomicBool, // starts set, unset when reader closes + writer_is_alive: AtomicBool, // starts set, unset when writer closes + has_run_dup: AtomicBool, +} diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index ece25f5a29..6183b87b06 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -11,7 +11,6 @@ use crate::{ data::{GrantDesc, Map, PtraceEvent, SigAction, Stat}, error::*, flag::*, - scheme::{CallerCtx, Scheme}, self, usercopy::{UserSliceWo, UserSliceRo}, }, LogicalCpuId, LogicalCpuSet, }; @@ -31,7 +30,7 @@ use core::{ }; use spin::{Once, RwLock}; -use super::OpenResult; +use super::{OpenResult, CallerCtx}; fn read_from(dst: UserSliceWo, src: &[u8], offset: &mut usize) -> Result { let avail_src = src.get(*offset..).unwrap_or(&[]); @@ -514,8 +513,8 @@ impl ProcScheme { } } -impl Scheme for ProcScheme { - fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result { +impl KernelScheme for ProcScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { let mut parts = path.splitn(2, '/'); let pid_str = parts.next() .ok_or(Error::new(ENOENT))?; @@ -530,7 +529,7 @@ impl Scheme for ProcScheme { ContextId::new(pid_str.parse().map_err(|_| Error::new(ENOENT))?) }; - self.open_inner(pid, parts.next(), flags, uid, gid) + self.open_inner(pid, parts.next(), flags, ctx.uid, ctx.gid).map(OpenResult::SchemeLocal) } fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { @@ -557,7 +556,7 @@ impl Scheme for ProcScheme { } - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { let mut handle = self.handles.write().remove(&id).ok_or(Error::new(EBADF))?; handle.continue_ignored_children(); @@ -617,10 +616,8 @@ impl Scheme for ProcScheme { } _ => (), } - Ok(0) + Ok(()) } -} -impl KernelScheme for ProcScheme { fn as_addrspace(&self, number: usize) -> Result>> { if let Operation::AddrSpace { ref addrspace } = self.handles.read().get(&number).ok_or(Error::new(EBADF))?.info.operation { Ok(Arc::clone(addrspace)) @@ -1094,7 +1091,7 @@ impl KernelScheme for ProcScheme { buf.copy_common_bytes_from_slice(path.as_bytes()) } - fn kfstat(&self, id: usize, buffer: UserSliceWo) -> Result { + fn kfstat(&self, id: usize, buffer: UserSliceWo) -> Result<()> { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; @@ -1108,7 +1105,7 @@ impl KernelScheme for ProcScheme { ..Stat::default() })?; - Ok(0) + Ok(()) } /// Dup is currently used to implement clone() and execve(). diff --git a/src/scheme/root.rs b/src/scheme/root.rs index 6a8fb88419..4bdbb6b910 100644 --- a/src/scheme/root.rs +++ b/src/scheme/root.rs @@ -13,11 +13,12 @@ use crate::context; use crate::syscall::data::Stat; use crate::syscall::error::*; use crate::syscall::flag::{EventFlags, O_CREAT, MODE_FILE, MODE_DIR}; -use crate::syscall::scheme::{calc_seek_offset_usize, Scheme}; use crate::scheme::{self, SchemeNamespace, SchemeId}; use crate::scheme::user::{UserInner, UserScheme}; use crate::syscall::usercopy::{UserSliceWo, UserSliceRo}; +use super::{KernelScheme, CallerCtx, OpenResult, calc_seek_offset}; + struct FolderInner { data: Box<[u8]>, pos: Mutex @@ -34,9 +35,9 @@ impl FolderInner { Ok(bytes_read) } - fn seek(&self, pos: isize, whence: usize) -> Result { + fn seek(&self, pos: isize, whence: usize) -> Result { let mut seek = self.pos.lock(); - let new_offset = calc_seek_offset_usize(*seek, pos, whence, self.data.len())?; + let new_offset = calc_seek_offset(*seek, pos, whence, self.data.len())?; *seek = new_offset as usize; Ok(new_offset) } @@ -67,13 +68,13 @@ impl RootScheme { } } -impl Scheme for RootScheme { - fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { - let path = path.trim_matches('/'); +impl KernelScheme for RootScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { + let path = path.trim_start_matches('/'); //TODO: Make this follow standards for flags and errors if flags & O_CREAT == O_CREAT { - if uid != 0 { + if ctx.uid != 0 { return Err(Error::new(EACCES)); }; @@ -103,7 +104,7 @@ impl Scheme for RootScheme { self.handles.write().insert(id, Handle::Scheme(inner)); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } else if path.is_empty() { let scheme_ns = { let contexts = context::contexts(); @@ -126,47 +127,46 @@ impl Scheme for RootScheme { pos: Mutex::new(0) }); - let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let id = self.next_id.fetch_add(1, Ordering::Relaxed); self.handles.write().insert(id, Handle::Folder(inner)); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } else { let inner = Arc::new( path.as_bytes().to_vec().into_boxed_slice() ); - let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let id = self.next_id.fetch_add(1, Ordering::Relaxed); self.handles.write().insert(id, Handle::File(inner)); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } } - fn unlink(&self, path: &str, uid: u32, _gid: u32) -> Result { + fn unlink(&self, path: &str, ctx: CallerCtx) -> Result<()> { let path = path.trim_matches('/'); - if uid == 0 { - let inner = { - let handles = self.handles.read(); - handles.iter().find_map(|(_id, handle)| { - match handle { - Handle::Scheme(inner) => { - if path == inner.name.as_ref() { - return Some(inner.clone()); - } - }, - _ => (), - } - None - }).ok_or(Error::new(ENOENT))? - }; - - inner.unmount() - } else { - Err(Error::new(EACCES)) + if ctx.uid != 0 { + return Err(Error::new(EACCES)); } + let inner = { + let handles = self.handles.read(); + handles.iter().find_map(|(_id, handle)| { + match handle { + Handle::Scheme(inner) => { + if path == inner.name.as_ref() { + return Some(inner.clone()); + } + }, + _ => (), + } + None + }).ok_or(Error::new(ENOENT))? + }; + + inner.unmount() } - fn seek(&self, file: usize, pos: isize, whence: usize) -> Result { + fn seek(&self, file: usize, pos: isize, whence: usize) -> Result { let handle = { let handles = self.handles.read(); let handle = handles.get(&file).ok_or(Error::new(EBADF))?; @@ -206,45 +206,30 @@ impl Scheme for RootScheme { } } - fn fpath(&self, file: usize, buf: &mut [u8]) -> Result { + fn kfpath(&self, file: usize, mut buf: UserSliceWo) -> Result { let handle = { let handles = self.handles.read(); let handle = handles.get(&file).ok_or(Error::new(EBADF))?; handle.clone() }; - let mut i = 0; - let scheme_path = b":"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } + let mut bytes_copied = buf.copy_common_bytes_from_slice(b":")?; + buf = buf.advance(bytes_copied).ok_or(Error::new(EINVAL))?; match handle { Handle::Scheme(inner) => { - let name = inner.name.as_bytes(); - let mut j = 0; - while i < buf.len() && j < name.len() { - buf[i] = name[j]; - i += 1; - j += 1; - } + bytes_copied += buf.copy_common_bytes_from_slice(inner.name.as_bytes())?; }, Handle::File(inner) => { - let mut j = 0; - while i < buf.len() && j < inner.len() { - buf[i] = inner[j]; - i += 1; - j += 1; - } + bytes_copied += buf.copy_common_bytes_from_slice(&inner)?; }, Handle::Folder(_) => () } - Ok(i) + Ok(bytes_copied) } - fn fsync(&self, file: usize) -> Result { + fn fsync(&self, file: usize) -> Result<()> { let handle = { let handles = self.handles.read(); let handle = handles.get(&file).ok_or(Error::new(EBADF))?; @@ -264,7 +249,7 @@ impl Scheme for RootScheme { } } - fn close(&self, file: usize) -> Result { + fn close(&self, file: usize) -> Result<()> { let handle = self.handles.write().remove(&file).ok_or(Error::new(EBADF))?; match handle { Handle::Scheme(inner) => { @@ -272,10 +257,8 @@ impl Scheme for RootScheme { }, _ => () } - Ok(0) + Ok(()) } -} -impl crate::scheme::KernelScheme for RootScheme { fn kread(&self, file: usize, buf: UserSliceWo) -> Result { let handle = { let handles = self.handles.read(); @@ -316,7 +299,7 @@ impl crate::scheme::KernelScheme for RootScheme { } } - fn kfstat(&self, file: usize, buf: UserSliceWo) -> Result { + fn kfstat(&self, file: usize, buf: UserSliceWo) -> Result<()> { let handle = { let handles = self.handles.read(); let handle = handles.get(&file).ok_or(Error::new(EBADF))?; @@ -347,7 +330,7 @@ impl crate::scheme::KernelScheme for RootScheme { } })?; - Ok(0) + Ok(()) } } diff --git a/src/scheme/serio.rs b/src/scheme/serio.rs index f11bb52f8f..1335d5dca5 100644 --- a/src/scheme/serio.rs +++ b/src/scheme/serio.rs @@ -9,7 +9,6 @@ use crate::event; use crate::scheme::*; use crate::sync::WaitQueue; use crate::syscall::flag::{EventFlags, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::UserSliceWo; static SCHEME_ID: Once = Once::new(); @@ -49,9 +48,9 @@ impl SerioScheme { } } -impl Scheme for SerioScheme { - fn open(&self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result { - if uid != 0 { +impl KernelScheme for SerioScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { + if ctx.uid != 0 { return Err(Error::new(EPERM)); } @@ -68,7 +67,7 @@ impl Scheme for SerioScheme { flags: flags & ! O_ACCMODE }); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { @@ -96,26 +95,24 @@ impl Scheme for SerioScheme { Ok(EventFlags::empty()) } - fn fsync(&self, id: usize) -> Result { + fn fsync(&self, id: usize) -> Result<()> { let _handle = { let handles = HANDLES.read(); *handles.get(&id).ok_or(Error::new(EBADF))? }; - Ok(0) + Ok(()) } /// Close the file `number` - fn close(&self, id: usize) -> Result { + fn close(&self, id: usize) -> Result<()> { let _handle = { let mut handles = HANDLES.write(); handles.remove(&id).ok_or(Error::new(EBADF))? }; - Ok(0) + Ok(()) } -} -impl crate::scheme::KernelScheme for SerioScheme { fn kread(&self, id: usize, buf: UserSliceWo) -> Result { let handle = { let handles = HANDLES.read(); diff --git a/src/scheme/sys/iostat.rs b/src/scheme/sys/iostat.rs index ee3e96c0e8..c381a3af6b 100644 --- a/src/scheme/sys/iostat.rs +++ b/src/scheme/sys/iostat.rs @@ -1,8 +1,6 @@ use alloc::string::String; use alloc::vec::Vec; use core::fmt::Write; -use core::str; - use crate::context; use crate::scheme; use crate::syscall::error::Result; @@ -33,7 +31,7 @@ pub fn resource() -> Result> { let description = file.description.read(); - let scheme = { + let _scheme = { let schemes = scheme::schemes(); match schemes.get(description.scheme) { Some(scheme) => scheme.clone(), @@ -44,6 +42,7 @@ pub fn resource() -> Result> { } }; + /* let mut fpath = [0; 4096]; match scheme.fpath(description.number, &mut fpath) { Ok(path_len) => { @@ -54,6 +53,7 @@ pub fn resource() -> Result> { let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, description.scheme.get(), description.number, description.flags, err); } } + */ } } } diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index de791825f2..da48ea281a 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -7,10 +7,11 @@ use spin::RwLock; use crate::syscall::data::Stat; use crate::syscall::error::{Error, EBADF, ENOENT, Result}; use crate::syscall::flag::{MODE_DIR, MODE_FILE}; -use crate::syscall::scheme::{calc_seek_offset_usize, Scheme}; use crate::arch::interrupt; use crate::syscall::usercopy::UserSliceWo; +use super::{KernelScheme, CallerCtx, OpenResult, calc_seek_offset}; + mod block; mod context; mod cpu; @@ -74,8 +75,8 @@ impl SysScheme { } } -impl Scheme for SysScheme { - fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { +impl KernelScheme for SysScheme { + fn kopen(&self, path: &str, _flags: usize, _ctx: CallerCtx) -> Result { let path = path.trim_matches('/'); if path.is_empty() { @@ -87,19 +88,19 @@ impl Scheme for SysScheme { data.extend_from_slice(entry.0.as_bytes()); } - let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let id = self.next_id.fetch_add(1, Ordering::Relaxed); self.handles.write().insert(id, Handle { path: "", data, mode: MODE_DIR | 0o444, seek: 0 }); - return Ok(id) + return Ok(OpenResult::SchemeLocal(id)) } else { //Have to iterate to get the path without allocation for entry in self.files.iter() { if entry.0 == &path { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let id = self.next_id.fetch_add(1, Ordering::Relaxed); let data = entry.1()?; self.handles.write().insert(id, Handle { path: entry.0, @@ -107,7 +108,7 @@ impl Scheme for SysScheme { mode: MODE_FILE | 0o444, seek: 0 }); - return Ok(id) + return Ok(OpenResult::SchemeLocal(id)); } } } @@ -115,24 +116,22 @@ impl Scheme for SysScheme { Err(Error::new(ENOENT)) } - fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { + fn seek(&self, id: usize, pos: isize, whence: usize) -> Result { let mut handles = self.handles.write(); let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - let new_offset = calc_seek_offset_usize(handle.seek, pos, whence, handle.data.len())?; + let new_offset = calc_seek_offset(handle.seek, pos, whence, handle.data.len())?; handle.seek = new_offset as usize; Ok(new_offset) } - fn fsync(&self, _id: usize) -> Result { - Ok(0) + fn fsync(&self, _id: usize) -> Result<()> { + Ok(()) } - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + fn close(&self, id: usize) -> Result<()> { + self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(())) } -} -impl crate::scheme::KernelScheme for SysScheme { fn kfpath(&self, id: usize, buf: UserSliceWo) -> Result { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; @@ -159,7 +158,7 @@ impl crate::scheme::KernelScheme for SysScheme { Ok(byte_count) } - fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result { + fn kfstat(&self, id: usize, buf: UserSliceWo) -> Result<()> { let handles = self.handles.read(); let handle = handles.get(&id).ok_or(Error::new(EBADF))?; @@ -171,6 +170,6 @@ impl crate::scheme::KernelScheme for SysScheme { ..Default::default() })?; - Ok(0) + Ok(()) } } diff --git a/src/scheme/time.rs b/src/scheme/time.rs index 1fbe272f45..a1f85a2290 100644 --- a/src/scheme/time.rs +++ b/src/scheme/time.rs @@ -8,10 +8,11 @@ use crate::scheme::SchemeId; use crate::syscall::data::TimeSpec; use crate::syscall::error::*; use crate::syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC, EventFlags}; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::{UserSliceWo, UserSliceRo}; use crate::time; +use super::{KernelScheme, CallerCtx, OpenResult}; + pub struct TimeScheme { scheme_id: SchemeId, next_id: AtomicUsize, @@ -28,9 +29,9 @@ impl TimeScheme { } } -impl Scheme for TimeScheme { - fn open(&self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { - let clock = path.parse::().or(Err(Error::new(ENOENT)))?; +impl KernelScheme for TimeScheme { + fn kopen(&self, path: &str, _flags: usize, _ctx: CallerCtx) -> Result { + let clock = path.parse::().map_err(|_| Error::new(ENOENT))?; match clock { CLOCK_REALTIME => (), @@ -38,10 +39,10 @@ impl Scheme for TimeScheme { _ => return Err(Error::new(ENOENT)) } - let id = self.next_id.fetch_add(1, Ordering::SeqCst); + let id = self.next_id.fetch_add(1, Ordering::Relaxed); self.handles.write().insert(id, clock); - Ok(id) + Ok(OpenResult::SchemeLocal(id)) } fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result { @@ -53,16 +54,14 @@ impl Scheme for TimeScheme { handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(EventFlags::empty())) } - fn fsync(&self, id: usize) -> Result { - let handles = self.handles.read(); - handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + fn fsync(&self, id: usize) -> Result<()> { + self.handles.read().get(&id).ok_or(Error::new(EBADF))?; + Ok(()) } - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) + fn close(&self, id: usize) -> Result<()> { + self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(())) } -} -impl crate::scheme::KernelScheme for TimeScheme { fn kread(&self, id: usize, buf: UserSliceWo) -> Result { let clock = { let handles = self.handles.read(); diff --git a/src/scheme/user.rs b/src/scheme/user.rs index cb5aa0cb42..9aeb73ec06 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -3,12 +3,11 @@ use alloc::sync::{Arc, Weak}; use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::vec::Vec; -use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE, MunmapFlags, SKMSG_FOBTAINFD, FobtainFdFlags, SendFdFlags}; +use syscall::{SKMSG_FRETURNFD, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE, MunmapFlags, SKMSG_FOBTAINFD, FobtainFdFlags, SendFdFlags}; use core::mem::size_of; use core::num::NonZeroUsize; use core::sync::atomic::{AtomicBool, Ordering}; use core::{mem, usize}; -use core::convert::TryFrom; use spin::{Mutex, RwLock}; use crate::context::context::HardBlockedReason; @@ -25,10 +24,9 @@ use crate::syscall::data::{Map, Packet}; use crate::syscall::error::*; use crate::syscall::flag::{EventFlags, EVENT_READ, O_NONBLOCK, PROT_READ, PROT_WRITE, MapFlags}; use crate::syscall::number::*; -use crate::syscall::scheme::Scheme; use crate::syscall::usercopy::{UserSlice, UserSliceWo, UserSliceRo}; -use super::{FileHandle, OpenResult, KernelScheme, current_caller_ctx}; +use super::{FileHandle, OpenResult, KernelScheme, CallerCtx}; pub struct UserInner { root_id: SchemeId, @@ -74,7 +72,7 @@ impl UserInner { } } - pub fn unmount(&self) -> Result { + pub fn unmount(&self) -> Result<()> { // First, block new requests and prepare to return EOF self.unmounting.store(true, Ordering::SeqCst); @@ -85,7 +83,7 @@ impl UserInner { event::trigger(self.root_id, self.handle_id, EVENT_READ); //TODO: wait for all todo and done to be processed? - Ok(0) + Ok(()) } fn next_id(&self) -> u64 { @@ -96,7 +94,8 @@ impl UserInner { } pub fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result { - match self.call_extended(current_caller_ctx()?, None, [a, b, c, d])? { + let ctx = context::current()?.read().caller_ctx(); + match self.call_extended(ctx, None, [a, b, c, d])? { Response::Regular(code) => Error::demux(code), Response::Fd(_) => { if a & SYS_RET_FILE == SYS_RET_FILE { @@ -555,8 +554,8 @@ impl UserInner { Ok(EventFlags::empty()) } - pub fn fsync(&self) -> Result { - Ok(0) + pub fn fsync(&self) -> Result<()> { + Ok(()) } fn fmap_inner(&self, dst_addr_space: Arc>, file: usize, map: &Map) -> Result { @@ -758,45 +757,41 @@ impl UserScheme { } } -fn handle_open_res(res: OpenResult) -> Result { - match res { - OpenResult::SchemeLocal(num) => Ok(num), - OpenResult::External(_) => { - log::warn!("Used Scheme::open when forwarding fd!"); - Err(Error::new(EIO)) +impl KernelScheme for UserScheme { + fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { + let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; + let address = inner.copy_and_capture_tail(path.as_bytes())?; + match inner.call_extended(ctx, None, [SYS_OPEN, address.base(), address.len(), flags])? { + Response::Regular(code) => Error::demux(code).map(OpenResult::SchemeLocal), + Response::Fd(desc) => Ok(OpenResult::External(desc)), } } -} - -impl Scheme for UserScheme { - fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result { - self.kopen(path, flags, CallerCtx { uid, gid, pid: context::context_id().into() }).and_then(handle_open_res) - } - - fn rmdir(&self, path: &str, _uid: u32, _gid: u32) -> Result { + fn rmdir(&self, path: &str, _ctx: CallerCtx) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.copy_and_capture_tail(path.as_bytes())?; - inner.call(SYS_RMDIR, address.base(), address.len(), 0) + inner.call(SYS_RMDIR, address.base(), address.len(), 0)?; + Ok(()) } - fn unlink(&self, path: &str, _uid: u32, _gid: u32) -> Result { + fn unlink(&self, path: &str, _ctx: CallerCtx) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.copy_and_capture_tail(path.as_bytes())?; - inner.call(SYS_UNLINK, address.base(), address.len(), 0) + inner.call(SYS_UNLINK, address.base(), address.len(), 0)?; + Ok(()) } - fn seek(&self, file: usize, position: isize, whence: usize) -> Result { + fn seek(&self, file: usize, position: isize, whence: usize) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let new_offset = inner.call(SYS_LSEEK, file, position as usize, whence)?; - isize::try_from(new_offset).or_else(|_| Err(Error::new(EOVERFLOW))) + inner.call(SYS_LSEEK, file, position as usize, whence) } - fn fchmod(&self, file: usize, mode: u16) -> Result { + fn fchmod(&self, file: usize, mode: u16) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FCHMOD, file, mode as usize, 0) + inner.call(SYS_FCHMOD, file, mode as usize, 0)?; + Ok(()) } - fn fchown(&self, file: usize, uid: u32, gid: u32) -> Result { + fn fchown(&self, file: usize, uid: u32, gid: u32) -> Result<()> { { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -809,7 +804,8 @@ impl Scheme for UserScheme { } let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FCHOWN, file, uid as usize, gid as usize) + inner.call(SYS_FCHOWN, file, uid as usize, gid as usize)?; + Ok(()) } fn fcntl(&self, file: usize, cmd: usize, arg: usize) -> Result { @@ -867,35 +863,29 @@ impl Scheme for UserScheme { } */ - fn frename(&self, file: usize, path: &str, _uid: u32, _gid: u32) -> Result { + fn frename(&self, file: usize, path: &str, _ctx: CallerCtx) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.copy_and_capture_tail(path.as_bytes())?; - inner.call(SYS_FRENAME, file, address.base(), address.len()) + inner.call(SYS_FRENAME, file, address.base(), address.len())?; + Ok(()) } - fn fsync(&self, file: usize) -> Result { + fn fsync(&self, file: usize) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FSYNC, file, 0, 0) + inner.call(SYS_FSYNC, file, 0, 0)?; + Ok(()) } - fn ftruncate(&self, file: usize, len: usize) -> Result { + fn ftruncate(&self, file: usize, len: usize) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FTRUNCATE, file, len, 0) + inner.call(SYS_FTRUNCATE, file, len, 0)?; + Ok(()) } - fn close(&self, file: usize) -> Result { + fn close(&self, file: usize) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_CLOSE, file, 0, 0) - } -} -impl KernelScheme for UserScheme { - fn kopen(&self, path: &str, flags: usize, ctx: CallerCtx) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.copy_and_capture_tail(path.as_bytes())?; - match inner.call_extended(ctx, None, [SYS_OPEN, address.base(), address.len(), flags])? { - Response::Regular(code) => Error::demux(code).map(OpenResult::SchemeLocal), - Response::Fd(desc) => Ok(OpenResult::External(desc)), - } + inner.call(SYS_CLOSE, file, 0, 0)?; + Ok(()) } fn kdup(&self, file: usize, buf: UserSliceRo, ctx: CallerCtx) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; @@ -939,19 +929,19 @@ impl KernelScheme for UserScheme { address.release()?; result } - fn kfstat(&self, file: usize, stat: UserSliceWo) -> Result { + fn kfstat(&self, file: usize, stat: UserSliceWo) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.capture_user(stat)?; let result = inner.call(SYS_FSTAT, file, address.base(), address.len()); address.release()?; - result + result.map(|_| ()) } - fn kfstatvfs(&self, file: usize, stat: UserSliceWo) -> Result { + fn kfstatvfs(&self, file: usize, stat: UserSliceWo) -> Result<()> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.capture_user(stat)?; let result = inner.call(SYS_FSTATVFS, file, address.base(), address.len()); address.release()?; - result + result.map(|_| ()) } fn kfmap(&self, file: usize, addr_space: &Arc>, map: &Map, _consume: bool) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 0403f41269..1d623a9bd6 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -7,11 +7,10 @@ use crate::context::file::{FileDescriptor, FileDescription}; use crate::context; use crate::context::memory::{PageSpan, AddrSpace}; use crate::paging::{PAGE_SIZE, VirtualAddress, Page}; -use crate::scheme::{self, FileHandle, OpenResult, current_caller_ctx, KernelScheme, SchemeId}; +use crate::scheme::{self, FileHandle, OpenResult, KernelScheme, SchemeId, CallerCtx}; use crate::syscall::data::Stat; use crate::syscall::error::*; use crate::syscall::flag::*; -use crate::syscall::scheme::CallerCtx; use super::usercopy::{UserSlice, UserSliceWo, UserSliceRo}; @@ -87,9 +86,9 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result { } /// rmdir syscall -pub fn rmdir(raw_path: UserSliceRo) -> Result { - let (uid, gid, scheme_ns) = match context::current()?.read() { - ref context => (context.euid, context.egid, context.ens), +pub fn rmdir(raw_path: UserSliceRo) -> Result<()> { + let (scheme_ns, caller_ctx) = match context::current()?.read() { + ref context => (context.ens, context.caller_ctx()), }; /* @@ -107,13 +106,13 @@ pub fn rmdir(raw_path: UserSliceRo) -> Result { let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; Arc::clone(scheme) }; - scheme.rmdir(reference, uid, gid) + scheme.rmdir(reference, caller_ctx) } /// Unlink syscall -pub fn unlink(raw_path: UserSliceRo) -> Result { - let (uid, gid, scheme_ns) = match context::current()?.read() { - ref context => (context.euid, context.egid, context.ens), +pub fn unlink(raw_path: UserSliceRo) -> Result<()> { + let (scheme_ns, caller_ctx) = match context::current()?.read() { + ref context => (context.ens, context.caller_ctx()), }; /* let mut path_buf = BorrowedHtBuf::head()?; @@ -130,11 +129,11 @@ pub fn unlink(raw_path: UserSliceRo) -> Result { let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; Arc::clone(scheme) }; - scheme.unlink(reference, uid, gid) + scheme.unlink(reference, caller_ctx) } /// Close syscall -pub fn close(fd: FileHandle) -> Result { +pub fn close(fd: FileHandle) -> Result<()> { let file = { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -146,8 +145,9 @@ pub fn close(fd: FileHandle) -> Result { } fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result { - let file = context::current()?.read() - .get_file(fd).ok_or(Error::new(EBADF))?; + let (file, caller_ctx) = match context::current()?.read() { + ref context => (context.get_file(fd).ok_or(Error::new(EBADF))?, context.caller_ctx()), + }; if user_buf.is_empty() { Ok(FileDescriptor { @@ -164,7 +164,7 @@ fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result Arc::new(RwLock::new(FileDescription { namespace: description.namespace, scheme: description.scheme, @@ -309,9 +309,9 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result { } } -pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result { - let (file, uid, gid, scheme_ns) = match context::current()?.read() { - ref context => (context.get_file(fd).ok_or(Error::new(EBADF))?, context.euid, context.egid, context.ens), +pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result<()> { + let (file, caller_ctx, scheme_ns) = match context::current()?.read() { + ref context => (context.get_file(fd).ok_or(Error::new(EBADF))?, CallerCtx { uid: context.euid, gid: context.egid, pid: context.id.get() }, context.ens), }; /* @@ -332,15 +332,15 @@ pub fn frename(fd: FileHandle, raw_path: UserSliceRo) -> Result { let description = file.description.read(); - if scheme_id == description.scheme { - scheme.frename(description.number, reference, uid, gid) - } else { - Err(Error::new(EXDEV)) + if scheme_id != description.scheme { + return Err(Error::new(EXDEV)); } + + scheme.frename(description.number, reference, caller_ctx) } /// File status -pub fn fstat(fd: FileHandle, user_buf: UserSliceWo) -> Result { +pub fn fstat(fd: FileHandle, user_buf: UserSliceWo) -> Result<()> { file_op_generic_ext(fd, |scheme, scheme_id, _, number| { scheme.kfstat(number, user_buf)?; @@ -350,7 +350,7 @@ pub fn fstat(fd: FileHandle, user_buf: UserSliceWo) -> Result { let st_dev = scheme_id.get().try_into().map_err(|_| Error::new(EOVERFLOW))?; user_buf.advance(memoffset::offset_of!(Stat, st_dev)).and_then(|b| b.limit(8)).ok_or(Error::new(EIO))?.copy_from_slice(&u64::to_ne_bytes(st_dev))?; - Ok(0) + Ok(()) }) } diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 9db10062a7..28d400aa1d 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -16,7 +16,6 @@ pub use self::syscall::{ io, number, ptrace_event, - scheme, }; pub use self::driver::*; @@ -91,8 +90,8 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack SYS_ARG_MSLICE => match a { SYS_READ => file_op_generic(fd, |scheme, _, number| scheme.kread(number, UserSlice::wo(c, d)?)), SYS_FPATH => file_op_generic(fd, |scheme, _, number| scheme.kfpath(number, UserSlice::wo(c, d)?)), - SYS_FSTAT => fstat(fd, UserSlice::wo(c, d)?), - SYS_FSTATVFS => file_op_generic(fd, |scheme, _, number| scheme.kfstatvfs(number, UserSlice::wo(c, d)?)), + SYS_FSTAT => fstat(fd, UserSlice::wo(c, d)?).map(|()| 0), + SYS_FSTATVFS => file_op_generic(fd, |scheme, _, number| scheme.kfstatvfs(number, UserSlice::wo(c, d)?).map(|()| 0)), _ => return Err(Error::new(ENOSYS)), }, @@ -106,18 +105,19 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack #[cfg(target_pointer_width = "64")] SYS_SENDFD => sendfd(fd, FileHandle::from(c), d, e as u64), - SYS_LSEEK => file_op_generic(fd, |scheme, _, number| Ok(scheme.seek(number, c as isize, d)? as usize)), - SYS_FCHMOD => file_op_generic(fd, |scheme, _, number| scheme.fchmod(number, c as u16)), - SYS_FCHOWN => file_op_generic(fd, |scheme, _, number| scheme.fchown(number, c as u32, d as u32)), + SYS_LSEEK => file_op_generic(fd, |scheme, _, number| scheme.seek(number, c as isize, d)), + SYS_FCHMOD => file_op_generic(fd, |scheme, _, number| scheme.fchmod(number, c as u16).map(|()| 0)), + SYS_FCHOWN => file_op_generic(fd, |scheme, _, number| scheme.fchown(number, c as u32, d as u32).map(|()| 0)), SYS_FCNTL => fcntl(fd, c, d), SYS_FEVENT => file_op_generic(fd, |scheme, _, number| Ok(scheme.fevent(number, EventFlags::from_bits_truncate(c))?.bits())), - SYS_FRENAME => frename(fd, UserSlice::ro(c, d)?), + SYS_FRENAME => frename(fd, UserSlice::ro(c, d)?).map(|()| 0), SYS_FUNMAP => funmap(b, c), - SYS_FSYNC => file_op_generic(fd, |scheme, _, number| scheme.fsync(number)), - SYS_FTRUNCATE => file_op_generic(fd, |scheme, _, number| scheme.ftruncate(number, c)), + SYS_FSYNC => file_op_generic(fd, |scheme, _, number| scheme.fsync(number).map(|()| 0)), + // TODO: 64-bit lengths on 32-bit platforms + SYS_FTRUNCATE => file_op_generic(fd, |scheme, _, number| scheme.ftruncate(number, c).map(|()| 0)), - SYS_CLOSE => close(fd), + SYS_CLOSE => close(fd).map(|()| 0), _ => return Err(Error::new(ENOSYS)), } @@ -125,8 +125,8 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack }, SYS_CLASS_PATH => match a { SYS_OPEN => open(UserSlice::ro(b, c)?, d).map(FileHandle::into), - SYS_RMDIR => rmdir(UserSlice::ro(b, c)?), - SYS_UNLINK => unlink(UserSlice::ro(b, c)?), + SYS_RMDIR => rmdir(UserSlice::ro(b, c)?).map(|()| 0), + SYS_UNLINK => unlink(UserSlice::ro(b, c)?).map(|()| 0), _ => Err(Error::new(ENOSYS)) }, _ => match a {