diff --git a/src/kernel/src/budget/mod.rs b/src/kernel/src/budget/mod.rs index 94ae333ad..4a5dc4d69 100644 --- a/src/kernel/src/budget/mod.rs +++ b/src/kernel/src/budget/mod.rs @@ -1,9 +1,8 @@ use crate::errno::{ENOENT, ENOSYS, ESRCH}; -use crate::idt::Idt; +use crate::idt::{Entry, Idt}; use crate::info; use crate::process::VThread; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; -use std::convert::Infallible; use std::sync::{Arc, Mutex}; /// An implementation of budget system on the PS4. @@ -25,12 +24,8 @@ impl BudgetManager { pub fn create(&self, budget: Budget) -> usize { let name = budget.name.clone(); let mut budgets = self.budgets.lock().unwrap(); - let (entry, id) = budgets - .alloc::<_, Infallible>(|_| Ok(Arc::new(budget))) - .unwrap(); - entry.set_name(Some(name)); - entry.set_ty(0x2000); + let id = budgets.alloc_infallible(|_| Entry::new(Some(name), Arc::new(budget), 0x2000)); id } diff --git a/src/kernel/src/fs/dev/cdev.rs b/src/kernel/src/fs/dev/cdev.rs index f9bad1f8c..aa44dc9da 100644 --- a/src/kernel/src/fs/dev/cdev.rs +++ b/src/kernel/src/fs/dev/cdev.rs @@ -207,14 +207,18 @@ pub(super) trait Device: Debug + Sync + Send + 'static { #[allow(unused_variables)] fn read( self: Arc, - data: &mut [u8], + data: &mut UioMut, td: Option<&VThread>, ) -> Result> { Err(Box::new(DefaultError::ReadNotSupported)) } #[allow(unused_variables)] - fn write(self: Arc, data: &[u8], td: Option<&VThread>) -> Result> { + fn write( + self: Arc, + data: &mut Uio, + td: Option<&VThread>, + ) -> Result> { Err(Box::new(DefaultError::WriteNotSupported)) } diff --git a/src/kernel/src/fs/file.rs b/src/kernel/src/fs/file.rs index 9779bcaeb..c367d7505 100644 --- a/src/kernel/src/fs/file.rs +++ b/src/kernel/src/fs/file.rs @@ -182,7 +182,7 @@ pub enum VFileType { bitflags! { /// Flags for [`VFile`]. - #[derive(Debug, Clone, Copy)] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct VFileFlags: u32 { const READ = 0x00000001; // FREAD const WRITE = 0x00000002; // FWRITE diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index ddde47892..25617bf84 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -507,6 +507,19 @@ impl Fs { Ok(SysOut::ZERO) } + fn revoke(&self, vn: Arc, td: &VThread) -> Result<(), RevokeError> { + let vattr = vn.getattr().map_err(RevokeError::GetAttrError)?; + + if td.cred().effective_uid() != vattr.uid() { + td.priv_check(Privilege::VFS_ADMIN)?; + } + + vn.revoke(RevokeFlags::REVOKE_ALL) + .map_err(RevokeError::RevokeFailed)?; + + Ok(()) + } + fn sys_readv(self: &Arc, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let iovec: *mut IoVec = i.args[1].into(); @@ -728,19 +741,6 @@ impl Fs { todo!() } - fn revoke(&self, vn: Arc, td: &VThread) -> Result<(), RevokeError> { - let vattr = vn.getattr().map_err(RevokeError::GetAttrError)?; - - if td.cred().effective_uid() != vattr.uid() { - td.priv_check(Privilege::VFS_ADMIN)?; - } - - vn.revoke(RevokeFlags::REVOKE_ALL) - .map_err(RevokeError::RevokeFailed)?; - - Ok(()) - } - fn sys_mkdir(self: &Arc, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path() }?.unwrap(); let mode: u32 = i.args[1].try_into().unwrap(); diff --git a/src/kernel/src/idt/entry.rs b/src/kernel/src/idt/entry.rs index 02b6f1c44..d8b4d1c1a 100644 --- a/src/kernel/src/idt/entry.rs +++ b/src/kernel/src/idt/entry.rs @@ -7,11 +7,11 @@ pub struct Entry { } impl Entry { - pub(super) fn new(data: T) -> Self { + pub fn new(name: Option, data: T, ty: u16) -> Self { Self { - name: None, + name: name, data, - ty: 0, + ty, } } @@ -22,12 +22,4 @@ impl Entry { pub fn ty(&self) -> u16 { self.ty } - - pub fn set_name(&mut self, v: Option) { - self.name = v; - } - - pub fn set_ty(&mut self, v: u16) { - self.ty = v; - } } diff --git a/src/kernel/src/idt/mod.rs b/src/kernel/src/idt/mod.rs index cf64d0136..966f8eb39 100644 --- a/src/kernel/src/idt/mod.rs +++ b/src/kernel/src/idt/mod.rs @@ -1,3 +1,5 @@ +use std::convert::Infallible; + pub use self::entry::*; mod entry; @@ -27,10 +29,21 @@ impl Idt { } } + pub fn alloc_infallible(&mut self, factory: F) -> usize + where + F: FnOnce(usize) -> Entry, + { + let Ok((_, id)) = self.alloc::<_, Infallible>(|id| Ok(factory(id))) else { + unreachable!(); + }; + + id + } + /// See `id_alloc` on the PS4 for a reference. pub fn alloc(&mut self, factory: F) -> Result<(&mut Entry, usize), E> where - F: FnOnce(usize) -> Result, + F: FnOnce(usize) -> Result, E>, { // Allocate a new set if necessary. let id = self.next; @@ -47,7 +60,7 @@ impl Idt { assert!(entry.is_none()); // Set the value. - let value = entry.insert(Entry::new(factory(id)?)); + let value = entry.insert(factory(id)?); // Update table states. self.next += 1; diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 15e50c8da..a5f31f238 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -8,6 +8,7 @@ use crate::kqueue::KernelQueueManager; use crate::llvm::Llvm; use crate::log::{print, LOGGER}; use crate::memory::{MemoryManager, MemoryManagerError}; +use crate::namedobj::NamedObjManager; use crate::net::NetManager; use crate::osem::OsemManager; use crate::process::{VProc, VProcInitError, VThread}; @@ -47,6 +48,7 @@ mod kqueue; mod llvm; mod log; mod memory; +mod namedobj; mod net; mod osem; mod process; @@ -289,6 +291,7 @@ fn run( &mut syscalls, )?; + NamedObjManager::new(&mut syscalls, &proc); OsemManager::new(&mut syscalls, &proc); // Initialize runtime linker. diff --git a/src/kernel/src/namedobj/mod.rs b/src/kernel/src/namedobj/mod.rs new file mode 100644 index 000000000..bb8085956 --- /dev/null +++ b/src/kernel/src/namedobj/mod.rs @@ -0,0 +1,64 @@ +use crate::{ + errno::EINVAL, + idt::Entry, + info, + process::VProc, + syscalls::{SysErr, SysIn, SysOut, Syscalls}, +}; +use std::sync::Arc; + +pub struct NamedObjManager { + proc: Arc, +} + +impl NamedObjManager { + pub fn new(sys: &mut Syscalls, proc: &Arc) -> Arc { + let namedobj = Arc::new(Self { proc: proc.clone() }); + + sys.register(557, &namedobj, Self::sys_namedobj_create); + + namedobj + } + + fn sys_namedobj_create(self: &Arc, i: &SysIn) -> Result { + // Get arguments. + let name = unsafe { i.args[0].to_str(32) }?.ok_or(SysErr::Raw(EINVAL))?; + let data: usize = i.args[1].into(); + let flags: u32 = i.args[2].try_into().unwrap(); + + // Allocate the entry. + let mut table = self.proc.objects_mut(); + + let obj = NamedObj::new(name, data); + + let id = table.alloc_infallible(|_| { + Entry::new( + Some(name.to_owned()), + Arc::new(obj), + (flags as u16) | 0x1000, + ) + }); + + info!( + "Named object '{}' (ID = {}) was created with data = {:#x} and flags = {:#x}.", + name, id, data, flags + ); + + Ok(id.into()) + } +} + +#[derive(Debug)] +pub struct NamedObj { + name: String, + data: usize, +} + +impl NamedObj { + pub fn new(name: impl Into, data: usize) -> Self { + Self { + name: name.into(), + data, + } + } +} diff --git a/src/kernel/src/osem/mod.rs b/src/kernel/src/osem/mod.rs index 25acd1310..80988a15e 100644 --- a/src/kernel/src/osem/mod.rs +++ b/src/kernel/src/osem/mod.rs @@ -1,8 +1,8 @@ use crate::errno::EINVAL; +use crate::idt::Entry; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use crate::VProc; use bitflags::bitflags; -use std::convert::Infallible; use std::sync::Arc; pub struct OsemManager { @@ -37,10 +37,8 @@ impl OsemManager { let mut objects = self.proc.objects_mut(); - let (entry, id) = objects.alloc::<_, Infallible>(|_| Ok(Osem::new(flags)))?; - - entry.set_name(Some(name.to_owned())); - entry.set_ty(0x120); + let id = objects + .alloc_infallible(|_| Entry::new(Some(name.to_owned()), Osem::new(flags), 0x120)); Ok(id.into()) } diff --git a/src/kernel/src/process/filedesc.rs b/src/kernel/src/process/filedesc.rs index e546c84b5..2a3dba04d 100644 --- a/src/kernel/src/process/filedesc.rs +++ b/src/kernel/src/process/filedesc.rs @@ -6,7 +6,7 @@ use gmtx::{Gutex, GutexGroup}; use macros::Errno; use std::collections::VecDeque; use std::convert::Infallible; -use std::num::NonZeroI32; +use std::num::{NonZeroI32, TryFromIntError}; use std::sync::Arc; use thiserror::Error; @@ -90,11 +90,11 @@ impl FileDesc { return i as i32; } - // This should never happened. + // This should never happen. panic!("Too many files has been opened."); } - // TODO: implement capabilities + // TODO: (maybe) implement capabilities /// See `fget` on the PS4 for a reference. pub fn get(&self, fd: i32) -> Result, GetFileError> { @@ -113,27 +113,28 @@ impl FileDesc { /// See `_fget` and `fget_unlocked` on the PS4 for a reference. fn get_internal(&self, fd: i32, flags: VFileFlags) -> Result, GetFileError> { - if fd < 0 { - return Err(GetFileError::NegativeFd(fd)); - } + let fd: usize = fd.try_into()?; let files = self.files.write(); - if fd as usize >= files.len() { - return Err(GetFileError::FdOutOfRange(fd)); - } + let file = files + .get(fd as usize) + .ok_or(GetFileError::FdOutOfRange)? // None means the file descriptor is out of range + .as_ref() + .ok_or(GetFileError::NoFile)?; // Some(None) means the file descriptor is not associated with a file - loop { - if let None = files.get(fd as usize) { - return Err(GetFileError::NoFile(fd)); + match flags { + VFileFlags::WRITE | VFileFlags::READ if !file.flags().intersects(flags) => { + return Err(GetFileError::BadFlags(flags, file.flags())); } - - todo!() + _ => {} } + + Ok(file.clone()) } pub fn free(&self, fd: i32) -> Result<(), FreeError> { - let fd: usize = fd.try_into().map_err(|_| FreeError::NegativeFd)?; + let fd: usize = fd.try_into()?; let mut files = self.files.write(); @@ -147,25 +148,28 @@ impl FileDesc { } } -#[derive(Debug, Error)] +#[derive(Debug, Error, Errno)] pub enum GetFileError { - #[error("got negative file descriptor {0}")] - NegativeFd(i32), + #[error("got negative file descriptor")] + #[errno(EBADF)] + NegativeFd, - #[error("file descriptor {0} out of range")] - FdOutOfRange(i32), + #[error("file descriptor is out of range")] + #[errno(EBADF)] + FdOutOfRange, - #[error("no file assoiated with file descriptor {0}")] - NoFile(i32), + #[error("no file assoiated with file descriptor")] + #[errno(EBADF)] + NoFile, + + #[error("bad flags associated with file descriptor: expected {0:?}, file has {1:?}")] + #[errno(EBADF)] + BadFlags(VFileFlags, VFileFlags), } -impl Errno for GetFileError { - fn errno(&self) -> NonZeroI32 { - match self { - Self::NegativeFd(_) => EBADF, - Self::FdOutOfRange(_) => EBADF, - Self::NoFile(_) => EBADF, - } +impl From for GetFileError { + fn from(_: TryFromIntError) -> Self { + GetFileError::NegativeFd } } @@ -193,3 +197,9 @@ pub enum FreeError { #[errno(EBADF)] NoFile, } + +impl From for FreeError { + fn from(_: TryFromIntError) -> Self { + FreeError::NegativeFd + } +} diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index 25c005679..f95380830 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -22,7 +22,6 @@ use crate::ucred::{AuthInfo, Gid, Privilege, Ucred, Uid}; use gmtx::{Gutex, GutexGroup, GutexWriteGuard}; use std::any::Any; use std::cmp::min; -use std::convert::Infallible; use std::ffi::c_char; use std::mem::zeroed; use std::num::NonZeroI32; @@ -117,7 +116,6 @@ impl VProc { sys.register(464, &vp, Self::sys_thr_set_name); sys.register(466, &vp, Self::sys_rtprio_thread); sys.register(487, &vp, Self::sys_cpuset_getaffinity); - sys.register(557, &vp, Self::sys_namedobj_create); sys.register(585, &vp, Self::sys_is_in_sandbox); sys.register(587, &vp, Self::sys_get_authinfo); sys.register(602, &vp, Self::sys_randomized_path); @@ -550,30 +548,6 @@ impl VProc { } } - // TODO: This should not be here. - fn sys_namedobj_create(self: &Arc, i: &SysIn) -> Result { - // Get arguments. - let name = unsafe { i.args[0].to_str(32)?.ok_or(SysErr::Raw(EINVAL))? }; - let data: usize = i.args[1].into(); - let flags: u32 = i.args[2].try_into().unwrap(); - - // Allocate the entry. - let mut table = self.objects.write(); - let (entry, id) = table - .alloc::<_, Infallible>(|_| Ok(Arc::new(NamedObj::new(name.to_owned(), data)))) - .unwrap(); - - entry.set_name(Some(name.to_owned())); - entry.set_ty((flags as u16) | 0x1000); - - info!( - "Named object '{}' (ID = {}) was created with data = {:#x} and flags = {:#x}.", - name, id, data, flags - ); - - Ok(id.into()) - } - fn sys_is_in_sandbox(self: &Arc, _: &SysIn) -> Result { // TODO: Implement this once FS rework has been usable. Ok(1.into()) @@ -664,19 +638,6 @@ struct RtPrio { prio: u16, } -/// TODO: Move this to somewhere else. -#[derive(Debug)] -pub struct NamedObj { - name: String, - data: usize, -} - -impl NamedObj { - pub fn new(name: String, data: usize) -> Self { - Self { name, data } - } -} - /// Represents an error when [`VProc`] construction is failed. #[derive(Debug, Error)] pub enum VProcInitError { diff --git a/src/kernel/src/regmgr/mod.rs b/src/kernel/src/regmgr/mod.rs index eee37fcd2..5b1a7d2f4 100644 --- a/src/kernel/src/regmgr/mod.rs +++ b/src/kernel/src/regmgr/mod.rs @@ -361,10 +361,9 @@ impl RegMgr { let mut out = 0; let ret = self.get_int(key, &mut out).unwrap(); - if ret == 0 { - Ok(out.into()) - } else { - Err(SysErr::Raw(unsafe { NonZeroI32::new_unchecked(ret) })) + match NonZeroI32::new(ret) { + None => Ok(ret.into()), + Some(v) => Err(SysErr::Raw(v)), } } _ => Err(SysErr::Raw(EINVAL)), diff --git a/src/kernel/src/rtld/mod.rs b/src/kernel/src/rtld/mod.rs index 9ed800cc5..d51efd321 100644 --- a/src/kernel/src/rtld/mod.rs +++ b/src/kernel/src/rtld/mod.rs @@ -5,6 +5,7 @@ use crate::budget::ProcType; use crate::ee::{ExecutionEngine, RawFn}; use crate::errno::{Errno, EINVAL, ENOENT, ENOEXEC, ENOMEM, EPERM, ESRCH}; use crate::fs::{Fs, OpenError, VPath, VPathBuf}; +use crate::idt::Entry; use crate::info; use crate::log::print; use crate::memory::{MemoryManager, MemoryUpdateError, MmapError, Protections}; @@ -271,11 +272,9 @@ impl RuntimeLinker { return Err(LoadError::SetupFailed(e)); } - Ok(Arc::new(md)) + Ok(Entry::new(None, Arc::new(md), 0x2000)) })?; - entry.set_ty(0x2000); - // Add to list. let module = entry.data().clone().downcast::>().unwrap();