mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
refactor(process): 重构process下的系统调用 (#1184)
* refactor(process):迁移geteuid系统调用 * refactor(process):迁移getegid系统调用 * refactor(process):迁移getgid系统调用 * refactor(process):迁移getpgid系统调用 * refactor(process):迁移getpid系统调用 * refactor(process):迁移getppid系统调用 * refactor(process):迁移getsid系统调用 * refactor(process):迁移gettid系统调用 * refactor(process):迁移getuid系统调用 * refactor(process):迁移set_tid_address系统调用 * refactor(process):迁移setfsgid系统调用 * refactor(process):迁移setfsuid系统调用 * refactor(process):迁移setgid系统调用 * refactor(process):迁移setpgid系统调用 * refactor(process):迁移setresgid系统调用 * refactor(process):迁移setresuid系统调用 * refactor(process):迁移setsid系统调用 * refactor(process):迁移setuid系统调用 * refactor(process):删除部分已迁移的syscall(id相关)的原有部分 * refactor(process):make fmt * refactor(process):迁移sys_get_rusage系统调用 * refactor(process):迁移exit exit_group 系统调用 * refactor(process):删除重构syscall下的mod中的全架构条件编译 * refactor(process):迁移sys_wait4系统调用 * refactor(process):迁移sys_getrlimit sys_prlimit64 系统调用 * make fmt * refactor(process):迁移sys_uname系统调用 * fix(ipc):修复rebase时的错误冲突 * refactor(process):修改已迁移的系统调用的handle参数from_user-->frame * refactor(process):迁移execve系统调用 * refactor(process):迁移clone系统调用 * refactor(process):迁移fork、vfork系统调用 * refactor(process):删除原有syscall文件,将迁移后的文件夹重命名为syscall * refactor(process):修复条件编译错误
This commit is contained in:
parent
58e7943c13
commit
326cf3e0a3
@ -13,11 +13,10 @@ use crate::{
|
|||||||
namespaces::NsProxy,
|
namespaces::NsProxy,
|
||||||
net::net_core::net_init,
|
net::net_core::net_init,
|
||||||
process::{
|
process::{
|
||||||
exec::ProcInitInfo, kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags,
|
exec::ProcInitInfo, execve::do_execve, kthread::KernelThreadMechanism, stdio::stdio_init,
|
||||||
ProcessManager,
|
ProcessFlags, ProcessManager,
|
||||||
},
|
},
|
||||||
smp::smp_init,
|
smp::smp_init,
|
||||||
syscall::Syscall,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{cmdline::kenrel_cmdline_param_manager, initcall::do_initcalls};
|
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
|
ProcessManager::current_pcb().set_nsproxy(NsProxy::new()); // 初始化init进程的namespace
|
||||||
let path = proc_init_info.proc_name.to_str().unwrap();
|
let path = proc_init_info.proc_name.to_str().unwrap();
|
||||||
|
|
||||||
Syscall::do_execve(
|
do_execve(
|
||||||
path.to_string(),
|
path.to_string(),
|
||||||
proc_init_info.args.clone(),
|
proc_init_info.args.clone(),
|
||||||
proc_init_info.envs.clone(),
|
proc_init_info.envs.clone(),
|
||||||
|
@ -25,8 +25,8 @@ use crate::libs::rbtree::RBTree;
|
|||||||
use crate::libs::rwlock::RwLock;
|
use crate::libs::rwlock::RwLock;
|
||||||
use crate::libs::wait_queue::WaitQueue;
|
use crate::libs::wait_queue::WaitQueue;
|
||||||
use crate::process::fork::CloneFlags;
|
use crate::process::fork::CloneFlags;
|
||||||
|
use crate::process::geteuid::do_geteuid;
|
||||||
use crate::process::ProcessManager;
|
use crate::process::ProcessManager;
|
||||||
use crate::syscall::Syscall;
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MntNamespace {
|
pub struct MntNamespace {
|
||||||
@ -230,7 +230,7 @@ impl MntNamespace {
|
|||||||
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.ucounts
|
.ucounts
|
||||||
.inc_ucounts(user_ns, Syscall::geteuid()?, MntNamespaces))
|
.inc_ucounts(user_ns, do_geteuid()?, MntNamespaces))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dec_mnt_namespace(&self, uc: Arc<UCounts>) {
|
pub fn dec_mnt_namespace(&self, uc: Arc<UCounts>) {
|
||||||
|
@ -9,8 +9,8 @@ use crate::container_of;
|
|||||||
use crate::filesystem::vfs::{IndexNode, ROOT_INODE};
|
use crate::filesystem::vfs::{IndexNode, ROOT_INODE};
|
||||||
use crate::namespaces::namespace::NsOperations;
|
use crate::namespaces::namespace::NsOperations;
|
||||||
use crate::process::fork::CloneFlags;
|
use crate::process::fork::CloneFlags;
|
||||||
|
use crate::process::geteuid::do_geteuid;
|
||||||
use crate::process::ProcessManager;
|
use crate::process::ProcessManager;
|
||||||
use crate::syscall::Syscall;
|
|
||||||
use crate::{libs::rwlock::RwLock, process::Pid};
|
use crate::{libs::rwlock::RwLock, process::Pid};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
@ -264,7 +264,7 @@ impl PidNamespace {
|
|||||||
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.ucounts
|
.ucounts
|
||||||
.inc_ucounts(user_ns, Syscall::geteuid()?, PidNamespaces))
|
.inc_ucounts(user_ns, do_geteuid()?, PidNamespaces))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dec_pid_namespaces(&mut self, uc: Arc<UCounts>) {
|
pub fn dec_pid_namespaces(&mut self, uc: Arc<UCounts>) {
|
||||||
|
113
kernel/src/process/execve.rs
Normal file
113
kernel/src/process/execve.rs
Normal file
@ -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<CString>,
|
||||||
|
envp: Vec<CString>,
|
||||||
|
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<AddressSpace>`。
|
||||||
|
///
|
||||||
|
/// # 返回值
|
||||||
|
/// - 返回旧的用户地址空间的引用,类型为 `Option<Arc<AddressSpace>>`。
|
||||||
|
///
|
||||||
|
/// # 错误处理
|
||||||
|
/// 如果地址空间切换失败,函数会触发断言失败,并输出错误信息。
|
||||||
|
fn do_execve_switch_user_vm(new_vm: Arc<AddressSpace>) -> Option<Arc<AddressSpace>> {
|
||||||
|
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
|
||||||
|
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
|
||||||
|
}
|
8
kernel/src/process/geteuid.rs
Normal file
8
kernel/src/process/geteuid.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use system_error::SystemError;
|
||||||
|
|
||||||
|
use crate::process::ProcessManager;
|
||||||
|
|
||||||
|
pub fn do_geteuid() -> Result<usize, SystemError> {
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
return Ok(pcb.cred.lock().euid.data());
|
||||||
|
}
|
@ -76,8 +76,10 @@ use self::{cred::Cred, kthread::WorkerPrivate};
|
|||||||
pub mod abi;
|
pub mod abi;
|
||||||
pub mod cred;
|
pub mod cred;
|
||||||
pub mod exec;
|
pub mod exec;
|
||||||
|
pub mod execve;
|
||||||
pub mod exit;
|
pub mod exit;
|
||||||
pub mod fork;
|
pub mod fork;
|
||||||
|
pub mod geteuid;
|
||||||
pub mod idle;
|
pub mod idle;
|
||||||
pub mod kthread;
|
pub mod kthread;
|
||||||
pub mod pid;
|
pub mod pid;
|
||||||
|
@ -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<usize, SystemError> {
|
|
||||||
ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vfork(frame: &TrapFrame) -> Result<usize, SystemError> {
|
|
||||||
// 由于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<CString> = check_and_clone_cstr_array(argv)?;
|
|
||||||
let envp: Vec<CString> = 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<CString>,
|
|
||||||
envp: Vec<CString>,
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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::<i32>(),
|
|
||||||
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>(
|
|
||||||
rusage as *mut RUsage,
|
|
||||||
core::mem::size_of::<RUsage>(),
|
|
||||||
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<Pid, SystemError> {
|
|
||||||
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<Pgid, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<Pid, SystemError> {
|
|
||||||
let current_pcb = ProcessManager::current_pcb();
|
|
||||||
return Ok(current_pcb.basic().ppid());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clone(
|
|
||||||
current_trapframe: &TrapFrame,
|
|
||||||
clone_args: KernelCloneArgs,
|
|
||||||
) -> Result<usize, SystemError> {
|
|
||||||
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::<i32>(), core::mem::size_of::<i32>(), 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<usize, SystemError> {
|
|
||||||
verify_area(VirtAddr::new(ptr), core::mem::size_of::<i32>())
|
|
||||||
.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<Pid, SystemError> {
|
|
||||||
let pcb = ProcessManager::current_pcb();
|
|
||||||
Ok(pcb.pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getuid() -> Result<usize, SystemError> {
|
|
||||||
let pcb = ProcessManager::current_pcb();
|
|
||||||
return Ok(pcb.cred.lock().uid.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getgid() -> Result<usize, SystemError> {
|
|
||||||
let pcb = ProcessManager::current_pcb();
|
|
||||||
return Ok(pcb.cred.lock().gid.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn geteuid() -> Result<usize, SystemError> {
|
|
||||||
let pcb = ProcessManager::current_pcb();
|
|
||||||
return Ok(pcb.cred.lock().euid.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getegid() -> Result<usize, SystemError> {
|
|
||||||
let pcb = ProcessManager::current_pcb();
|
|
||||||
return Ok(pcb.cred.lock().egid.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setuid(uid: usize) -> Result<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
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<usize, SystemError> {
|
|
||||||
let who = RUsageWho::try_from(who)?;
|
|
||||||
let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::<RUsage>(), true)?;
|
|
||||||
let pcb = ProcessManager::current_pcb();
|
|
||||||
let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?;
|
|
||||||
|
|
||||||
let ubuf = writer.buffer::<RUsage>(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<usize, SystemError> {
|
|
||||||
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::<RLimit64>(),
|
|
||||||
true,
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
match resource {
|
|
||||||
RLimitID::Stack => {
|
|
||||||
if let Some(mut writer) = writer {
|
|
||||||
let mut rlimit = writer.buffer::<RLimit64>(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::<RLimit64>(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::<RLimit64>(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<usize, SystemError> {
|
|
||||||
let mut writer =
|
|
||||||
UserBufferWriter::new(name, core::mem::size_of::<PosixOldUtsName>(), true)?;
|
|
||||||
writer.copy_one_to_user(&PosixOldUtsName::new(), 0)?;
|
|
||||||
|
|
||||||
return Ok(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 切换用户虚拟内存空间
|
|
||||||
///
|
|
||||||
/// 该函数用于在执行系统调用 `execve` 时切换用户进程的虚拟内存空间。
|
|
||||||
///
|
|
||||||
/// # 参数
|
|
||||||
/// - `new_vm`: 新的用户地址空间,类型为 `Arc<AddressSpace>`。
|
|
||||||
///
|
|
||||||
/// # 返回值
|
|
||||||
/// - 返回旧的用户地址空间的引用,类型为 `Option<Arc<AddressSpace>>`。
|
|
||||||
///
|
|
||||||
/// # 错误处理
|
|
||||||
/// 如果地址空间切换失败,函数会触发断言失败,并输出错误信息。
|
|
||||||
fn do_execve_switch_user_vm(new_vm: Arc<AddressSpace>) -> Option<Arc<AddressSpace>> {
|
|
||||||
// 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
|
|
||||||
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
|
|
||||||
}
|
|
81
kernel/src/process/syscall/mod.rs
Normal file
81
kernel/src/process/syscall/mod.rs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
128
kernel/src/process/syscall/sys_clone.rs
Normal file
128
kernel/src/process/syscall/sys_clone.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let parent_tid = Self::parent_tid(args);
|
||||||
|
let child_tid = Self::child_tid(args);
|
||||||
|
|
||||||
|
// 地址校验
|
||||||
|
verify_area(parent_tid, core::mem::size_of::<i32>())?;
|
||||||
|
verify_area(child_tid, core::mem::size_of::<i32>())?;
|
||||||
|
|
||||||
|
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::<i32>(), core::mem::size_of::<i32>(), 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<FormattedSyscallParam> {
|
||||||
|
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);
|
98
kernel/src/process/syscall/sys_execve.rs
Normal file
98
kernel/src/process/syscall/sys_execve.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<CString> = check_and_clone_cstr_array(argv)?;
|
||||||
|
let envp: Vec<CString> = 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<FormattedSyscallParam> {
|
||||||
|
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);
|
34
kernel/src/process/syscall/sys_exit.rs
Normal file
34
kernel/src/process/syscall/sys_exit.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let exit_code = Self::exit_code(args);
|
||||||
|
ProcessManager::exit((exit_code & 0xff) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"exit_code",
|
||||||
|
format!("{:#x}", Self::exit_code(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_EXIT, SysExit);
|
34
kernel/src/process/syscall/sys_exit_group.rs
Normal file
34
kernel/src/process/syscall/sys_exit_group.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let exit_code = Self::exit_code(args);
|
||||||
|
ProcessManager::exit((exit_code & 0xff) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"exit_code",
|
||||||
|
format!("{:#x}", Self::exit_code(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_EXIT_GROUP, SysExitGroup);
|
26
kernel/src/process/syscall/sys_fork.rs
Normal file
26
kernel/src/process/syscall/sys_fork.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
log::debug!("fork");
|
||||||
|
ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//syscall_table_macros::declare_syscall!(SYS_FORK, SysFork);
|
52
kernel/src/process/syscall/sys_get_rusage.rs
Normal file
52
kernel/src/process/syscall/sys_get_rusage.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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::<RUsage>(), true)?;
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?;
|
||||||
|
|
||||||
|
let ubuf = writer.buffer::<RUsage>(0).unwrap();
|
||||||
|
ubuf.copy_from_slice(&[rusage]);
|
||||||
|
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
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);
|
26
kernel/src/process/syscall/sys_getegid.rs
Normal file
26
kernel/src/process/syscall/sys_getegid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
return Ok(pcb.cred.lock().egid.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETEGID, SysGetEgid);
|
25
kernel/src/process/syscall/sys_geteuid.rs
Normal file
25
kernel/src/process/syscall/sys_geteuid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
do_geteuid()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETEUID, SysGetEuid);
|
25
kernel/src/process/syscall/sys_getgid.rs
Normal file
25
kernel/src/process/syscall/sys_getgid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
return Ok(pcb.cred.lock().gid.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETGID, SysGetGid);
|
49
kernel/src/process/syscall/sys_getpgid.rs
Normal file
49
kernel/src/process/syscall/sys_getpgid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"pid",
|
||||||
|
format!("{:#x}", Self::pid(args).0),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETPGID, SysGetPgid);
|
33
kernel/src/process/syscall/sys_getpid.rs
Normal file
33
kernel/src/process/syscall/sys_getpid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETPID, SysGetPid);
|
27
kernel/src/process/syscall/sys_getppid.rs
Normal file
27
kernel/src/process/syscall/sys_getppid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let current_pcb = ProcessManager::current_pcb();
|
||||||
|
return Ok(current_pcb.basic().ppid().into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETPPID, SysGetPpid);
|
50
kernel/src/process/syscall/sys_getrlimit.rs
Normal file
50
kernel/src/process/syscall/sys_getrlimit.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let resource = Self::resource(args);
|
||||||
|
let rlimit = Self::rlimit(args);
|
||||||
|
|
||||||
|
do_prlimit64(
|
||||||
|
ProcessManager::current_pcb().pid(),
|
||||||
|
resource,
|
||||||
|
core::ptr::null::<RLimit64>(),
|
||||||
|
rlimit,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
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);
|
54
kernel/src/process/syscall/sys_getsid.rs
Normal file
54
kernel/src/process/syscall/sys_getsid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"pid",
|
||||||
|
format!("{:#x}", Self::pid(args).0),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETSID, SysGetsid);
|
25
kernel/src/process/syscall/sys_gettid.rs
Normal file
25
kernel/src/process/syscall/sys_gettid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
return Ok(pcb.pid.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETTID, SysGetTid);
|
26
kernel/src/process/syscall/sys_getuid.rs
Normal file
26
kernel/src/process/syscall/sys_getuid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
return Ok(pcb.cred.lock().uid.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, _args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_GETUID, SysGetUid);
|
135
kernel/src/process/syscall/sys_prlimit64.rs
Normal file
135
kernel/src/process/syscall/sys_prlimit64.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
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<usize, SystemError> {
|
||||||
|
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::<RLimit64>(),
|
||||||
|
true,
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
match resource {
|
||||||
|
RLimitID::Stack => {
|
||||||
|
if let Some(mut writer) = writer {
|
||||||
|
let mut rlimit = writer.buffer::<RLimit64>(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::<RLimit64>(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::<RLimit64>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
kernel/src/process/syscall/sys_set_tid_address.rs
Normal file
43
kernel/src/process/syscall/sys_set_tid_address.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let ptr = Self::ptr(args);
|
||||||
|
verify_area(VirtAddr::new(ptr), core::mem::size_of::<i32>())
|
||||||
|
.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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"ptr",
|
||||||
|
format!("{:#x}", Self::ptr(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SET_TID_ADDRESS, SysSetTidAddress);
|
46
kernel/src/process/syscall/sys_setfsgid.rs
Normal file
46
kernel/src/process/syscall/sys_setfsgid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"fsgid",
|
||||||
|
format!("{:#x}", Self::fsgid(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETFSGID, SysSetFsgid);
|
45
kernel/src/process/syscall/sys_setfsuid.rs
Normal file
45
kernel/src/process/syscall/sys_setfsuid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"fsuid",
|
||||||
|
format!("{:#x}", Self::fsuid(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETFSUID, SysSetFsuid);
|
50
kernel/src/process/syscall/sys_setgid.rs
Normal file
50
kernel/src/process/syscall/sys_setgid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"gid",
|
||||||
|
format!("{:#x}", Self::gid(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETGID, SysSetGid);
|
69
kernel/src/process/syscall/sys_setpgid.rs
Normal file
69
kernel/src/process/syscall/sys_setpgid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
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);
|
48
kernel/src/process/syscall/sys_setresgid.rs
Normal file
48
kernel/src/process/syscall/sys_setresgid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"egid",
|
||||||
|
format!("{:#x}", Self::egid(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETRESGID, SysSetResGid);
|
48
kernel/src/process/syscall/sys_setresuid.rs
Normal file
48
kernel/src/process/syscall/sys_setresuid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"euid",
|
||||||
|
format!("{:#x}", Self::euid(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETRESUID, SysSetResUid);
|
30
kernel/src/process/syscall/sys_setsid.rs
Normal file
30
kernel/src/process/syscall/sys_setsid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETSID, SysSetsid);
|
47
kernel/src/process/syscall/sys_setuid.rs
Normal file
47
kernel/src/process/syscall/sys_setuid.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"uid",
|
||||||
|
format!("{:#x}", Self::uid(args)),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_SETUID, SysSetUid);
|
38
kernel/src/process/syscall/sys_uname.rs
Normal file
38
kernel/src/process/syscall/sys_uname.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
let name = Self::name(args);
|
||||||
|
let mut writer =
|
||||||
|
UserBufferWriter::new(name, core::mem::size_of::<PosixOldUtsName>(), true)?;
|
||||||
|
writer.copy_one_to_user(&PosixOldUtsName::new(), 0)?;
|
||||||
|
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
vec![FormattedSyscallParam::new(
|
||||||
|
"name",
|
||||||
|
format!("{:#x}", Self::name(args) as usize),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_table_macros::declare_syscall!(SYS_UNAME, SysUname);
|
35
kernel/src/process/syscall/sys_vfork.rs
Normal file
35
kernel/src/process/syscall/sys_vfork.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
// 由于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<FormattedSyscallParam> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//syscall_table_macros::declare_syscall!(SYS_VFORK, SysVfork);
|
88
kernel/src/process/syscall/sys_wait4.rs
Normal file
88
kernel/src/process/syscall/sys_wait4.rs
Normal file
@ -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<usize, SystemError> {
|
||||||
|
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::<i32>(),
|
||||||
|
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>(
|
||||||
|
rusage as *mut RUsage,
|
||||||
|
core::mem::size_of::<RUsage>(),
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
rusage_buf.copy_one_to_user(&tmp_rusage.unwrap(), 0)?;
|
||||||
|
}
|
||||||
|
return Ok(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||||
|
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);
|
@ -1,5 +1,6 @@
|
|||||||
|
use crate::process::fork::CloneFlags;
|
||||||
use core::{
|
use core::{
|
||||||
ffi::{c_int, c_void},
|
ffi::c_int,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -9,12 +10,7 @@ use crate::{
|
|||||||
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
||||||
mm::{page::PAGE_4K_SIZE, syscall::MremapFlags},
|
mm::{page::PAGE_4K_SIZE, syscall::MremapFlags},
|
||||||
net::syscall::MsgHdr,
|
net::syscall::MsgHdr,
|
||||||
process::{
|
process::{ProcessFlags, ProcessManager},
|
||||||
fork::KernelCloneArgs,
|
|
||||||
process_group::Pgid,
|
|
||||||
resource::{RLimit64, RUsage},
|
|
||||||
ProcessFlags, ProcessManager,
|
|
||||||
},
|
|
||||||
sched::{schedule, SchedMode},
|
sched::{schedule, SchedMode},
|
||||||
syscall::user_access::check_and_clone_cstr,
|
syscall::user_access::check_and_clone_cstr,
|
||||||
};
|
};
|
||||||
@ -29,12 +25,10 @@ use crate::{
|
|||||||
filesystem::vfs::{
|
filesystem::vfs::{
|
||||||
fcntl::{AtFlags, FcntlCommand},
|
fcntl::{AtFlags, FcntlCommand},
|
||||||
syscall::{ModeType, UtimensFlags},
|
syscall::{ModeType, UtimensFlags},
|
||||||
MAX_PATHLEN,
|
|
||||||
},
|
},
|
||||||
libs::align::page_align_up,
|
libs::align::page_align_up,
|
||||||
mm::{verify_area, MemoryManagementArch, VirtAddr},
|
mm::{verify_area, MemoryManagementArch, VirtAddr},
|
||||||
net::syscall::SockAddr,
|
net::syscall::SockAddr,
|
||||||
process::{fork::CloneFlags, syscall::PosixOldUtsName, Pid},
|
|
||||||
time::{
|
time::{
|
||||||
syscall::{PosixTimeZone, PosixTimeval},
|
syscall::{PosixTimeZone, PosixTimeval},
|
||||||
PosixTimeSpec,
|
PosixTimeSpec,
|
||||||
@ -106,6 +100,7 @@ impl Syscall {
|
|||||||
// handler.name,
|
// handler.name,
|
||||||
// handler.args_string(args)
|
// handler.args_string(args)
|
||||||
// );
|
// );
|
||||||
|
|
||||||
return handler.inner_handle.handle(args, frame);
|
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")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
SYS_RENAMEAT => {
|
SYS_RENAMEAT => {
|
||||||
let oldfd = args[0] as i32;
|
let oldfd = args[0] as i32;
|
||||||
@ -188,11 +188,6 @@ impl Syscall {
|
|||||||
Self::pwrite(fd, buf, len, offset)
|
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 => {
|
SYS_BRK => {
|
||||||
let new_brk = VirtAddr::new(args[0]);
|
let new_brk = VirtAddr::new(args[0]);
|
||||||
Self::brk(new_brk).map(|vaddr| vaddr.data())
|
Self::brk(new_brk).map(|vaddr| vaddr.data())
|
||||||
@ -243,44 +238,6 @@ impl Syscall {
|
|||||||
res
|
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")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
SYS_MKDIR => {
|
SYS_MKDIR => {
|
||||||
let path = args[0] as *const u8;
|
let path = args[0] as *const u8;
|
||||||
@ -360,7 +317,6 @@ impl Syscall {
|
|||||||
let path = args[0] as *const u8;
|
let path = args[0] as *const u8;
|
||||||
Self::unlink(path)
|
Self::unlink(path)
|
||||||
}
|
}
|
||||||
SYS_GETPID => Self::getpid().map(|pid| pid.into()),
|
|
||||||
|
|
||||||
SYS_SCHED => {
|
SYS_SCHED => {
|
||||||
warn!("syscall 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 => {
|
SYS_FCNTL => {
|
||||||
let fd = args[0] as i32;
|
let fd = args[0] as i32;
|
||||||
let cmd: Option<FcntlCommand> =
|
let cmd: Option<FcntlCommand> =
|
||||||
@ -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::<i32>())?;
|
|
||||||
verify_area(child_tid, core::mem::size_of::<i32>())?;
|
|
||||||
|
|
||||||
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 => {
|
SYS_FUTEX => {
|
||||||
let uaddr = VirtAddr::new(args[0]);
|
let uaddr = VirtAddr::new(args[0]);
|
||||||
let operation = FutexFlag::from_bits(args[1] as u32).ok_or(SystemError::ENOSYS)?;
|
let operation = FutexFlag::from_bits(args[1] as u32).ok_or(SystemError::ENOSYS)?;
|
||||||
@ -703,8 +638,6 @@ impl Syscall {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_SET_TID_ADDRESS => Self::set_tid_address(args[0]),
|
|
||||||
|
|
||||||
SYS_STATFS => {
|
SYS_STATFS => {
|
||||||
let path = args[0] as *const u8;
|
let path = args[0] as *const u8;
|
||||||
let statfs = args[1] as *mut PosixStatfs;
|
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_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 => {
|
SYS_TKILL => {
|
||||||
warn!("SYS_TKILL has not yet been implemented");
|
warn!("SYS_TKILL has not yet been implemented");
|
||||||
Ok(0)
|
Ok(0)
|
||||||
@ -767,13 +694,6 @@ impl Syscall {
|
|||||||
Ok(0)
|
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 => {
|
SYS_MADVISE => {
|
||||||
let addr = args[0];
|
let addr = args[0];
|
||||||
let len = page_align_up(args[1]);
|
let len = page_align_up(args[1]);
|
||||||
@ -784,8 +704,6 @@ impl Syscall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_GETTID => Self::gettid().map(|tid| tid.into()),
|
|
||||||
|
|
||||||
SYS_SYSLOG => {
|
SYS_SYSLOG => {
|
||||||
let syslog_action_type = args[0];
|
let syslog_action_type = args[0];
|
||||||
let buf_vaddr = args[1];
|
let buf_vaddr = args[1];
|
||||||
@ -798,27 +716,6 @@ impl Syscall {
|
|||||||
Self::do_syslog(syslog_action_type, user_buf, len)
|
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")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
SYS_READLINK => {
|
SYS_READLINK => {
|
||||||
let path = args[0] as *const u8;
|
let path = args[0] as *const u8;
|
||||||
@ -835,16 +732,6 @@ impl Syscall {
|
|||||||
Self::readlink_at(dirfd, path, buf, bufsiz)
|
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")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
SYS_ACCESS => {
|
SYS_ACCESS => {
|
||||||
let pathname = args[0] as *const u8;
|
let pathname = args[0] as *const u8;
|
||||||
@ -954,19 +841,6 @@ impl Syscall {
|
|||||||
Self::getaffinity(pid, set)
|
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::<RLimit64>(),
|
|
||||||
rlimit,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_FADVISE64 => {
|
SYS_FADVISE64 => {
|
||||||
// todo: 这个系统调用还没有实现
|
// todo: 这个系统调用还没有实现
|
||||||
|
|
||||||
@ -993,10 +867,6 @@ impl Syscall {
|
|||||||
SYS_NEWFSTATAT => Self::newfstatat(args[0] as i32, args[1], args[2], args[3] as u32),
|
SYS_NEWFSTATAT => Self::newfstatat(args[0] as i32, args[1], args[2], args[3] as u32),
|
||||||
|
|
||||||
// SYS_SCHED_YIELD => Self::sched_yield(),
|
// SYS_SCHED_YIELD => Self::sched_yield(),
|
||||||
SYS_UNAME => {
|
|
||||||
let name = args[0] as *mut PosixOldUtsName;
|
|
||||||
Self::uname(name)
|
|
||||||
}
|
|
||||||
SYS_PRCTL => {
|
SYS_PRCTL => {
|
||||||
// todo: 这个系统调用还没有实现
|
// todo: 这个系统调用还没有实现
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user