From fe36be5b7d8ca1520d348bb929aeacc397162465 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Mon, 8 Apr 2024 15:28:40 +0700 Subject: [PATCH] Moves some syscalls out of VProc (#815) --- src/kernel/src/process/mod.rs | 270 +++++++++++++++++++++++++++++++- src/kernel/src/process/proc.rs | 278 +++------------------------------ 2 files changed, 286 insertions(+), 262 deletions(-) diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index 2c07a4acb..715fd8270 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -1,9 +1,17 @@ use crate::budget::ProcType; use crate::dev::DmemContainer; +use crate::errno::{EINVAL, ENAMETOOLONG, EPERM, ESRCH}; use crate::fs::Vnode; -use crate::syscalls::Syscalls; -use crate::ucred::AuthInfo; +use crate::info; +use crate::signal::{ + strsignal, SigChldFlags, Signal, SignalAct, SignalFlags, SIGCHLD, SIGKILL, SIGSTOP, SIG_DFL, + SIG_IGN, +}; +use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; +use crate::ucred::{AuthInfo, Privilege}; use crate::vm::MemoryManagerError; +use std::cmp::min; +use std::ffi::c_char; use std::sync::atomic::AtomicI32; use std::sync::Arc; use thiserror::Error; @@ -35,8 +43,17 @@ pub struct ProcManager {} impl ProcManager { pub fn new(sys: &mut Syscalls) -> Arc { + // Register syscalls. let pmgr = Arc::new(Self {}); + sys.register(20, &pmgr, Self::sys_getpid); + sys.register(50, &pmgr, Self::sys_setlogin); + sys.register(147, &pmgr, Self::sys_setsid); + sys.register(416, &pmgr, Self::sys_sigaction); + sys.register(432, &pmgr, Self::sys_thr_self); + sys.register(464, &pmgr, Self::sys_thr_set_name); + sys.register(602, &pmgr, Self::sys_randomized_path); + pmgr } @@ -49,7 +66,7 @@ impl ProcManager { dmem_container: DmemContainer, root: Arc, system_path: impl Into, - mut sys: Syscalls, + sys: Syscalls, ) -> Result, SpawnError> { VProc::new( auth, @@ -61,6 +78,253 @@ impl ProcManager { sys, ) } + + fn sys_getpid(self: &Arc, td: &VThread, _: &SysIn) -> Result { + Ok(td.proc().id().into()) + } + + fn sys_setlogin(self: &Arc, td: &VThread, i: &SysIn) -> Result { + // Check current thread privilege. + td.priv_check(Privilege::PROC_SETLOGIN)?; + + // Get login name. + let login = unsafe { i.args[0].to_str(17) } + .map_err(|e| { + if e.errno() == ENAMETOOLONG { + SysErr::Raw(EINVAL) + } else { + e + } + })? + .unwrap(); + + // Set login name. + let mut group = td.proc().group_mut(); + let session = group.as_mut().unwrap().session_mut(); + + session.set_login(login); + + info!("Login name was changed to '{login}'."); + + Ok(SysOut::ZERO) + } + + fn sys_setsid(self: &Arc, td: &VThread, _: &SysIn) -> Result { + // Check if current thread has privilege. + td.priv_check(Privilege::SCE680)?; + + // Check if the process already become a group leader. + let mut group = td.proc().group_mut(); + + if group.is_some() { + return Err(SysErr::Raw(EPERM)); + } + + // TODO: Find out the correct login name for VSession. + let pid = td.proc().id(); + let session = VSession::new(pid, String::from("root")); + + *group = Some(VProcGroup::new(pid, session)); + drop(group); + + info!("Virtual process now set as group leader."); + + Ok(pid.into()) + } + + fn sys_sigaction(self: &Arc, td: &VThread, i: &SysIn) -> Result { + // Get arguments. + let sig = { + let sig: i32 = i.args[0].try_into().unwrap(); + Signal::new(sig).ok_or(SysErr::Raw(EINVAL))? + }; + let act: *const SignalAct = i.args[1].into(); + let oact: *mut SignalAct = i.args[2].into(); + + // Save the old actions. + let proc = td.proc(); + let mut acts = proc.sigacts_mut(); + + if !oact.is_null() { + let handler = acts.handler(sig); + let flags = acts.signal_flags(sig); + let mask = acts.catchmask(sig); + let old_act = SignalAct { + handler, + flags, + mask, + }; + + unsafe { + *oact = old_act; + } + } + + if act.is_null() { + return Ok(SysOut::ZERO); + } + + // Set new actions. + let handler = unsafe { (*act).handler }; + let flags = unsafe { (*act).flags }; + let mut mask = unsafe { (*act).mask }; + + info!( + "Setting {} handler to {:#x} with flags = {} and mask = {}.", + strsignal(sig), + handler, + flags, + mask + ); + + if (sig == SIGKILL || sig == SIGSTOP) && handler != 0 { + return Err(SysErr::Raw(EINVAL)); + } + + mask.remove(SIGKILL); + mask.remove(SIGSTOP); + acts.set_catchmask(sig, mask); + acts.set_handler(sig, handler); + + if flags.intersects(SignalFlags::SA_SIGINFO) { + acts.set_modern(sig); + + if flags.intersects(SignalFlags::SA_RESTART) { + todo!("sys_sigaction with act.flags & 0x2 != 0"); + } else { + acts.set_interupt(sig); + } + + if flags.intersects(SignalFlags::SA_ONSTACK) { + todo!("sys_sigaction with act.flags & 0x1 != 0"); + } else { + acts.remove_stack(sig); + } + + if flags.intersects(SignalFlags::SA_RESETHAND) { + todo!("sys_sigaction with act.flags & 0x4 != 0"); + } else { + acts.remove_reset(sig); + } + + if flags.intersects(SignalFlags::SA_NODEFER) { + todo!("sys_sigaction with act.flags & 0x10 != 0"); + } else { + acts.remove_nodefer(sig); + } + } else { + todo!("sys_sigaction with act.flags & 0x40 = 0"); + } + + if sig == SIGCHLD { + let mut flag = acts.flag(); + + if flags.intersects(SignalFlags::SA_NOCLDSTOP) { + flag |= SigChldFlags::PS_NOCLDSTOP; + } else { + flag &= !SigChldFlags::PS_NOCLDSTOP; + } + + if !flags.intersects(SignalFlags::SA_NOCLDWAIT) || proc.id().get() == 1 { + flag &= !SigChldFlags::PS_NOCLDWAIT; + } else { + flag |= SigChldFlags::PS_NOCLDWAIT; + } + + if acts.handler(sig) == SIG_IGN { + flag |= SigChldFlags::PS_CLDSIGIGN; + } else { + flag &= !SigChldFlags::PS_CLDSIGIGN; + } + + acts.set_flag(flag); + } + + // TODO: Refactor this for readability. + if acts.handler(sig) == SIG_IGN + || (sig.get() < 32 + && ((0x184c8000u32 >> sig.get()) & 1) != 0 + && acts.handler(sig) == SIG_DFL) + { + todo!("sys_sigaction with SIG_IGN"); + } else { + acts.remove_ignore(sig); + + if acts.handler(sig) == SIG_DFL { + acts.remove_catch(sig); + } else { + acts.set_catch(sig); + } + } + + Ok(SysOut::ZERO) + } + + fn sys_thr_self(self: &Arc, td: &VThread, i: &SysIn) -> Result { + let id: *mut i64 = i.args[0].into(); + + unsafe { *id = td.id().get().into() }; + + Ok(SysOut::ZERO) + } + + fn sys_thr_set_name(self: &Arc, td: &VThread, i: &SysIn) -> Result { + let tid: i64 = i.args[0].into(); + let name: Option<&str> = unsafe { i.args[1].to_str(32) }?; + let proc = td.proc(); + + if tid == -1 { + info!("Setting process name to '{}'.", name.unwrap_or("NULL")); + + proc.set_name(name); + } else { + let threads = proc.threads(); + let thr = threads + .iter() + .find(|t| t.id().get() == tid as i32) + .ok_or(SysErr::Raw(ESRCH))?; + + info!( + "Setting name of thread {} to '{}'.", + thr.id(), + name.unwrap_or("NULL") + ); + + thr.set_name(name); + } + + Ok(SysOut::ZERO) + } + + fn sys_randomized_path(self: &Arc, td: &VThread, i: &SysIn) -> Result { + let set = i.args[0]; + let get: *mut c_char = i.args[1].into(); + let len: *mut usize = i.args[2].into(); + let proc = td.proc(); + + // Get the value. + let len = if get.is_null() || len.is_null() { + 0 + } else { + let v = unsafe { *len }; + unsafe { *len = proc.system_path().len() }; + v + }; + + if len > 0 && !proc.system_path().is_empty() { + let len = min(len - 1, proc.system_path().len()); + + unsafe { get.copy_from_nonoverlapping(proc.system_path().as_ptr().cast(), len) }; + unsafe { *get.add(len) = 0 }; + } + + // Set the value. + if set != 0 { + todo!("sys_randomized_path with non-null set"); + } + + Ok(SysOut::ZERO) + } } /// Represents an error when [`ProcManager::spawn()`] was failed. diff --git a/src/kernel/src/process/proc.rs b/src/kernel/src/process/proc.rs index 61f501734..e10fea634 100644 --- a/src/kernel/src/process/proc.rs +++ b/src/kernel/src/process/proc.rs @@ -1,19 +1,14 @@ use super::{ AppInfo, Binaries, CpuLevel, CpuWhich, FileDesc, Limits, ResourceLimit, ResourceType, - SignalActs, SpawnError, VProcGroup, VSession, VThread, NEXT_ID, + SignalActs, SpawnError, VProcGroup, VThread, NEXT_ID, }; use crate::budget::ProcType; use crate::dev::DmemContainer; use crate::errno::Errno; -use crate::errno::{EINVAL, ENAMETOOLONG, EPERM, ERANGE, ESRCH}; +use crate::errno::{EINVAL, ERANGE, ESRCH}; use crate::fs::Vnode; use crate::idt::Idt; -use crate::info; -use crate::signal::{ - strsignal, SignalAct, SignalFlags, SignalSet, SIGCHLD, SIGKILL, SIGSTOP, SIG_BLOCK, SIG_DFL, - SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, -}; -use crate::signal::{SigChldFlags, Signal}; +use crate::signal::{SignalSet, SIGKILL, SIGSTOP, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK}; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use crate::sysent::ProcAbi; use crate::ucred::{AuthInfo, Gid, Privilege, Ucred, Uid}; @@ -22,8 +17,6 @@ use bitflags::bitflags; use gmtx::{Gutex, GutexGroup, GutexReadGuard, GutexWriteGuard}; use macros::Errno; use std::any::Any; -use std::cmp::min; -use std::ffi::c_char; use std::mem::size_of; use std::mem::zeroed; use std::num::NonZeroI32; @@ -104,20 +97,13 @@ impl VProc { }); // TODO: Move all syscalls here to somewhere else. - sys.register(20, &vp, Self::sys_getpid); - sys.register(50, &vp, Self::sys_setlogin); - sys.register(147, &vp, Self::sys_setsid); sys.register(340, &vp, Self::sys_sigprocmask); - sys.register(416, &vp, Self::sys_sigaction); - sys.register(432, &vp, Self::sys_thr_self); sys.register(455, &vp, Self::sys_thr_new); - 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(488, &vp, Self::sys_cpuset_setaffinity); 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); sys.register(612, &vp, Self::sys_get_proc_type_info); vp.abi.set(ProcAbi::new(sys)).unwrap(); @@ -129,6 +115,10 @@ impl VProc { self.id } + pub fn threads(&self) -> GutexReadGuard>> { + self.threads.read() + } + pub fn threads_mut(&self) -> GutexWriteGuard>> { self.threads.write() } @@ -137,6 +127,10 @@ impl VProc { &self.cred } + pub fn group_mut(&self) -> GutexWriteGuard>> { + self.group.write() + } + pub fn abi(&self) -> &ProcAbi { self.abi.get().unwrap() } @@ -145,10 +139,18 @@ impl VProc { &self.vm } + pub fn sigacts_mut(&self) -> GutexWriteGuard { + self.sigacts.write() + } + pub fn files(&self) -> &Arc { &self.files } + pub fn system_path(&self) -> &str { + &self.system_path + } + pub fn limit(&self, ty: ResourceType) -> &ResourceLimit { &self.limits[ty] } @@ -197,56 +199,6 @@ impl VProc { &self.uptc } - fn sys_getpid(self: &Arc, _: &VThread, _: &SysIn) -> Result { - Ok(self.id.into()) - } - - fn sys_setlogin(self: &Arc, td: &VThread, i: &SysIn) -> Result { - // Check current thread privilege. - td.priv_check(Privilege::PROC_SETLOGIN)?; - - // Get login name. - let login = unsafe { i.args[0].to_str(17) } - .map_err(|e| { - if e.errno() == ENAMETOOLONG { - SysErr::Raw(EINVAL) - } else { - e - } - })? - .unwrap(); - - // Set login name. - let mut group = self.group.write(); - let session = group.as_mut().unwrap().session_mut(); - - session.set_login(login); - - info!("Login name was changed to '{login}'."); - - Ok(SysOut::ZERO) - } - - fn sys_setsid(self: &Arc, td: &VThread, _: &SysIn) -> Result { - // Check if current thread has privilege. - td.priv_check(Privilege::SCE680)?; - - // Check if the process already become a group leader. - let mut group = self.group.write(); - - if group.is_some() { - return Err(SysErr::Raw(EPERM)); - } - - // TODO: Find out the correct login name for VSession. - let session = VSession::new(self.id, String::from("root")); - - *group = Some(VProcGroup::new(self.id, session)); - info!("Virtual process now set as group leader."); - - Ok(self.id.into()) - } - fn sys_sigprocmask(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let how: How = { @@ -309,141 +261,6 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_sigaction(self: &Arc, _: &VThread, i: &SysIn) -> Result { - // Get arguments. - let sig = { - let sig: i32 = i.args[0].try_into().unwrap(); - Signal::new(sig).ok_or(SysErr::Raw(EINVAL))? - }; - let act: *const SignalAct = i.args[1].into(); - let oact: *mut SignalAct = i.args[2].into(); - - // Save the old actions. - let mut acts = self.sigacts.write(); - - if !oact.is_null() { - let handler = acts.handler(sig); - let flags = acts.signal_flags(sig); - let mask = acts.catchmask(sig); - let old_act = SignalAct { - handler: handler, - flags: flags, - mask: mask, - }; - - unsafe { - *oact = old_act; - } - } - - if act.is_null() { - return Ok(SysOut::ZERO); - } - - // Set new actions. - let handler = unsafe { (*act).handler }; - let flags = unsafe { (*act).flags }; - let mut mask = unsafe { (*act).mask }; - - info!( - "Setting {} handler to {:#x} with flags = {} and mask = {}.", - strsignal(sig), - handler, - flags, - mask - ); - - if (sig == SIGKILL || sig == SIGSTOP) && handler != 0 { - return Err(SysErr::Raw(EINVAL)); - } - - mask.remove(SIGKILL); - mask.remove(SIGSTOP); - acts.set_catchmask(sig, mask); - acts.set_handler(sig, handler); - - if flags.intersects(SignalFlags::SA_SIGINFO) { - acts.set_modern(sig); - - if flags.intersects(SignalFlags::SA_RESTART) { - todo!("sys_sigaction with act.flags & 0x2 != 0"); - } else { - acts.set_interupt(sig); - } - - if flags.intersects(SignalFlags::SA_ONSTACK) { - todo!("sys_sigaction with act.flags & 0x1 != 0"); - } else { - acts.remove_stack(sig); - } - - if flags.intersects(SignalFlags::SA_RESETHAND) { - todo!("sys_sigaction with act.flags & 0x4 != 0"); - } else { - acts.remove_reset(sig); - } - - if flags.intersects(SignalFlags::SA_NODEFER) { - todo!("sys_sigaction with act.flags & 0x10 != 0"); - } else { - acts.remove_nodefer(sig); - } - } else { - todo!("sys_sigaction with act.flags & 0x40 = 0"); - } - - if sig == SIGCHLD { - let mut flag = acts.flag(); - - if flags.intersects(SignalFlags::SA_NOCLDSTOP) { - flag |= SigChldFlags::PS_NOCLDSTOP; - } else { - flag &= !SigChldFlags::PS_NOCLDSTOP; - } - - if !flags.intersects(SignalFlags::SA_NOCLDWAIT) || self.id.get() == 1 { - flag &= !SigChldFlags::PS_NOCLDWAIT; - } else { - flag |= SigChldFlags::PS_NOCLDWAIT; - } - - if acts.handler(sig) == SIG_IGN { - flag |= SigChldFlags::PS_CLDSIGIGN; - } else { - flag &= !SigChldFlags::PS_CLDSIGIGN; - } - - acts.set_flag(flag); - } - - // TODO: Refactor this for readability. - if acts.handler(sig) == SIG_IGN - || (sig.get() < 32 - && ((0x184c8000u32 >> sig.get()) & 1) != 0 - && acts.handler(sig) == SIG_DFL) - { - todo!("sys_sigaction with SIG_IGN"); - } else { - acts.remove_ignore(sig); - - if acts.handler(sig) == SIG_DFL { - acts.remove_catch(sig); - } else { - acts.set_catch(sig); - } - } - - Ok(SysOut::ZERO) - } - - fn sys_thr_self(self: &Arc, td: &VThread, i: &SysIn) -> Result { - let id: *mut i64 = i.args[0].into(); - - unsafe { *id = td.id().get().into() }; - - Ok(SysOut::ZERO) - } - fn sys_thr_new(self: &Arc, td: &VThread, i: &SysIn) -> Result { let param: *const ThrParam = i.args[0].into(); let param_size: i32 = i.args[1].try_into().unwrap(); @@ -500,34 +317,6 @@ impl VProc { todo!() } - fn sys_thr_set_name(self: &Arc, _: &VThread, i: &SysIn) -> Result { - let tid: i64 = i.args[0].into(); - let name: Option<&str> = unsafe { i.args[1].to_str(32) }?; - - if tid == -1 { - info!("Setting process name to '{}'.", name.unwrap_or("NULL")); - - self.set_name(name); - } else { - let threads = self.threads.read(); - - let thr = threads - .iter() - .find(|t| t.id().get() == tid as i32) - .ok_or(SysErr::Raw(ESRCH))?; - - info!( - "Setting name of thread {} to '{}'.", - thr.id(), - name.unwrap_or("NULL") - ); - - thr.set_name(name); - } - - Ok(SysOut::ZERO) - } - fn sys_rtprio_thread(self: &Arc, td: &VThread, i: &SysIn) -> Result { let function: RtpFunction = TryInto::::try_into(i.args[0]).unwrap().try_into()?; let lwpid: i32 = i.args[1].try_into().unwrap(); @@ -690,35 +479,6 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_randomized_path(self: &Arc, _: &VThread, i: &SysIn) -> Result { - let set = i.args[0]; - let get: *mut c_char = i.args[1].into(); - let len: *mut usize = i.args[2].into(); - - // Get the value. - let len = if get.is_null() || len.is_null() { - 0 - } else { - let v = unsafe { *len }; - unsafe { *len = self.system_path.len() }; - v - }; - - if len > 0 && !self.system_path.is_empty() { - let len = min(len - 1, self.system_path.len()); - - unsafe { get.copy_from_nonoverlapping(self.system_path.as_ptr().cast(), len) }; - unsafe { *get.add(len) = 0 }; - } - - // Set the value. - if set != 0 { - todo!("sys_randomized_path with non-null set"); - } - - Ok(SysOut::ZERO) - } - fn sys_get_proc_type_info(self: &Arc, td: &VThread, i: &SysIn) -> Result { let info = unsafe { &mut *Into::<*mut ProcTypeInfo>::into(i.args[0]) };