diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index c7e3caa1..79271aa4 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -11,7 +11,7 @@ mod process_filter; pub mod process_table; mod process_vm; mod program_loader; -mod rlimit; +pub mod rlimit; pub mod signal; mod status; pub mod sync; diff --git a/kernel/src/process/rlimit.rs b/kernel/src/process/rlimit.rs index cc848713..978d7a08 100644 --- a/kernel/src/process/rlimit.rs +++ b/kernel/src/process/rlimit.rs @@ -1,19 +1,37 @@ // SPDX-License-Identifier: MPL-2.0 +// FIXME: The resource limits should be respected by the corresponding subsystems of the kernel. #![allow(non_camel_case_types)] use super::process_vm::{INIT_STACK_SIZE, USER_HEAP_SIZE_LIMIT}; use crate::prelude::*; +// Constants for the boot-time rlimit defaults +// See https://github.com/torvalds/linux/blob/fac04efc5c793dccbd07e2d59af9f90b7fc0dca4/include/asm-generic/resource.h#L11 +const RLIM_INFINITY: u64 = u64::MAX; +const INIT_RLIMIT_NPROC: u64 = 0; +const INIT_RLIMIT_NICE: u64 = 0; +const INIT_RLIMIT_SIGPENDING: u64 = 0; +const INIT_RLIMIT_RTPRIO: u64 = 0; +// https://github.com/torvalds/linux/blob/fac04efc5c793dccbd07e2d59af9f90b7fc0dca4/include/uapi/linux/fs.h#L37 +const INIT_RLIMIT_NOFILE_CUR: u64 = 1024; +const INIT_RLIMIT_NOFILE_MAX: u64 = 4096; +// https://github.com/torvalds/linux/blob/fac04efc5c793dccbd07e2d59af9f90b7fc0dca4/include/uapi/linux/resource.h#L79 +const INIT_RLIMIT_MEMLOCK: u64 = 8 * 1024 * 1024; +// https://github.com/torvalds/linux/blob/fac04efc5c793dccbd07e2d59af9f90b7fc0dca4/include/uapi/linux/mqueue.h#L26 +const INIT_RLIMIT_MSGQUEUE: u64 = 819200; + pub struct ResourceLimits { rlimits: [RLimit64; RLIMIT_COUNT], } impl ResourceLimits { + // Get a reference to a specific resource limit pub fn get_rlimit(&self, resource: ResourceType) -> &RLimit64 { &self.rlimits[resource as usize] } + // Get a mutable reference to a specific resource limit pub fn get_rlimit_mut(&mut self, resource: ResourceType) -> &mut RLimit64 { &mut self.rlimits[resource as usize] } @@ -21,17 +39,36 @@ impl ResourceLimits { impl Default for ResourceLimits { fn default() -> Self { - let stack_size = RLimit64::new(INIT_STACK_SIZE as u64); - let heap_size = RLimit64::new(USER_HEAP_SIZE_LIMIT as u64); - let open_files = RLimit64::new(1024); + let mut rlimits = [RLimit64::default(); RLIMIT_COUNT]; - let mut rlimits = Self { - rlimits: [RLimit64::default(); RLIMIT_COUNT], - }; - *rlimits.get_rlimit_mut(ResourceType::RLIMIT_STACK) = stack_size; - *rlimits.get_rlimit_mut(ResourceType::RLIMIT_DATA) = heap_size; - *rlimits.get_rlimit_mut(ResourceType::RLIMIT_NOFILE) = open_files; - rlimits + // Setting the resource limits with predefined values + rlimits[ResourceType::RLIMIT_CPU as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_FSIZE as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_DATA as usize] = + RLimit64::new(USER_HEAP_SIZE_LIMIT as u64, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_STACK as usize] = + RLimit64::new(INIT_STACK_SIZE as u64, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_CORE as usize] = RLimit64::new(0, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_RSS as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_NPROC as usize] = + RLimit64::new(INIT_RLIMIT_NPROC, INIT_RLIMIT_NPROC); + rlimits[ResourceType::RLIMIT_NOFILE as usize] = + RLimit64::new(INIT_RLIMIT_NOFILE_CUR, INIT_RLIMIT_NOFILE_MAX); + rlimits[ResourceType::RLIMIT_MEMLOCK as usize] = + RLimit64::new(INIT_RLIMIT_MEMLOCK, INIT_RLIMIT_MEMLOCK); + rlimits[ResourceType::RLIMIT_AS as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_LOCKS as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY); + rlimits[ResourceType::RLIMIT_SIGPENDING as usize] = + RLimit64::new(INIT_RLIMIT_SIGPENDING, INIT_RLIMIT_SIGPENDING); + rlimits[ResourceType::RLIMIT_MSGQUEUE as usize] = + RLimit64::new(INIT_RLIMIT_MSGQUEUE, INIT_RLIMIT_MSGQUEUE); + rlimits[ResourceType::RLIMIT_NICE as usize] = + RLimit64::new(INIT_RLIMIT_NICE, INIT_RLIMIT_NICE); + rlimits[ResourceType::RLIMIT_RTPRIO as usize] = + RLimit64::new(INIT_RLIMIT_RTPRIO, INIT_RLIMIT_RTPRIO); + rlimits[ResourceType::RLIMIT_RTTIME as usize] = RLimit64::new(RLIM_INFINITY, RLIM_INFINITY); + + ResourceLimits { rlimits } } } @@ -66,8 +103,8 @@ pub struct RLimit64 { } impl RLimit64 { - pub fn new(cur: u64) -> Self { - Self { cur, max: u64::MAX } + pub fn new(cur: u64, max: u64) -> Self { + Self { cur, max } } pub fn get_cur(&self) -> u64 { @@ -77,13 +114,17 @@ impl RLimit64 { pub fn get_max(&self) -> u64 { self.max } + + pub fn is_valid(&self) -> bool { + self.cur <= self.max + } } impl Default for RLimit64 { fn default() -> Self { Self { - cur: u64::MAX, - max: u64::MAX, + cur: RLIM_INFINITY, + max: RLIM_INFINITY, } } } diff --git a/kernel/src/syscall/prlimit64.rs b/kernel/src/syscall/prlimit64.rs index 3df2fb58..51ca0038 100644 --- a/kernel/src/syscall/prlimit64.rs +++ b/kernel/src/syscall/prlimit64.rs @@ -3,7 +3,7 @@ use super::SyscallReturn; use crate::{ prelude::*, - process::{Pid, ResourceType}, + process::{rlimit::RLimit64, Pid, ResourceType}, }; pub fn sys_getrlimit(resource: u32, rlim_addr: Vaddr, ctx: &Context) -> Result { @@ -21,7 +21,10 @@ pub fn sys_setrlimit(resource: u32, new_rlim_addr: Vaddr, ctx: &Context) -> Resu "resource = {:?}, new_rlim_addr = 0x{:x}", resource, new_rlim_addr ); - let new_rlimit = ctx.user_space().read_val(new_rlim_addr)?; + let new_rlimit: RLimit64 = ctx.user_space().read_val(new_rlim_addr)?; + if !new_rlimit.is_valid() { + return_errno_with_message!(Errno::EINVAL, "invalid rlimit"); + } let mut resource_limits = ctx.process.resource_limits().lock(); *resource_limits.get_rlimit_mut(resource) = new_rlimit; Ok(SyscallReturn::Return(0)) @@ -45,7 +48,11 @@ pub fn sys_prlimit64( ctx.user_space().write_val(old_rlim_addr, rlimit)?; } if new_rlim_addr != 0 { - let new_rlimit = ctx.user_space().read_val(new_rlim_addr)?; + let new_rlimit: RLimit64 = ctx.user_space().read_val(new_rlim_addr)?; + debug!("new_rlimit = {:?}", new_rlimit); + if !new_rlimit.is_valid() { + return_errno_with_message!(Errno::EINVAL, "invalid rlimit"); + } *resource_limits.get_rlimit_mut(resource) = new_rlimit; } Ok(SyscallReturn::Return(0))