diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index cc3393c2..10a8fdc8 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/kernel/src/init/initial_kthread.rs @@ -13,11 +13,10 @@ use crate::{ namespaces::NsProxy, net::net_core::net_init, process::{ - exec::ProcInitInfo, kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, - ProcessManager, + exec::ProcInitInfo, execve::do_execve, kthread::KernelThreadMechanism, stdio::stdio_init, + ProcessFlags, ProcessManager, }, smp::smp_init, - syscall::Syscall, }; use super::{cmdline::kenrel_cmdline_param_manager, initcall::do_initcalls}; @@ -164,7 +163,7 @@ fn run_init_process( ProcessManager::current_pcb().set_nsproxy(NsProxy::new()); // 初始化init进程的namespace let path = proc_init_info.proc_name.to_str().unwrap(); - Syscall::do_execve( + do_execve( path.to_string(), proc_init_info.args.clone(), proc_init_info.envs.clone(), diff --git a/kernel/src/namespaces/mnt_namespace.rs b/kernel/src/namespaces/mnt_namespace.rs index 721cc519..81954586 100644 --- a/kernel/src/namespaces/mnt_namespace.rs +++ b/kernel/src/namespaces/mnt_namespace.rs @@ -25,8 +25,8 @@ use crate::libs::rbtree::RBTree; use crate::libs::rwlock::RwLock; use crate::libs::wait_queue::WaitQueue; use crate::process::fork::CloneFlags; +use crate::process::geteuid::do_geteuid; use crate::process::ProcessManager; -use crate::syscall::Syscall; #[allow(dead_code)] #[derive(Debug)] pub struct MntNamespace { @@ -230,7 +230,7 @@ impl MntNamespace { ) -> Result>, SystemError> { Ok(self .ucounts - .inc_ucounts(user_ns, Syscall::geteuid()?, MntNamespaces)) + .inc_ucounts(user_ns, do_geteuid()?, MntNamespaces)) } pub fn dec_mnt_namespace(&self, uc: Arc) { diff --git a/kernel/src/namespaces/pid_namespace.rs b/kernel/src/namespaces/pid_namespace.rs index 7f1eb05b..f07a51bd 100644 --- a/kernel/src/namespaces/pid_namespace.rs +++ b/kernel/src/namespaces/pid_namespace.rs @@ -9,8 +9,8 @@ use crate::container_of; use crate::filesystem::vfs::{IndexNode, ROOT_INODE}; use crate::namespaces::namespace::NsOperations; use crate::process::fork::CloneFlags; +use crate::process::geteuid::do_geteuid; use crate::process::ProcessManager; -use crate::syscall::Syscall; use crate::{libs::rwlock::RwLock, process::Pid}; use alloc::boxed::Box; use alloc::string::String; @@ -264,7 +264,7 @@ impl PidNamespace { ) -> Result>, SystemError> { Ok(self .ucounts - .inc_ucounts(user_ns, Syscall::geteuid()?, PidNamespaces)) + .inc_ucounts(user_ns, do_geteuid()?, PidNamespaces)) } pub fn dec_pid_namespaces(&mut self, uc: Arc) { diff --git a/kernel/src/process/execve.rs b/kernel/src/process/execve.rs new file mode 100644 index 00000000..7d2e4ac2 --- /dev/null +++ b/kernel/src/process/execve.rs @@ -0,0 +1,113 @@ +use crate::arch::CurrentIrqArch; +use crate::exception::InterruptArch; +use crate::process::exec::{load_binary_file, ExecParam, ExecParamFlags}; +use crate::process::ProcessManager; +use crate::syscall::Syscall; +use crate::{libs::rand::rand_bytes, mm::ucontext::AddressSpace}; + +use crate::arch::interrupt::TrapFrame; +use alloc::{ffi::CString, string::String, sync::Arc, vec::Vec}; +use system_error::SystemError; +pub fn do_execve( + path: String, + argv: Vec, + envp: Vec, + regs: &mut TrapFrame, +) -> Result<(), SystemError> { + let address_space = AddressSpace::new(true).expect("Failed to create new address space"); + // debug!("to load binary file"); + let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?; + let old_vm = do_execve_switch_user_vm(address_space.clone()); + + // 加载可执行文件 + let load_result = load_binary_file(&mut param).inspect_err(|_| { + if let Some(old_vm) = old_vm { + do_execve_switch_user_vm(old_vm); + } + })?; + + // debug!("load binary file done"); + // debug!("argv: {:?}, envp: {:?}", argv, envp); + param.init_info_mut().args = argv; + param.init_info_mut().envs = envp; + // // 生成16字节随机数 + param.init_info_mut().rand_num = rand_bytes::<16>(); + + // 把proc_init_info写到用户栈上 + let mut ustack_message = unsafe { + address_space + .write() + .user_stack_mut() + .expect("No user stack found") + .clone_info_only() + }; + let (user_sp, argv_ptr) = unsafe { + param + .init_info_mut() + .push_at( + // address_space + // .write() + // .user_stack_mut() + // .expect("No user stack found"), + &mut ustack_message, + ) + .expect("Failed to push proc_init_info to user stack") + }; + address_space.write().user_stack = Some(ustack_message); + + Syscall::arch_do_execve(regs, ¶m, &load_result, user_sp, argv_ptr) +} + +/// 切换用户虚拟内存空间 +/// +/// 该函数用于在执行系统调用 `execve` 时切换用户进程的虚拟内存空间。 +/// +/// # 参数 +/// - `new_vm`: 新的用户地址空间,类型为 `Arc`。 +/// +/// # 返回值 +/// - 返回旧的用户地址空间的引用,类型为 `Option>`。 +/// +/// # 错误处理 +/// 如果地址空间切换失败,函数会触发断言失败,并输出错误信息。 +fn do_execve_switch_user_vm(new_vm: Arc) -> Option> { + // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + let pcb = ProcessManager::current_pcb(); + // log::debug!( + // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n", + // pcb.pid(), + // path, + // argv, + // envp + // ); + + let mut basic_info = pcb.basic_mut(); + // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free) + let old_address_space = basic_info.user_vm(); + + // 在pcb中原来的用户地址空间 + unsafe { + basic_info.set_user_vm(None); + } + // 创建新的地址空间并设置为当前地址空间 + unsafe { + basic_info.set_user_vm(Some(new_vm.clone())); + } + + // to avoid deadlock + drop(basic_info); + + assert!( + AddressSpace::is_current(&new_vm), + "Failed to set address space" + ); + // debug!("Switch to new address space"); + + // 切换到新的用户地址空间 + unsafe { new_vm.read().user_mapper.utable.make_current() }; + + drop(irq_guard); + + old_address_space +} diff --git a/kernel/src/process/geteuid.rs b/kernel/src/process/geteuid.rs new file mode 100644 index 00000000..99fc3f2d --- /dev/null +++ b/kernel/src/process/geteuid.rs @@ -0,0 +1,8 @@ +use system_error::SystemError; + +use crate::process::ProcessManager; + +pub fn do_geteuid() -> Result { + let pcb = ProcessManager::current_pcb(); + return Ok(pcb.cred.lock().euid.data()); +} diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index a6c3ef0d..c694392b 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -76,8 +76,10 @@ use self::{cred::Cred, kthread::WorkerPrivate}; pub mod abi; pub mod cred; pub mod exec; +pub mod execve; pub mod exit; pub mod fork; +pub mod geteuid; pub mod idle; pub mod kthread; pub mod pid; diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs deleted file mode 100644 index 1d95c86b..00000000 --- a/kernel/src/process/syscall.rs +++ /dev/null @@ -1,683 +0,0 @@ -use core::ffi::c_void; - -use alloc::{ - ffi::CString, - string::{String, ToString}, - sync::Arc, - vec::Vec, -}; -use log::error; -use system_error::SystemError; - -use super::{ - abi::WaitOption, - cred::{Kgid, Kuid}, - exec::{load_binary_file, ExecParam, ExecParamFlags}, - exit::kernel_wait4, - fork::{CloneFlags, KernelCloneArgs}, - resource::{RLimit64, RLimitID, RUsage, RUsageWho}, - KernelStack, Pgid, Pid, ProcessManager, -}; -use crate::{ - arch::{interrupt::TrapFrame, CurrentIrqArch, MMArch}, - exception::InterruptArch, - filesystem::{ - procfs::procfs_register_pid, - vfs::{file::FileDescriptorVec, MAX_PATHLEN}, - }, - libs::rand::rand_bytes, - mm::{ - ucontext::{AddressSpace, UserStack}, - verify_area, MemoryManagementArch, VirtAddr, - }, - process::ProcessControlBlock, - sched::completion::Completion, - syscall::{ - user_access::{check_and_clone_cstr, check_and_clone_cstr_array, UserBufferWriter}, - Syscall, - }, -}; - -//参考资料:https://code.dragonos.org.cn/xref/linux-6.1.9/include/uapi/linux/utsname.h#17 -#[repr(C)] -#[derive(Debug, Clone, Copy)] -pub struct PosixOldUtsName { - pub sysname: [u8; 65], - pub nodename: [u8; 65], - pub release: [u8; 65], - pub version: [u8; 65], - pub machine: [u8; 65], -} - -impl PosixOldUtsName { - pub fn new() -> Self { - const SYS_NAME: &[u8] = b"Linux"; - const NODENAME: &[u8] = b"DragonOS"; - const RELEASE: &[u8] = b"5.19.0"; - const VERSION: &[u8] = b"5.19.0"; - - #[cfg(target_arch = "x86_64")] - const MACHINE: &[u8] = b"x86_64"; - - #[cfg(target_arch = "aarch64")] - const MACHINE: &[u8] = b"aarch64"; - - #[cfg(target_arch = "riscv64")] - const MACHINE: &[u8] = b"riscv64"; - - #[cfg(target_arch = "loongarch64")] - const MACHINE: &[u8] = b"longarch64"; - - let mut r = Self { - sysname: [0; 65], - nodename: [0; 65], - release: [0; 65], - version: [0; 65], - machine: [0; 65], - }; - - r.sysname[0..SYS_NAME.len()].copy_from_slice(SYS_NAME); - r.nodename[0..NODENAME.len()].copy_from_slice(NODENAME); - r.release[0..RELEASE.len()].copy_from_slice(RELEASE); - r.version[0..VERSION.len()].copy_from_slice(VERSION); - r.machine[0..MACHINE.len()].copy_from_slice(MACHINE); - - return r; - } -} - -impl Syscall { - pub fn fork(frame: &TrapFrame) -> Result { - ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()) - } - - pub fn vfork(frame: &TrapFrame) -> Result { - // 由于Linux vfork需要保证子进程先运行(除非子进程调用execve或者exit), - // 而我们目前没有实现这个特性,所以暂时使用fork代替vfork(linux文档表示这样也是也可以的) - Self::fork(frame) - - // 下面是以前的实现,除非我们实现了子进程先运行的特性,否则不要使用,不然会导致父进程数据损坏 - // ProcessManager::fork( - // frame, - // CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL, - // ) - // .map(|pid| pid.into()) - } - - pub fn execve( - path: *const u8, - argv: *const *const u8, - envp: *const *const u8, - frame: &mut TrapFrame, - ) -> Result<(), SystemError> { - // debug!( - // "execve path: {:?}, argv: {:?}, envp: {:?}\n", - // path, - // argv, - // envp - // ); - // debug!( - // "before execve: strong count: {}", - // Arc::strong_count(&ProcessManager::current_pcb()) - // ); - - if path.is_null() { - return Err(SystemError::EINVAL); - } - - let x = || { - let path: CString = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; - let argv: Vec = check_and_clone_cstr_array(argv)?; - let envp: Vec = check_and_clone_cstr_array(envp)?; - Ok((path, argv, envp)) - }; - let (path, argv, envp) = x().inspect_err(|e: &SystemError| { - error!("Failed to execve: {:?}", e); - })?; - - let path = path.into_string().map_err(|_| SystemError::EINVAL)?; - ProcessManager::current_pcb() - .basic_mut() - .set_name(ProcessControlBlock::generate_name(&path, &argv)); - - Self::do_execve(path.clone(), argv, envp, frame)?; - - let pcb = ProcessManager::current_pcb(); - // 关闭设置了O_CLOEXEC的文件描述符 - let fd_table = pcb.fd_table(); - fd_table.write().close_on_exec(); - // debug!( - // "after execve: strong count: {}", - // Arc::strong_count(&ProcessManager::current_pcb()) - // ); - pcb.set_execute_path(path); - - return Ok(()); - } - - pub fn do_execve( - path: String, - argv: Vec, - envp: Vec, - regs: &mut TrapFrame, - ) -> Result<(), SystemError> { - let address_space = AddressSpace::new(true).expect("Failed to create new address space"); - // debug!("to load binary file"); - let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?; - let old_vm = do_execve_switch_user_vm(address_space.clone()); - - // 加载可执行文件 - let load_result = load_binary_file(&mut param).inspect_err(|_| { - if let Some(old_vm) = old_vm { - do_execve_switch_user_vm(old_vm); - } - })?; - - // debug!("load binary file done"); - // debug!("argv: {:?}, envp: {:?}", argv, envp); - param.init_info_mut().args = argv; - param.init_info_mut().envs = envp; - // // 生成16字节随机数 - param.init_info_mut().rand_num = rand_bytes::<16>(); - - // 把proc_init_info写到用户栈上 - let mut ustack_message = unsafe { - address_space - .write() - .user_stack_mut() - .expect("No user stack found") - .clone_info_only() - }; - let (user_sp, argv_ptr) = unsafe { - param - .init_info_mut() - .push_at( - // address_space - // .write() - // .user_stack_mut() - // .expect("No user stack found"), - &mut ustack_message, - ) - .expect("Failed to push proc_init_info to user stack") - }; - address_space.write().user_stack = Some(ustack_message); - - Self::arch_do_execve(regs, ¶m, &load_result, user_sp, argv_ptr) - } - - pub fn wait4( - pid: i32, - wstatus: *mut i32, - options: i32, - rusage: *mut c_void, - ) -> Result { - let options = WaitOption::from_bits(options as u32).ok_or(SystemError::EINVAL)?; - - let wstatus_buf = if wstatus.is_null() { - None - } else { - Some(UserBufferWriter::new( - wstatus, - core::mem::size_of::(), - true, - )?) - }; - - let mut tmp_rusage = if rusage.is_null() { - None - } else { - Some(RUsage::default()) - }; - - let r = kernel_wait4(pid, wstatus_buf, options, tmp_rusage.as_mut())?; - - if !rusage.is_null() { - let mut rusage_buf = UserBufferWriter::new::( - rusage as *mut RUsage, - core::mem::size_of::(), - true, - )?; - rusage_buf.copy_one_to_user(&tmp_rusage.unwrap(), 0)?; - } - return Ok(r); - } - - /// # 退出进程 - /// - /// ## 参数 - /// - /// - status: 退出状态 - pub fn exit(status: usize) -> ! { - ProcessManager::exit((status & 0xff) << 8); - } - - /// @brief 获取当前进程的pid - pub fn getpid() -> Result { - let current_pcb = ProcessManager::current_pcb(); - // if let Some(pid_ns) = ¤t_pcb.get_nsproxy().read().pid_namespace { - // // 获取该进程在命名空间中的 PID - // return Ok(current_pcb.pid_strcut().read().numbers[pid_ns.level].nr); - // // 返回命名空间中的 PID - // } - // 默认返回 tgid - Ok(current_pcb.tgid()) - } - - /// @brief 获取指定进程的pgid - /// - /// @param pid 指定一个进程号 - /// - /// @return 成功,指定进程的进程组id - /// @return 错误,不存在该进程 - pub fn getpgid(pid: Pid) -> Result { - if pid == Pid(0) { - let current_pcb = ProcessManager::current_pcb(); - return Ok(current_pcb.pgid()); - } - let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; - return Ok(target_proc.pgid()); - } - - /// 设置指定进程的pgid - /// - /// ## 参数 - /// - /// - pid: 指定进程号 - /// - pgid: 新的进程组号 - /// - /// ## 返回值 - /// 无 - pub fn setpgid(pid: Pid, pgid: Pgid) -> Result { - let current_pcb = ProcessManager::current_pcb(); - let pid = if pid == Pid(0) { - current_pcb.pid() - } else { - pid - }; - let pgid = if pgid == Pgid::from(0) { - Pgid::from(pid.into()) - } else { - pgid - }; - if pid != current_pcb.pid() && !current_pcb.contain_child(&pid) { - return Err(SystemError::ESRCH); - } - - if pgid.into() != pid.into() && ProcessManager::find_process_group(pgid).is_none() { - return Err(SystemError::EPERM); - } - let pcb = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; - pcb.join_other_group(pgid)?; - - return Ok(0); - } - - /// 创建新的会话 - pub fn setsid() -> Result { - let pcb = ProcessManager::current_pcb(); - let session = pcb.go_to_new_session()?; - let mut guard = pcb.sig_info_mut(); - guard.set_tty(None); - Ok(session.sid().into()) - } - - /// 获取指定进程的会话id - /// - /// 若pid为0,则返回当前进程的会话id - /// - /// 若pid不为0,则返回指定进程的会话id - pub fn getsid(pid: Pid) -> Result { - let session = ProcessManager::current_pcb().session().unwrap(); - let sid = session.sid().into(); - if pid == Pid(0) { - return Ok(sid); - } - let pcb = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; - if !Arc::ptr_eq(&session, &pcb.session().unwrap()) { - return Err(SystemError::EPERM); - } - return Ok(sid); - } - - /// @brief 获取当前进程的父进程id - /// - /// 若为initproc则ppid设置为0 - pub fn getppid() -> Result { - let current_pcb = ProcessManager::current_pcb(); - return Ok(current_pcb.basic().ppid()); - } - - pub fn clone( - current_trapframe: &TrapFrame, - clone_args: KernelCloneArgs, - ) -> Result { - let flags = clone_args.flags; - - let vfork = Arc::new(Completion::new()); - - if flags.contains(CloneFlags::CLONE_PIDFD) - && flags.contains(CloneFlags::CLONE_PARENT_SETTID) - { - return Err(SystemError::EINVAL); - } - - let current_pcb = ProcessManager::current_pcb(); - let new_kstack = KernelStack::new()?; - let name = current_pcb.basic().name().to_string(); - - let pcb = ProcessControlBlock::new(name, new_kstack); - // 克隆pcb - ProcessManager::copy_process(¤t_pcb, &pcb, clone_args, current_trapframe)?; - - // 向procfs注册进程 - procfs_register_pid(pcb.pid()).unwrap_or_else(|e| { - panic!( - "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}", - pcb.pid(), - e - ) - }); - - if flags.contains(CloneFlags::CLONE_VFORK) { - pcb.thread.write_irqsave().vfork_done = Some(vfork.clone()); - } - - if pcb.thread.read_irqsave().set_child_tid.is_some() { - let addr = pcb.thread.read_irqsave().set_child_tid.unwrap(); - let mut writer = - UserBufferWriter::new(addr.as_ptr::(), core::mem::size_of::(), true)?; - writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?; - } - - ProcessManager::wakeup(&pcb).unwrap_or_else(|e| { - panic!( - "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}", - pcb.pid(), - e - ) - }); - - if flags.contains(CloneFlags::CLONE_VFORK) { - // 等待子进程结束或者exec; - vfork.wait_for_completion_interruptible()?; - } - - return Ok(pcb.pid().0); - } - - /// 设置线程地址 - pub fn set_tid_address(ptr: usize) -> Result { - verify_area(VirtAddr::new(ptr), core::mem::size_of::()) - .map_err(|_| SystemError::EFAULT)?; - - let pcb = ProcessManager::current_pcb(); - pcb.thread.write_irqsave().clear_child_tid = Some(VirtAddr::new(ptr)); - Ok(pcb.pid.0) - } - - pub fn gettid() -> Result { - let pcb = ProcessManager::current_pcb(); - Ok(pcb.pid) - } - - pub fn getuid() -> Result { - let pcb = ProcessManager::current_pcb(); - return Ok(pcb.cred.lock().uid.data()); - } - - pub fn getgid() -> Result { - let pcb = ProcessManager::current_pcb(); - return Ok(pcb.cred.lock().gid.data()); - } - - pub fn geteuid() -> Result { - let pcb = ProcessManager::current_pcb(); - return Ok(pcb.cred.lock().euid.data()); - } - - pub fn getegid() -> Result { - let pcb = ProcessManager::current_pcb(); - return Ok(pcb.cred.lock().egid.data()); - } - - pub fn setuid(uid: usize) -> Result { - let pcb = ProcessManager::current_pcb(); - let mut guard = pcb.cred.lock(); - - if guard.uid.data() == 0 { - guard.setuid(uid); - guard.seteuid(uid); - guard.setsuid(uid); - } else if uid == guard.uid.data() || uid == guard.suid.data() { - guard.seteuid(uid); - } else { - return Err(SystemError::EPERM); - } - - return Ok(0); - } - - pub fn setgid(gid: usize) -> Result { - let pcb = ProcessManager::current_pcb(); - let mut guard = pcb.cred.lock(); - - if guard.egid.data() == 0 { - guard.setgid(gid); - guard.setegid(gid); - guard.setsgid(gid); - guard.setfsgid(gid); - } else if guard.gid.data() == gid || guard.sgid.data() == gid { - guard.setegid(gid); - guard.setfsgid(gid); - } else { - return Err(SystemError::EPERM); - } - - return Ok(0); - } - - pub fn seteuid(euid: usize) -> Result { - let pcb = ProcessManager::current_pcb(); - let mut guard = pcb.cred.lock(); - - if euid == usize::MAX || (euid == guard.euid.data() && euid == guard.fsuid.data()) { - return Ok(0); - } - - if euid != usize::MAX { - guard.seteuid(euid); - } - - let euid = guard.euid.data(); - guard.setfsuid(euid); - - return Ok(0); - } - - pub fn setegid(egid: usize) -> Result { - let pcb = ProcessManager::current_pcb(); - let mut guard = pcb.cred.lock(); - - if egid == usize::MAX || (egid == guard.egid.data() && egid == guard.fsgid.data()) { - return Ok(0); - } - - if egid != usize::MAX { - guard.setegid(egid); - } - - let egid = guard.egid.data(); - guard.setfsgid(egid); - - return Ok(0); - } - - pub fn setfsuid(fsuid: usize) -> Result { - let fsuid = Kuid::new(fsuid); - - let pcb = ProcessManager::current_pcb(); - let mut guard = pcb.cred.lock(); - let old_fsuid = guard.fsuid; - - if fsuid == guard.uid || fsuid == guard.euid || fsuid == guard.suid { - guard.setfsuid(fsuid.data()); - } - - Ok(old_fsuid.data()) - } - - pub fn setfsgid(fsgid: usize) -> Result { - let fsgid = Kgid::new(fsgid); - - let pcb = ProcessManager::current_pcb(); - let mut guard = pcb.cred.lock(); - let old_fsgid = guard.fsgid; - - if fsgid == guard.gid || fsgid == guard.egid || fsgid == guard.sgid { - guard.setfsgid(fsgid.data()); - } - - Ok(old_fsgid.data()) - } - - pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result { - let who = RUsageWho::try_from(who)?; - let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::(), true)?; - let pcb = ProcessManager::current_pcb(); - let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?; - - let ubuf = writer.buffer::(0).unwrap(); - ubuf.copy_from_slice(&[rusage]); - - return Ok(0); - } - - /// # 设置资源限制 - /// - /// TODO: 目前暂时不支持设置资源限制,只提供读取默认值的功能 - /// - /// ## 参数 - /// - /// - pid: 进程号 - /// - resource: 资源类型 - /// - new_limit: 新的资源限制 - /// - old_limit: 旧的资源限制 - /// - /// ## 返回值 - /// - /// - 成功,0 - /// - 如果old_limit不为NULL,则返回旧的资源限制到old_limit - /// - pub fn prlimit64( - _pid: Pid, - resource: usize, - _new_limit: *const RLimit64, - old_limit: *mut RLimit64, - ) -> Result { - let resource = RLimitID::try_from(resource)?; - let mut writer = None; - - if !old_limit.is_null() { - writer = Some(UserBufferWriter::new( - old_limit, - core::mem::size_of::(), - true, - )?); - } - - match resource { - RLimitID::Stack => { - if let Some(mut writer) = writer { - let mut rlimit = writer.buffer::(0).unwrap()[0]; - rlimit.rlim_cur = UserStack::DEFAULT_USER_STACK_SIZE as u64; - rlimit.rlim_max = UserStack::DEFAULT_USER_STACK_SIZE as u64; - } - return Ok(0); - } - - RLimitID::Nofile => { - if let Some(mut writer) = writer { - let mut rlimit = writer.buffer::(0).unwrap()[0]; - rlimit.rlim_cur = FileDescriptorVec::PROCESS_MAX_FD as u64; - rlimit.rlim_max = FileDescriptorVec::PROCESS_MAX_FD as u64; - } - return Ok(0); - } - - RLimitID::As | RLimitID::Rss => { - if let Some(mut writer) = writer { - let mut rlimit = writer.buffer::(0).unwrap()[0]; - rlimit.rlim_cur = MMArch::USER_END_VADDR.data() as u64; - rlimit.rlim_max = MMArch::USER_END_VADDR.data() as u64; - } - return Ok(0); - } - - _ => { - return Err(SystemError::ENOSYS); - } - } - } - - pub fn uname(name: *mut PosixOldUtsName) -> Result { - let mut writer = - UserBufferWriter::new(name, core::mem::size_of::(), true)?; - writer.copy_one_to_user(&PosixOldUtsName::new(), 0)?; - - return Ok(0); - } -} - -/// 切换用户虚拟内存空间 -/// -/// 该函数用于在执行系统调用 `execve` 时切换用户进程的虚拟内存空间。 -/// -/// # 参数 -/// - `new_vm`: 新的用户地址空间,类型为 `Arc`。 -/// -/// # 返回值 -/// - 返回旧的用户地址空间的引用,类型为 `Option>`。 -/// -/// # 错误处理 -/// 如果地址空间切换失败,函数会触发断言失败,并输出错误信息。 -fn do_execve_switch_user_vm(new_vm: Arc) -> Option> { - // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 - let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; - let pcb = ProcessManager::current_pcb(); - // log::debug!( - // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n", - // pcb.pid(), - // path, - // argv, - // envp - // ); - - let mut basic_info = pcb.basic_mut(); - // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free) - let old_address_space = basic_info.user_vm(); - - // 在pcb中原来的用户地址空间 - unsafe { - basic_info.set_user_vm(None); - } - // 创建新的地址空间并设置为当前地址空间 - unsafe { - basic_info.set_user_vm(Some(new_vm.clone())); - } - - // to avoid deadlock - drop(basic_info); - - assert!( - AddressSpace::is_current(&new_vm), - "Failed to set address space" - ); - // debug!("Switch to new address space"); - - // 切换到新的用户地址空间 - unsafe { new_vm.read().user_mapper.utable.make_current() }; - - drop(irq_guard); - - old_address_space -} diff --git a/kernel/src/process/syscall/mod.rs b/kernel/src/process/syscall/mod.rs new file mode 100644 index 00000000..7d3dd9ce --- /dev/null +++ b/kernel/src/process/syscall/mod.rs @@ -0,0 +1,81 @@ +mod sys_clone; +mod sys_execve; +mod sys_exit; +mod sys_exit_group; +mod sys_get_rusage; +mod sys_getegid; +mod sys_geteuid; +mod sys_getgid; +mod sys_getpgid; +mod sys_getpid; +mod sys_getppid; +mod sys_getsid; +mod sys_gettid; +mod sys_getuid; +mod sys_prlimit64; +mod sys_set_tid_address; +mod sys_setfsgid; +mod sys_setfsuid; +mod sys_setgid; +mod sys_setpgid; +mod sys_setresgid; +mod sys_setresuid; +mod sys_setsid; +mod sys_setuid; +mod sys_uname; +mod sys_wait4; + +#[cfg(target_arch = "x86_64")] +mod sys_fork; +#[cfg(target_arch = "x86_64")] +mod sys_getrlimit; +#[cfg(target_arch = "x86_64")] +mod sys_vfork; + +//参考资料:https://code.dragonos.org.cn/xref/linux-6.1.9/include/uapi/linux/utsname.h#17 +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct PosixOldUtsName { + pub sysname: [u8; 65], + pub nodename: [u8; 65], + pub release: [u8; 65], + pub version: [u8; 65], + pub machine: [u8; 65], +} + +impl PosixOldUtsName { + pub fn new() -> Self { + const SYS_NAME: &[u8] = b"Linux"; + const NODENAME: &[u8] = b"DragonOS"; + const RELEASE: &[u8] = b"5.19.0"; + const VERSION: &[u8] = b"5.19.0"; + + #[cfg(target_arch = "x86_64")] + const MACHINE: &[u8] = b"x86_64"; + + #[cfg(target_arch = "aarch64")] + const MACHINE: &[u8] = b"aarch64"; + + #[cfg(target_arch = "riscv64")] + const MACHINE: &[u8] = b"riscv64"; + + #[cfg(target_arch = "loongarch64")] + const MACHINE: &[u8] = b"longarch64"; + + let mut r = Self { + sysname: [0; 65], + nodename: [0; 65], + release: [0; 65], + version: [0; 65], + machine: [0; 65], + }; + + r.sysname[0..SYS_NAME.len()].copy_from_slice(SYS_NAME); + r.nodename[0..NODENAME.len()].copy_from_slice(NODENAME); + r.release[0..RELEASE.len()].copy_from_slice(RELEASE); + r.version[0..VERSION.len()].copy_from_slice(VERSION); + r.machine[0..MACHINE.len()].copy_from_slice(MACHINE); + + return r; + } +} diff --git a/kernel/src/process/syscall/sys_clone.rs b/kernel/src/process/syscall/sys_clone.rs new file mode 100644 index 00000000..67bf1077 --- /dev/null +++ b/kernel/src/process/syscall/sys_clone.rs @@ -0,0 +1,128 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_CLONE; +use crate::filesystem::procfs::procfs_register_pid; +use crate::mm::{verify_area, VirtAddr}; +use crate::process::fork::{CloneFlags, KernelCloneArgs}; +use crate::process::{KernelStack, ProcessControlBlock, ProcessManager}; +use crate::sched::completion::Completion; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use crate::syscall::user_access::UserBufferWriter; +use alloc::vec::Vec; +use alloc::{string::ToString, sync::Arc}; +use system_error::SystemError; + +pub struct SysClone; + +impl SysClone { + fn parent_tid(args: &[usize]) -> VirtAddr { + VirtAddr::new(args[2]) + } + + fn child_tid(args: &[usize]) -> VirtAddr { + VirtAddr::new(args[3]) + } + + fn flags(args: &[usize]) -> CloneFlags { + CloneFlags::from_bits_truncate(args[0] as u64) + } + + fn stack(args: &[usize]) -> usize { + args[1] + } + + fn tls(args: &[usize]) -> usize { + args[4] + } +} + +impl Syscall for SysClone { + fn num_args(&self) -> usize { + 5 + } + + fn handle(&self, args: &[usize], frame: &mut TrapFrame) -> Result { + let parent_tid = Self::parent_tid(args); + let child_tid = Self::child_tid(args); + + // 地址校验 + verify_area(parent_tid, core::mem::size_of::())?; + verify_area(child_tid, core::mem::size_of::())?; + + let flags = Self::flags(args); + let stack = Self::stack(args); + let tls = Self::tls(args); + + let mut clone_args = KernelCloneArgs::new(); + clone_args.flags = flags; + clone_args.stack = stack; + clone_args.parent_tid = parent_tid; + clone_args.child_tid = child_tid; + clone_args.tls = tls; + + let vfork = Arc::new(Completion::new()); + + if flags.contains(CloneFlags::CLONE_PIDFD) + && flags.contains(CloneFlags::CLONE_PARENT_SETTID) + { + return Err(SystemError::EINVAL); + } + + let current_pcb = ProcessManager::current_pcb(); + let new_kstack = KernelStack::new()?; + let name = current_pcb.basic().name().to_string(); + + let pcb = ProcessControlBlock::new(name, new_kstack); + // 克隆pcb + ProcessManager::copy_process(¤t_pcb, &pcb, clone_args, frame)?; + + // 向procfs注册进程 + procfs_register_pid(pcb.pid()).unwrap_or_else(|e| { + panic!( + "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}", + pcb.pid(), + e + ) + }); + + if flags.contains(CloneFlags::CLONE_VFORK) { + pcb.thread.write_irqsave().vfork_done = Some(vfork.clone()); + } + + if pcb.thread.read_irqsave().set_child_tid.is_some() { + let addr = pcb.thread.read_irqsave().set_child_tid.unwrap(); + let mut writer = + UserBufferWriter::new(addr.as_ptr::(), core::mem::size_of::(), true)?; + writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?; + } + + ProcessManager::wakeup(&pcb).unwrap_or_else(|e| { + panic!( + "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}", + pcb.pid(), + e + ) + }); + + if flags.contains(CloneFlags::CLONE_VFORK) { + // 等待子进程结束或者exec; + vfork.wait_for_completion_interruptible()?; + } + + return Ok(pcb.pid().0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new( + "parent_tid", + format!("{:#x}", Self::parent_tid(args).data()), + ), + FormattedSyscallParam::new("child_tid", format!("{:#x}", Self::child_tid(args).data())), + FormattedSyscallParam::new("flags", format!("{:#x}", Self::flags(args))), + FormattedSyscallParam::new("stack", format!("{:#x}", Self::stack(args))), + FormattedSyscallParam::new("tls", format!("{:#x}", Self::tls(args))), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_CLONE, SysClone); diff --git a/kernel/src/process/syscall/sys_execve.rs b/kernel/src/process/syscall/sys_execve.rs new file mode 100644 index 00000000..3a4f470a --- /dev/null +++ b/kernel/src/process/syscall/sys_execve.rs @@ -0,0 +1,98 @@ +use log::error; + +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_EXECVE; +use crate::filesystem::vfs::MAX_PATHLEN; +use crate::mm::page::PAGE_4K_SIZE; +use crate::mm::{verify_area, VirtAddr}; +use crate::process::execve::do_execve; +use crate::process::{ProcessControlBlock, ProcessManager}; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use crate::syscall::user_access::{check_and_clone_cstr, check_and_clone_cstr_array}; +use alloc::{ffi::CString, vec::Vec}; +use system_error::SystemError; + +pub struct SysExecve; + +impl SysExecve { + fn path_ptr(args: &[usize]) -> usize { + args[0] + } + + fn argv_ptr(args: &[usize]) -> usize { + args[1] + } + + fn env_ptr(args: &[usize]) -> usize { + args[2] + } +} + +impl Syscall for SysExecve { + fn num_args(&self) -> usize { + 3 + } + + fn handle(&self, args: &[usize], frame: &mut TrapFrame) -> Result { + let path_ptr = Self::path_ptr(args); + let argv_ptr = Self::argv_ptr(args); + let env_ptr = Self::env_ptr(args); + + let virt_path_ptr = VirtAddr::new(path_ptr); + let virt_argv_ptr = VirtAddr::new(argv_ptr); + let virt_env_ptr = VirtAddr::new(env_ptr); + + // 权限校验 + if frame.is_from_user() + && (verify_area(virt_path_ptr, MAX_PATHLEN).is_err() + || verify_area(virt_argv_ptr, PAGE_4K_SIZE).is_err()) + || verify_area(virt_env_ptr, PAGE_4K_SIZE).is_err() + { + Err(SystemError::EFAULT) + } else { + let path = path_ptr as *const u8; + let argv = argv_ptr as *const *const u8; + let envp = env_ptr as *const *const u8; + + if path.is_null() { + return Err(SystemError::EINVAL); + } + + let x = || { + let path: CString = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; + let argv: Vec = check_and_clone_cstr_array(argv)?; + let envp: Vec = check_and_clone_cstr_array(envp)?; + Ok((path, argv, envp)) + }; + let (path, argv, envp) = x().inspect_err(|e: &SystemError| { + error!("Failed to execve: {:?}", e); + })?; + + let path = path.into_string().map_err(|_| SystemError::EINVAL)?; + ProcessManager::current_pcb() + .basic_mut() + .set_name(ProcessControlBlock::generate_name(&path, &argv)); + + do_execve(path.clone(), argv, envp, frame)?; + + let pcb = ProcessManager::current_pcb(); + // 关闭设置了O_CLOEXEC的文件描述符 + let fd_table = pcb.fd_table(); + fd_table.write().close_on_exec(); + + pcb.set_execute_path(path); + + return Ok(0); + } + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("path", format!("{:#x}", Self::path_ptr(args))), + FormattedSyscallParam::new("argv", format!("{:#x}", Self::argv_ptr(args))), + FormattedSyscallParam::new("env", format!("{:#x}", Self::env_ptr(args))), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_EXECVE, SysExecve); diff --git a/kernel/src/process/syscall/sys_exit.rs b/kernel/src/process/syscall/sys_exit.rs new file mode 100644 index 00000000..796126fe --- /dev/null +++ b/kernel/src/process/syscall/sys_exit.rs @@ -0,0 +1,34 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_EXIT; +use crate::process::ProcessManager; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysExit; + +impl SysExit { + fn exit_code(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysExit { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let exit_code = Self::exit_code(args); + ProcessManager::exit((exit_code & 0xff) << 8); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "exit_code", + format!("{:#x}", Self::exit_code(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_EXIT, SysExit); diff --git a/kernel/src/process/syscall/sys_exit_group.rs b/kernel/src/process/syscall/sys_exit_group.rs new file mode 100644 index 00000000..557f4e5b --- /dev/null +++ b/kernel/src/process/syscall/sys_exit_group.rs @@ -0,0 +1,34 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_EXIT_GROUP; +use crate::process::ProcessManager; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysExitGroup; + +impl SysExitGroup { + fn exit_code(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysExitGroup { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let exit_code = Self::exit_code(args); + ProcessManager::exit((exit_code & 0xff) << 8); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "exit_code", + format!("{:#x}", Self::exit_code(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_EXIT_GROUP, SysExitGroup); diff --git a/kernel/src/process/syscall/sys_fork.rs b/kernel/src/process/syscall/sys_fork.rs new file mode 100644 index 00000000..8a2aea69 --- /dev/null +++ b/kernel/src/process/syscall/sys_fork.rs @@ -0,0 +1,26 @@ +use crate::arch::interrupt::TrapFrame; +//use crate::arch::syscall::nr::SYS_FORK; +use crate::process::fork::CloneFlags; +use crate::process::ProcessManager; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysFork; + +impl Syscall for SysFork { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], frame: &mut TrapFrame) -> Result { + log::debug!("fork"); + ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()) + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +//syscall_table_macros::declare_syscall!(SYS_FORK, SysFork); diff --git a/kernel/src/process/syscall/sys_get_rusage.rs b/kernel/src/process/syscall/sys_get_rusage.rs new file mode 100644 index 00000000..ba7a77e7 --- /dev/null +++ b/kernel/src/process/syscall/sys_get_rusage.rs @@ -0,0 +1,52 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETRUSAGE; +use crate::process::resource::RUsageWho; +use crate::process::{resource::RUsage, ProcessManager}; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use crate::syscall::user_access::UserBufferWriter; +use alloc::vec::Vec; +use core::ffi::c_int; +use system_error::SystemError; + +pub struct SysGetRusage; + +impl SysGetRusage { + fn who(args: &[usize]) -> c_int { + args[0] as c_int + } + + fn rusage(args: &[usize]) -> *mut RUsage { + args[1] as *mut RUsage + } +} + +impl Syscall for SysGetRusage { + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let who = Self::who(args); + let rusage = Self::rusage(args); + + let who = RUsageWho::try_from(who)?; + let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::(), true)?; + let pcb = ProcessManager::current_pcb(); + let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?; + + let ubuf = writer.buffer::(0).unwrap(); + ubuf.copy_from_slice(&[rusage]); + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("who", format!("{:#x}", Self::who(args))), + FormattedSyscallParam::new("rusage", format!("{:#x}", Self::rusage(args) as usize)), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETRUSAGE, SysGetRusage); diff --git a/kernel/src/process/syscall/sys_getegid.rs b/kernel/src/process/syscall/sys_getegid.rs new file mode 100644 index 00000000..ae044793 --- /dev/null +++ b/kernel/src/process/syscall/sys_getegid.rs @@ -0,0 +1,26 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETEGID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysGetEgid; + +impl Syscall for SysGetEgid { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let pcb = ProcessManager::current_pcb(); + return Ok(pcb.cred.lock().egid.data()); + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETEGID, SysGetEgid); diff --git a/kernel/src/process/syscall/sys_geteuid.rs b/kernel/src/process/syscall/sys_geteuid.rs new file mode 100644 index 00000000..7c328408 --- /dev/null +++ b/kernel/src/process/syscall/sys_geteuid.rs @@ -0,0 +1,25 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETEUID; +use crate::process::geteuid::do_geteuid; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysGetEuid; + +impl Syscall for SysGetEuid { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + do_geteuid() + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETEUID, SysGetEuid); diff --git a/kernel/src/process/syscall/sys_getgid.rs b/kernel/src/process/syscall/sys_getgid.rs new file mode 100644 index 00000000..e00e1a5c --- /dev/null +++ b/kernel/src/process/syscall/sys_getgid.rs @@ -0,0 +1,25 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETGID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysGetGid; + +impl Syscall for SysGetGid { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let pcb = ProcessManager::current_pcb(); + return Ok(pcb.cred.lock().gid.data()); + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETGID, SysGetGid); diff --git a/kernel/src/process/syscall/sys_getpgid.rs b/kernel/src/process/syscall/sys_getpgid.rs new file mode 100644 index 00000000..331e01f0 --- /dev/null +++ b/kernel/src/process/syscall/sys_getpgid.rs @@ -0,0 +1,49 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETPGID; +use crate::process::Pid; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysGetPgid; + +impl SysGetPgid { + fn pid(args: &[usize]) -> Pid { + Pid::new(args[0]) + } +} + +impl Syscall for SysGetPgid { + fn num_args(&self) -> usize { + 1 + } + + /// # 函数的功能 + /// 获取指定进程的pgid + /// + /// ## 参数 + /// - pid: 指定一个进程号 + /// + /// ## 返回值 + /// - 成功,指定进程的进程组id + /// - 错误,不存在该进程 + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let pid = Self::pid(args); + if pid == Pid(0) { + let current_pcb = ProcessManager::current_pcb(); + return Ok(current_pcb.pgid().into()); + } + let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; + return Ok(target_proc.pgid().into()); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "pid", + format!("{:#x}", Self::pid(args).0), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETPGID, SysGetPgid); diff --git a/kernel/src/process/syscall/sys_getpid.rs b/kernel/src/process/syscall/sys_getpid.rs new file mode 100644 index 00000000..72d2ff1b --- /dev/null +++ b/kernel/src/process/syscall/sys_getpid.rs @@ -0,0 +1,33 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETPID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysGetPid; + +impl Syscall for SysGetPid { + fn num_args(&self) -> usize { + 0 + } + + /// # 函数的功能 + /// 获取当前进程的pid + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let current_pcb = ProcessManager::current_pcb(); + // if let Some(pid_ns) = ¤t_pcb.get_nsproxy().read().pid_namespace { + // // 获取该进程在命名空间中的 PID + // return Ok(current_pcb.pid_strcut().read().numbers[pid_ns.level].nr); + // // 返回命名空间中的 PID + // } + // 默认返回 tgid + return Ok(current_pcb.tgid().into()); + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETPID, SysGetPid); diff --git a/kernel/src/process/syscall/sys_getppid.rs b/kernel/src/process/syscall/sys_getppid.rs new file mode 100644 index 00000000..f4ef8bd3 --- /dev/null +++ b/kernel/src/process/syscall/sys_getppid.rs @@ -0,0 +1,27 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETPPID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysGetPpid; + +impl Syscall for SysGetPpid { + fn num_args(&self) -> usize { + 0 + } + + /// # 函数的功能 + /// 获取当前进程的父进程id + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let current_pcb = ProcessManager::current_pcb(); + return Ok(current_pcb.basic().ppid().into()); + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETPPID, SysGetPpid); diff --git a/kernel/src/process/syscall/sys_getrlimit.rs b/kernel/src/process/syscall/sys_getrlimit.rs new file mode 100644 index 00000000..815d22fa --- /dev/null +++ b/kernel/src/process/syscall/sys_getrlimit.rs @@ -0,0 +1,50 @@ +use system_error::SystemError; + +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETRLIMIT; +use crate::process::resource::RLimit64; +use crate::process::syscall::sys_prlimit64::do_prlimit64; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; + +use alloc::vec::Vec; + +pub struct SysGetRlimit; + +impl SysGetRlimit { + fn resource(args: &[usize]) -> usize { + args[0] + } + + fn rlimit(args: &[usize]) -> *mut RLimit64 { + args[1] as *mut RLimit64 + } +} + +impl Syscall for SysGetRlimit { + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let resource = Self::resource(args); + let rlimit = Self::rlimit(args); + + do_prlimit64( + ProcessManager::current_pcb().pid(), + resource, + core::ptr::null::(), + rlimit, + ) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("resource", format!("{:#x}", Self::resource(args))), + FormattedSyscallParam::new("rlimit", format!("{:#x}", Self::rlimit(args) as usize)), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETRLIMIT, SysGetRlimit); diff --git a/kernel/src/process/syscall/sys_getsid.rs b/kernel/src/process/syscall/sys_getsid.rs new file mode 100644 index 00000000..2bdb710f --- /dev/null +++ b/kernel/src/process/syscall/sys_getsid.rs @@ -0,0 +1,54 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETSID; +use crate::process::Pid; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::sync::Arc; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysGetsid; + +impl SysGetsid { + fn pid(args: &[usize]) -> Pid { + Pid::new(args[0]) + } +} + +impl Syscall for SysGetsid { + fn num_args(&self) -> usize { + 1 + } + + /// # 函数的功能 + /// 获取指定进程的会话id + /// + /// 若pid为0,则返回当前进程的会话id + /// + /// 若pid不为0,则返回指定进程的会话id + /// + /// ## 参数 + /// - pid: 指定一个进程号 + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let pid = Self::pid(args); + let session = ProcessManager::current_pcb().session().unwrap(); + let sid = session.sid().into(); + if pid == Pid(0) { + return Ok(sid); + } + let pcb = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; + if !Arc::ptr_eq(&session, &pcb.session().unwrap()) { + return Err(SystemError::EPERM); + } + return Ok(sid); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "pid", + format!("{:#x}", Self::pid(args).0), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETSID, SysGetsid); diff --git a/kernel/src/process/syscall/sys_gettid.rs b/kernel/src/process/syscall/sys_gettid.rs new file mode 100644 index 00000000..5e825668 --- /dev/null +++ b/kernel/src/process/syscall/sys_gettid.rs @@ -0,0 +1,25 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETTID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysGetTid; + +impl Syscall for SysGetTid { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let pcb = ProcessManager::current_pcb(); + return Ok(pcb.pid.into()); + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETTID, SysGetTid); diff --git a/kernel/src/process/syscall/sys_getuid.rs b/kernel/src/process/syscall/sys_getuid.rs new file mode 100644 index 00000000..19fa7edb --- /dev/null +++ b/kernel/src/process/syscall/sys_getuid.rs @@ -0,0 +1,26 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_GETUID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysGetUid; + +impl Syscall for SysGetUid { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let pcb = ProcessManager::current_pcb(); + return Ok(pcb.cred.lock().uid.data()); + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_GETUID, SysGetUid); diff --git a/kernel/src/process/syscall/sys_prlimit64.rs b/kernel/src/process/syscall/sys_prlimit64.rs new file mode 100644 index 00000000..bdac7ad9 --- /dev/null +++ b/kernel/src/process/syscall/sys_prlimit64.rs @@ -0,0 +1,135 @@ +use crate::arch::syscall::nr::SYS_PRLIMIT64; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use crate::{ + arch::MMArch, + filesystem::vfs::file::FileDescriptorVec, + mm::{ucontext::UserStack, MemoryManagementArch}, + process::{ + resource::{RLimit64, RLimitID}, + Pid, + }, + syscall::user_access::UserBufferWriter, +}; +use alloc::vec::Vec; +use system_error::SystemError; + +use crate::arch::interrupt::TrapFrame; +pub struct SysPrlimit64; + +impl SysPrlimit64 { + fn pid(args: &[usize]) -> Pid { + Pid::new(args[0]) + } + + fn resource(args: &[usize]) -> usize { + args[1] + } + + fn new_limit(args: &[usize]) -> *const RLimit64 { + args[2] as *const RLimit64 + } + + fn old_limit(args: &[usize]) -> *mut RLimit64 { + args[3] as *mut RLimit64 + } +} + +impl Syscall for SysPrlimit64 { + fn num_args(&self) -> usize { + 4 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let pid = Self::pid(args); + let resource = Self::resource(args); + let new_limit = Self::new_limit(args); + let old_limit = Self::old_limit(args); + + do_prlimit64(pid, resource, new_limit, old_limit) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("pid", format!("{:#x}", Self::pid(args).data())), + FormattedSyscallParam::new("resource", format!("{:#x}", Self::resource(args))), + FormattedSyscallParam::new( + "new_limit", + format!("{:#x}", Self::new_limit(args) as usize), + ), + FormattedSyscallParam::new( + "old_limit", + format!("{:#x}", Self::old_limit(args) as usize), + ), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_PRLIMIT64, SysPrlimit64); + +/// # 设置资源限制 +/// +/// TODO: 目前暂时不支持设置资源限制,只提供读取默认值的功能 +/// +/// ## 参数 +/// +/// - pid: 进程号 +/// - resource: 资源类型 +/// - new_limit: 新的资源限制 +/// - old_limit: 旧的资源限制 +/// +/// ## 返回值 +/// +/// - 成功,0 +/// - 如果old_limit不为NULL,则返回旧的资源限制到old_limit +/// +pub(super) fn do_prlimit64( + _pid: Pid, + resource: usize, + _new_limit: *const RLimit64, + old_limit: *mut RLimit64, +) -> Result { + let resource = RLimitID::try_from(resource)?; + let mut writer = None; + + if !old_limit.is_null() { + writer = Some(UserBufferWriter::new( + old_limit, + core::mem::size_of::(), + true, + )?); + } + + match resource { + RLimitID::Stack => { + if let Some(mut writer) = writer { + let mut rlimit = writer.buffer::(0).unwrap()[0]; + rlimit.rlim_cur = UserStack::DEFAULT_USER_STACK_SIZE as u64; + rlimit.rlim_max = UserStack::DEFAULT_USER_STACK_SIZE as u64; + } + return Ok(0); + } + + RLimitID::Nofile => { + if let Some(mut writer) = writer { + let mut rlimit = writer.buffer::(0).unwrap()[0]; + rlimit.rlim_cur = FileDescriptorVec::PROCESS_MAX_FD as u64; + rlimit.rlim_max = FileDescriptorVec::PROCESS_MAX_FD as u64; + } + return Ok(0); + } + + RLimitID::As | RLimitID::Rss => { + if let Some(mut writer) = writer { + let mut rlimit = writer.buffer::(0).unwrap()[0]; + rlimit.rlim_cur = MMArch::USER_END_VADDR.data() as u64; + rlimit.rlim_max = MMArch::USER_END_VADDR.data() as u64; + } + return Ok(0); + } + + _ => { + return Err(SystemError::ENOSYS); + } + } +} diff --git a/kernel/src/process/syscall/sys_set_tid_address.rs b/kernel/src/process/syscall/sys_set_tid_address.rs new file mode 100644 index 00000000..ba02b45e --- /dev/null +++ b/kernel/src/process/syscall/sys_set_tid_address.rs @@ -0,0 +1,43 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SET_TID_ADDRESS; +use crate::mm::verify_area; +use crate::mm::VirtAddr; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetTidAddress; + +impl SysSetTidAddress { + fn ptr(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysSetTidAddress { + fn num_args(&self) -> usize { + 1 + } + + /// # 函数的功能 + /// 设置线程地址 + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let ptr = Self::ptr(args); + verify_area(VirtAddr::new(ptr), core::mem::size_of::()) + .map_err(|_| SystemError::EFAULT)?; + + let pcb = ProcessManager::current_pcb(); + pcb.thread.write_irqsave().clear_child_tid = Some(VirtAddr::new(ptr)); + Ok(pcb.pid.0) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "ptr", + format!("{:#x}", Self::ptr(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SET_TID_ADDRESS, SysSetTidAddress); diff --git a/kernel/src/process/syscall/sys_setfsgid.rs b/kernel/src/process/syscall/sys_setfsgid.rs new file mode 100644 index 00000000..7c63d2b5 --- /dev/null +++ b/kernel/src/process/syscall/sys_setfsgid.rs @@ -0,0 +1,46 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETFSGID; +use crate::process::cred::Kgid; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysSetFsgid; + +impl SysSetFsgid { + fn fsgid(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysSetFsgid { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let fsgid = Self::fsgid(args); + let fsgid = Kgid::new(fsgid); + + let pcb = ProcessManager::current_pcb(); + let mut guard = pcb.cred.lock(); + let old_fsgid = guard.fsgid; + + if fsgid == guard.gid || fsgid == guard.egid || fsgid == guard.sgid { + guard.setfsgid(fsgid.data()); + } + + Ok(old_fsgid.data()) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "fsgid", + format!("{:#x}", Self::fsgid(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETFSGID, SysSetFsgid); diff --git a/kernel/src/process/syscall/sys_setfsuid.rs b/kernel/src/process/syscall/sys_setfsuid.rs new file mode 100644 index 00000000..1823831c --- /dev/null +++ b/kernel/src/process/syscall/sys_setfsuid.rs @@ -0,0 +1,45 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETFSUID; +use crate::process::cred::Kuid; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetFsuid; + +impl SysSetFsuid { + fn fsuid(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysSetFsuid { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let fsuid = Self::fsuid(args); + let fsuid = Kuid::new(fsuid); + + let pcb = ProcessManager::current_pcb(); + let mut guard = pcb.cred.lock(); + let old_fsuid = guard.fsuid; + + if fsuid == guard.uid || fsuid == guard.euid || fsuid == guard.suid { + guard.setfsuid(fsuid.data()); + } + + Ok(old_fsuid.data()) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "fsuid", + format!("{:#x}", Self::fsuid(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETFSUID, SysSetFsuid); diff --git a/kernel/src/process/syscall/sys_setgid.rs b/kernel/src/process/syscall/sys_setgid.rs new file mode 100644 index 00000000..a482c48c --- /dev/null +++ b/kernel/src/process/syscall/sys_setgid.rs @@ -0,0 +1,50 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETGID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysSetGid; + +impl SysSetGid { + fn gid(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysSetGid { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let gid = Self::gid(args); + let pcb = ProcessManager::current_pcb(); + let mut guard = pcb.cred.lock(); + + if guard.egid.data() == 0 { + guard.setgid(gid); + guard.setegid(gid); + guard.setsgid(gid); + guard.setfsgid(gid); + } else if guard.gid.data() == gid || guard.sgid.data() == gid { + guard.setegid(gid); + guard.setfsgid(gid); + } else { + return Err(SystemError::EPERM); + } + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "gid", + format!("{:#x}", Self::gid(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETGID, SysSetGid); diff --git a/kernel/src/process/syscall/sys_setpgid.rs b/kernel/src/process/syscall/sys_setpgid.rs new file mode 100644 index 00000000..1185a032 --- /dev/null +++ b/kernel/src/process/syscall/sys_setpgid.rs @@ -0,0 +1,69 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETPGID; +use crate::process::Pgid; +use crate::process::Pid; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetPgid; + +impl SysSetPgid { + fn pid(args: &[usize]) -> Pid { + Pid::new(args[0]) + } + + fn pgid(args: &[usize]) -> Pgid { + Pgid::new(args[1]) + } +} + +impl Syscall for SysSetPgid { + fn num_args(&self) -> usize { + 2 + } + + /// # 函数的功能 + /// 设置指定进程的pgid + /// + /// ## 参数 + /// - pid: 指定进程号 + /// - pgid: 新的进程组号 + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let pid = Self::pid(args); + let pgid = Self::pgid(args); + + let current_pcb = ProcessManager::current_pcb(); + let pid = if pid == Pid(0) { + current_pcb.pid() + } else { + pid + }; + let pgid = if pgid == Pgid::from(0) { + Pgid::from(pid.into()) + } else { + pgid + }; + if pid != current_pcb.pid() && !current_pcb.contain_child(&pid) { + return Err(SystemError::ESRCH); + } + + if pgid.into() != pid.into() && ProcessManager::find_process_group(pgid).is_none() { + return Err(SystemError::EPERM); + } + let pcb = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?; + pcb.join_other_group(pgid)?; + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("pid", format!("{:#x}", Self::pid(args).0)), + FormattedSyscallParam::new("pgid", format!("{:#x}", Self::pgid(args).0)), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETPGID, SysSetPgid); diff --git a/kernel/src/process/syscall/sys_setresgid.rs b/kernel/src/process/syscall/sys_setresgid.rs new file mode 100644 index 00000000..aa1eac6e --- /dev/null +++ b/kernel/src/process/syscall/sys_setresgid.rs @@ -0,0 +1,48 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETRESGID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetResGid; + +impl SysSetResGid { + fn egid(args: &[usize]) -> usize { + args[1] + } +} + +impl Syscall for SysSetResGid { + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let egid = Self::egid(args); + let pcb = ProcessManager::current_pcb(); + let mut guard = pcb.cred.lock(); + + if egid == usize::MAX || (egid == guard.egid.data() && egid == guard.fsgid.data()) { + return Ok(0); + } + + if egid != usize::MAX { + guard.setegid(egid); + } + + let egid = guard.egid.data(); + guard.setfsgid(egid); + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "egid", + format!("{:#x}", Self::egid(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETRESGID, SysSetResGid); diff --git a/kernel/src/process/syscall/sys_setresuid.rs b/kernel/src/process/syscall/sys_setresuid.rs new file mode 100644 index 00000000..2041933b --- /dev/null +++ b/kernel/src/process/syscall/sys_setresuid.rs @@ -0,0 +1,48 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETRESUID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetResUid; + +impl SysSetResUid { + fn euid(args: &[usize]) -> usize { + args[1] + } +} + +impl Syscall for SysSetResUid { + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let euid = Self::euid(args); + let pcb = ProcessManager::current_pcb(); + let mut guard = pcb.cred.lock(); + + if euid == usize::MAX || (euid == guard.euid.data() && euid == guard.fsuid.data()) { + return Ok(0); + } + + if euid != usize::MAX { + guard.seteuid(euid); + } + + let euid = guard.euid.data(); + guard.setfsuid(euid); + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "euid", + format!("{:#x}", Self::euid(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETRESUID, SysSetResUid); diff --git a/kernel/src/process/syscall/sys_setsid.rs b/kernel/src/process/syscall/sys_setsid.rs new file mode 100644 index 00000000..5f6fb82e --- /dev/null +++ b/kernel/src/process/syscall/sys_setsid.rs @@ -0,0 +1,30 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETSID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetsid; + +impl Syscall for SysSetsid { + fn num_args(&self) -> usize { + 0 + } + + /// # 函数的功能 + /// 创建新的会话 + fn handle(&self, _args: &[usize], _frame: &mut TrapFrame) -> Result { + let pcb = ProcessManager::current_pcb(); + let session = pcb.go_to_new_session()?; + let mut guard = pcb.sig_info_mut(); + guard.set_tty(None); + Ok(session.sid().into()) + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETSID, SysSetsid); diff --git a/kernel/src/process/syscall/sys_setuid.rs b/kernel/src/process/syscall/sys_setuid.rs new file mode 100644 index 00000000..4c392bd8 --- /dev/null +++ b/kernel/src/process/syscall/sys_setuid.rs @@ -0,0 +1,47 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_SETUID; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysSetUid; + +impl SysSetUid { + fn uid(args: &[usize]) -> usize { + args[0] + } +} + +impl Syscall for SysSetUid { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let uid = Self::uid(args); + let pcb = ProcessManager::current_pcb(); + let mut guard = pcb.cred.lock(); + + if guard.uid.data() == 0 { + guard.setuid(uid); + guard.seteuid(uid); + guard.setsuid(uid); + } else if uid == guard.uid.data() || uid == guard.suid.data() { + guard.seteuid(uid); + } else { + return Err(SystemError::EPERM); + } + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "uid", + format!("{:#x}", Self::uid(args)), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_SETUID, SysSetUid); diff --git a/kernel/src/process/syscall/sys_uname.rs b/kernel/src/process/syscall/sys_uname.rs new file mode 100644 index 00000000..5ed44fc9 --- /dev/null +++ b/kernel/src/process/syscall/sys_uname.rs @@ -0,0 +1,38 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_UNAME; +use crate::process::syscall::PosixOldUtsName; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use crate::syscall::user_access::UserBufferWriter; +use alloc::vec::Vec; +use system_error::SystemError; +pub struct SysUname; + +impl SysUname { + fn name(args: &[usize]) -> *mut PosixOldUtsName { + args[0] as *mut PosixOldUtsName + } +} + +impl Syscall for SysUname { + fn num_args(&self) -> usize { + 1 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let name = Self::name(args); + let mut writer = + UserBufferWriter::new(name, core::mem::size_of::(), true)?; + writer.copy_one_to_user(&PosixOldUtsName::new(), 0)?; + + return Ok(0); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new( + "name", + format!("{:#x}", Self::name(args) as usize), + )] + } +} + +syscall_table_macros::declare_syscall!(SYS_UNAME, SysUname); diff --git a/kernel/src/process/syscall/sys_vfork.rs b/kernel/src/process/syscall/sys_vfork.rs new file mode 100644 index 00000000..b7b1dd00 --- /dev/null +++ b/kernel/src/process/syscall/sys_vfork.rs @@ -0,0 +1,35 @@ +use crate::arch::interrupt::TrapFrame; +//use crate::arch::syscall::nr::SYS_VFORK; +use crate::process::fork::CloneFlags; +use crate::process::ProcessManager; +use crate::syscall::table::{FormattedSyscallParam, Syscall}; +use alloc::vec::Vec; +use system_error::SystemError; + +pub struct SysVfork; + +impl Syscall for SysVfork { + fn num_args(&self) -> usize { + 0 + } + + fn handle(&self, _args: &[usize], frame: &mut TrapFrame) -> Result { + // 由于Linux vfork需要保证子进程先运行(除非子进程调用execve或者exit), + // 而我们目前没有实现这个特性,所以暂时使用fork代替vfork(linux文档表示这样也是也可以的) + log::debug!("vfork"); + ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()) + + // 下面是以前的实现,除非我们实现了子进程先运行的特性,否则不要使用,不然会导致父进程数据损坏 + // ProcessManager::fork( + // frame, + // CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL, + // ) + // .map(|pid| pid.into()) + } + + fn entry_format(&self, _args: &[usize]) -> Vec { + vec![] + } +} + +//syscall_table_macros::declare_syscall!(SYS_VFORK, SysVfork); diff --git a/kernel/src/process/syscall/sys_wait4.rs b/kernel/src/process/syscall/sys_wait4.rs new file mode 100644 index 00000000..705910ea --- /dev/null +++ b/kernel/src/process/syscall/sys_wait4.rs @@ -0,0 +1,88 @@ +use crate::arch::interrupt::TrapFrame; +use crate::arch::syscall::nr::SYS_WAIT4; +use crate::process::abi::WaitOption; +use crate::process::exit::kernel_wait4; +use crate::process::resource::RUsage; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use crate::syscall::user_access::UserBufferWriter; +use alloc::vec::Vec; +use core::ffi::c_int; +use core::ffi::c_void; +use system_error::SystemError; + +pub struct SysWait4; + +impl SysWait4 { + fn pid(args: &[usize]) -> i32 { + args[0] as i32 + } + + fn wstatus(args: &[usize]) -> *mut i32 { + args[1] as *mut i32 + } + + fn options(args: &[usize]) -> c_int { + args[2] as c_int + } + + fn rusage(args: &[usize]) -> *mut c_void { + args[3] as *mut c_void + } +} + +impl Syscall for SysWait4 { + fn num_args(&self) -> usize { + 4 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let pid = Self::pid(args); + let wstatus = Self::wstatus(args); + let options = Self::options(args); + let rusage = Self::rusage(args); + // 权限校验 + // todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小 + + let options = WaitOption::from_bits(options as u32).ok_or(SystemError::EINVAL)?; + + let wstatus_buf = if wstatus.is_null() { + None + } else { + Some(UserBufferWriter::new( + wstatus, + core::mem::size_of::(), + true, + )?) + }; + + let mut tmp_rusage = if rusage.is_null() { + None + } else { + Some(RUsage::default()) + }; + + let r = kernel_wait4(pid, wstatus_buf, options, tmp_rusage.as_mut())?; + + if !rusage.is_null() { + let mut rusage_buf = UserBufferWriter::new::( + rusage as *mut RUsage, + core::mem::size_of::(), + true, + )?; + rusage_buf.copy_one_to_user(&tmp_rusage.unwrap(), 0)?; + } + return Ok(r); + } + + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("pid", format!("{:#x}", Self::pid(args))), + FormattedSyscallParam::new("wstatus", format!("{:#x}", Self::wstatus(args) as usize)), + FormattedSyscallParam::new("options", format!("{:#x}", Self::options(args))), + FormattedSyscallParam::new("rusage", format!("{:#x}", Self::rusage(args) as usize)), + ] + } +} + +syscall_table_macros::declare_syscall!(SYS_WAIT4, SysWait4); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 9ec8b3ee..d51fe6ed 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -1,5 +1,6 @@ +use crate::process::fork::CloneFlags; use core::{ - ffi::{c_int, c_void}, + ffi::c_int, sync::atomic::{AtomicBool, Ordering}, }; @@ -9,12 +10,7 @@ use crate::{ libs::{futex::constant::FutexFlag, rand::GRandFlags}, mm::{page::PAGE_4K_SIZE, syscall::MremapFlags}, net::syscall::MsgHdr, - process::{ - fork::KernelCloneArgs, - process_group::Pgid, - resource::{RLimit64, RUsage}, - ProcessFlags, ProcessManager, - }, + process::{ProcessFlags, ProcessManager}, sched::{schedule, SchedMode}, syscall::user_access::check_and_clone_cstr, }; @@ -29,12 +25,10 @@ use crate::{ filesystem::vfs::{ fcntl::{AtFlags, FcntlCommand}, syscall::{ModeType, UtimensFlags}, - MAX_PATHLEN, }, libs::align::page_align_up, mm::{verify_area, MemoryManagementArch, VirtAddr}, net::syscall::SockAddr, - process::{fork::CloneFlags, syscall::PosixOldUtsName, Pid}, time::{ syscall::{PosixTimeZone, PosixTimeval}, PosixTimeSpec, @@ -106,6 +100,7 @@ impl Syscall { // handler.name, // handler.args_string(args) // ); + return handler.inner_handle.handle(args, frame); } @@ -128,6 +123,11 @@ impl Syscall { ) } + #[cfg(target_arch = "x86_64")] + SYS_FORK => ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()), + #[cfg(target_arch = "x86_64")] + SYS_VFORK => ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into()), + #[cfg(target_arch = "x86_64")] SYS_RENAMEAT => { let oldfd = args[0] as i32; @@ -188,11 +188,6 @@ impl Syscall { Self::pwrite(fd, buf, len, offset) } - #[cfg(target_arch = "x86_64")] - SYS_FORK => Self::fork(frame), - #[cfg(target_arch = "x86_64")] - SYS_VFORK => Self::vfork(frame), - SYS_BRK => { let new_brk = VirtAddr::new(args[0]); Self::brk(new_brk).map(|vaddr| vaddr.data()) @@ -243,44 +238,6 @@ impl Syscall { res } - SYS_EXECVE => { - let path_ptr = args[0]; - let argv_ptr = args[1]; - let env_ptr = args[2]; - let virt_path_ptr = VirtAddr::new(path_ptr); - let virt_argv_ptr = VirtAddr::new(argv_ptr); - let virt_env_ptr = VirtAddr::new(env_ptr); - // 权限校验 - if frame.is_from_user() - && (verify_area(virt_path_ptr, MAX_PATHLEN).is_err() - || verify_area(virt_argv_ptr, PAGE_4K_SIZE).is_err()) - || verify_area(virt_env_ptr, PAGE_4K_SIZE).is_err() - { - Err(SystemError::EFAULT) - } else { - Self::execve( - path_ptr as *const u8, - argv_ptr as *const *const u8, - env_ptr as *const *const u8, - frame, - ) - .map(|_| 0) - } - } - SYS_WAIT4 => { - let pid = args[0] as i32; - let wstatus = args[1] as *mut i32; - let options = args[2] as c_int; - let rusage = args[3] as *mut c_void; - // 权限校验 - // todo: 引入rusage之后,更正以下权限校验代码中,rusage的大小 - Self::wait4(pid, wstatus, options, rusage) - } - - SYS_EXIT => { - let exit_code = args[0]; - Self::exit(exit_code) - } #[cfg(target_arch = "x86_64")] SYS_MKDIR => { let path = args[0] as *const u8; @@ -360,7 +317,6 @@ impl Syscall { let path = args[0] as *const u8; Self::unlink(path) } - SYS_GETPID => Self::getpid().map(|pid| pid.into()), SYS_SCHED => { warn!("syscall sched"); @@ -604,10 +560,6 @@ impl Syscall { } } - SYS_GETPGID => Self::getpgid(Pid::new(args[0])).map(|pgid| pgid.into()), - - SYS_GETPPID => Self::getppid().map(|pid| pid.into()), - SYS_FCNTL => { let fd = args[0] as i32; let cmd: Option = @@ -644,23 +596,6 @@ impl Syscall { ) } - SYS_CLONE => { - let parent_tid = VirtAddr::new(args[2]); - let child_tid = VirtAddr::new(args[3]); - - // 地址校验 - verify_area(parent_tid, core::mem::size_of::())?; - verify_area(child_tid, core::mem::size_of::())?; - - let mut clone_args = KernelCloneArgs::new(); - clone_args.flags = CloneFlags::from_bits_truncate(args[0] as u64); - clone_args.stack = args[1]; - clone_args.parent_tid = parent_tid; - clone_args.child_tid = child_tid; - clone_args.tls = args[4]; - Self::clone(frame, clone_args) - } - SYS_FUTEX => { let uaddr = VirtAddr::new(args[0]); let operation = FutexFlag::from_bits(args[1] as u32).ok_or(SystemError::ENOSYS)?; @@ -703,8 +638,6 @@ impl Syscall { return ret; } - SYS_SET_TID_ADDRESS => Self::set_tid_address(args[0]), - SYS_STATFS => { let path = args[0] as *const u8; let statfs = args[1] as *mut PosixStatfs; @@ -751,12 +684,6 @@ impl Syscall { SYS_PPOLL => Self::ppoll(args[0], args[1] as u32, args[2], args[3]), - SYS_SETPGID => { - let pid = Pid::new(args[0]); - let pgid = Pgid::new(args[1]); - Self::setpgid(pid, pgid) - } - SYS_TKILL => { warn!("SYS_TKILL has not yet been implemented"); Ok(0) @@ -767,13 +694,6 @@ impl Syscall { Ok(0) } - SYS_EXIT_GROUP => { - let exit_code = args[0]; - Self::exit(exit_code) - // warn!("SYS_EXIT_GROUP has not yet been implemented"); - // Ok(0) - } - SYS_MADVISE => { let addr = args[0]; let len = page_align_up(args[1]); @@ -784,8 +704,6 @@ impl Syscall { } } - SYS_GETTID => Self::gettid().map(|tid| tid.into()), - SYS_SYSLOG => { let syslog_action_type = args[0]; let buf_vaddr = args[1]; @@ -798,27 +716,6 @@ impl Syscall { Self::do_syslog(syslog_action_type, user_buf, len) } - SYS_GETUID => Self::getuid(), - SYS_GETGID => Self::getgid(), - SYS_SETUID => Self::setuid(args[0]), - SYS_SETGID => Self::setgid(args[0]), - - SYS_GETEUID => Self::geteuid(), - SYS_GETEGID => Self::getegid(), - SYS_SETRESUID => Self::seteuid(args[1]), - SYS_SETRESGID => Self::setegid(args[1]), - - SYS_SETFSUID => Self::setfsuid(args[0]), - SYS_SETFSGID => Self::setfsgid(args[0]), - - SYS_SETSID => Self::setsid(), - SYS_GETSID => Self::getsid(Pid::new(args[0])), - - SYS_GETRUSAGE => { - let who = args[0] as c_int; - let rusage = args[1] as *mut RUsage; - Self::get_rusage(who, rusage) - } #[cfg(target_arch = "x86_64")] SYS_READLINK => { let path = args[0] as *const u8; @@ -835,16 +732,6 @@ impl Syscall { Self::readlink_at(dirfd, path, buf, bufsiz) } - SYS_PRLIMIT64 => { - let pid = args[0]; - let pid = Pid::new(pid); - let resource = args[1]; - let new_limit = args[2] as *const RLimit64; - let old_limit = args[3] as *mut RLimit64; - - Self::prlimit64(pid, resource, new_limit, old_limit) - } - #[cfg(target_arch = "x86_64")] SYS_ACCESS => { let pathname = args[0] as *const u8; @@ -954,19 +841,6 @@ impl Syscall { Self::getaffinity(pid, set) } - #[cfg(target_arch = "x86_64")] - SYS_GETRLIMIT => { - let resource = args[0]; - let rlimit = args[1] as *mut RLimit64; - - Self::prlimit64( - ProcessManager::current_pcb().pid(), - resource, - core::ptr::null::(), - rlimit, - ) - } - SYS_FADVISE64 => { // todo: 这个系统调用还没有实现 @@ -993,10 +867,6 @@ impl Syscall { SYS_NEWFSTATAT => Self::newfstatat(args[0] as i32, args[1], args[2], args[3] as u32), // SYS_SCHED_YIELD => Self::sched_yield(), - SYS_UNAME => { - let name = args[0] as *mut PosixOldUtsName; - Self::uname(name) - } SYS_PRCTL => { // todo: 这个系统调用还没有实现