Browse Source

添加prlimit64系统调用 (#438)

注意: 目前仅支持读取默认的rlimit值,尚不支持设置rlimit值.
LoGin 1 year ago
parent
commit
0d9b7d9240

+ 3 - 1
kernel/src/arch/x86_64/syscall.rs

@@ -13,6 +13,8 @@ use alloc::string::String;
 
 use super::{interrupt::TrapFrame, mm::barrier::mfence};
 
+pub const SYS_PRLIMIT64: usize = 302;
+
 /// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体
 ///
 /// 在syscall指令中将会从该结构体中读取系统调用栈和暂存rsp,
@@ -65,7 +67,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) -> () {
     ];
     mfence();
 
-    // 由于进程管理未完成重构,有些系统调用需要在这里临时处理,以后这里的特殊处理要删掉。
+    // Arch specific syscall
     match syscall_num {
         SYS_RT_SIGRETURN => {
             syscall_return!(X86_64SignalArch::sys_rt_sigreturn(frame) as usize, frame);

+ 1 - 1
kernel/src/filesystem/vfs/file.rs

@@ -417,7 +417,7 @@ pub struct FileDescriptorVec {
 }
 
 impl FileDescriptorVec {
-    pub const PROCESS_MAX_FD: usize = 32;
+    pub const PROCESS_MAX_FD: usize = 1024;
 
     pub fn new() -> FileDescriptorVec {
         // 先声明一个未初始化的数组

+ 65 - 0
kernel/src/process/resource.rs

@@ -1,3 +1,5 @@
+use num_traits::FromPrimitive;
+
 use crate::{syscall::SystemError, time::TimeSpec};
 
 use super::ProcessControlBlock;
@@ -71,6 +73,69 @@ impl TryFrom<i32> for RUsageWho {
     }
 }
 
+/// Resource limit
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(C)]
+pub struct RLimit64 {
+    /// The current (soft) limit
+    pub rlim_cur: u64,
+    /// The hard limit
+    pub rlim_max: u64,
+}
+
+/// Resource limit IDs
+///
+/// ## Note
+///
+/// 有些架构中,这里[5,9]的值是不同的,我们将来需要在这里增加条件编译
+#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive)]
+pub enum RLimitID {
+    /// CPU time in sec
+    Cpu = 0,
+    /// Maximum file size
+    Fsize = 1,
+    /// Max data size
+    Data = 2,
+    /// Max stack size
+    Stack = 3,
+    /// Max core file size
+    Core = 4,
+    /// Max resident set size
+    Rss = 5,
+
+    /// Max number of processes
+    Nproc = 6,
+    /// Max number of open files
+    Nofile = 7,
+    /// Max locked-in-memory address space
+    Memlock = 8,
+    /// Address space limit
+    As = 9,
+    /// Max number of file locks held
+    Locks = 10,
+
+    /// Max number of pending signals
+    Sigpending = 11,
+    /// Max bytes in POSIX mqueues
+    Msgqueue = 12,
+    /// Max nice prio allowed to raise to
+    ///  0-39 for nice level 19 .. -20
+    Nice = 13,
+    /// Max realtime priority
+    Rtprio = 14,
+    /// Timeout for RT tasks in us
+    Rttime = 15,
+    Nlimits = 16,
+}
+
+impl TryFrom<usize> for RLimitID {
+    type Error = SystemError;
+
+    fn try_from(value: usize) -> Result<Self, Self::Error> {
+        <Self as FromPrimitive>::from_usize(value).ok_or(SystemError::EINVAL)
+    }
+}
+
 impl ProcessControlBlock {
     /// 获取进程资源使用情况
     ///

+ 80 - 4
kernel/src/process/syscall.rs

@@ -9,15 +9,18 @@ use alloc::{
 use super::{
     abi::WaitOption,
     fork::{CloneFlags, KernelCloneArgs},
-    resource::{RUsage, RUsageWho},
+    resource::{RLimit64, RLimitID, RUsage, RUsageWho},
     KernelStack, Pid, ProcessManager, ProcessState,
 };
 use crate::{
-    arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch},
+    arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch, MMArch},
     exception::InterruptArch,
-    filesystem::{procfs::procfs_register_pid, vfs::MAX_PATHLEN},
+    filesystem::{
+        procfs::procfs_register_pid,
+        vfs::{file::FileDescriptorVec, MAX_PATHLEN},
+    },
     include::bindings::bindings::verify_area,
-    mm::VirtAddr,
+    mm::{ucontext::UserStack, MemoryManagementArch, VirtAddr},
     process::ProcessControlBlock,
     sched::completion::Completion,
     syscall::{
@@ -333,4 +336,77 @@ impl Syscall {
 
         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 new_limit.is_null() {
+            return Err(SystemError::EINVAL);
+        }
+
+        if !old_limit.is_null() {
+            writer = Some(UserBufferWriter::new(
+                old_limit,
+                core::mem::size_of::<RLimit64>(),
+                true,
+            )?);
+        }
+
+        let _reader = UserBufferReader::new(new_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);
+            }
+        }
+    }
 }

+ 15 - 1
kernel/src/syscall/mod.rs

@@ -4,8 +4,12 @@ use core::{
 };
 
 use crate::{
+    arch::syscall::SYS_PRLIMIT64,
     libs::{futex::constant::FutexFlag, rand::GRandFlags},
-    process::{fork::KernelCloneArgs, resource::RUsage},
+    process::{
+        fork::KernelCloneArgs,
+        resource::{RLimit64, RUsage},
+    },
 };
 
 use num_traits::{FromPrimitive, ToPrimitive};
@@ -1190,6 +1194,16 @@ impl Syscall {
                 Self::readlink_at(dirfd, pathname, 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)
+            }
+
             _ => panic!("Unsupported syscall ID: {}", syscall_num),
         };
         return r;

+ 1 - 1
user/apps/shell/cmd.c

@@ -521,7 +521,7 @@ int shell_cmd_exec(int argc, char **argv)
         char *file_path = get_target_filepath(argv[1], &path_len);
         // printf("before execv, path=%s, argc=%d\n", file_path, argc);
 
-        char **real_argv;
+        char **real_argv = NULL;
         if (argc > 1)
         {
             real_argv = &argv[1];