Add prlimit64, getrlimit, and setrlimit

This commit is contained in:
Tate, Hongliang Tian 2019-04-09 20:39:50 +08:00 committed by Tate Tian
parent 8846c62b5e
commit b003f4ce43
11 changed files with 190 additions and 9 deletions

@ -1,5 +1,7 @@
use super::*; use super::*;
mod uname; mod uname;
mod rlimit;
pub use self::uname::{utsname_t, do_uname}; pub use self::uname::{utsname_t, do_uname};
pub use self::rlimit::{rlimit_t, resource_t, ResourceLimits, ResourceLimitsRef, do_prlimit};

@ -0,0 +1,123 @@
use super::*;
use process::{pid_t};
#[derive(Debug, Copy, Clone)]
pub struct ResourceLimits {
rlimits: [rlimit_t; RLIMIT_COUNT],
}
pub type ResourceLimitsRef = Arc<SgxMutex<ResourceLimits>>;
impl ResourceLimits {
pub fn get(&self, resource: resource_t) -> &rlimit_t {
&self.rlimits[resource as usize]
}
pub fn get_mut(&mut self, resource: resource_t) -> &mut rlimit_t {
&mut self.rlimits[resource as usize]
}
}
impl Default for ResourceLimits {
fn default() -> ResourceLimits {
// TODO: set appropriate limits for resources
let mut rlimits = ResourceLimits {
rlimits: [ Default::default(); RLIMIT_COUNT ],
};
rlimits
}
}
#[derive(Debug, Copy, Clone)]
#[allow(non_camel_case_types)]
pub struct rlimit_t {
cur: u64,
max: u64,
}
impl Default for rlimit_t {
fn default() -> rlimit_t {
rlimit_t {
cur: u64::max_value(),
max: u64::max_value(),
}
}
}
#[derive(Debug, Copy, Clone)]
#[allow(non_camel_case_types)]
pub enum resource_t {
RLIMIT_CPU = 0,
RLIMIT_FSIZE = 1,
RLIMIT_DATA = 2,
RLIMIT_STACK = 3,
RLIMIT_CORE = 4,
RLIMIT_RSS = 5,
RLIMIT_NPROC = 6,
RLIMIT_NOFILE = 7,
RLIMIT_MEMLOCK = 8,
RLIMIT_AS = 9,
RLIMIT_LOCKS = 10,
RLIMIT_SIGPENDING = 11,
RLIMIT_MSGQUEUE = 12,
RLIMIT_NICE = 13,
RLIMIT_RTPRIO = 14,
}
const RLIMIT_COUNT: usize = 15;
impl resource_t {
pub fn from_u32(bits: u32) -> Result<resource_t, Error> {
match bits {
0 => Ok(resource_t::RLIMIT_CPU),
1 => Ok(resource_t::RLIMIT_FSIZE),
2 => Ok(resource_t::RLIMIT_DATA),
3 => Ok(resource_t::RLIMIT_STACK),
4 => Ok(resource_t::RLIMIT_CORE),
5 => Ok(resource_t::RLIMIT_RSS),
6 => Ok(resource_t::RLIMIT_NPROC),
7 => Ok(resource_t::RLIMIT_NOFILE),
8 => Ok(resource_t::RLIMIT_MEMLOCK),
9 => Ok(resource_t::RLIMIT_AS),
10 => Ok(resource_t::RLIMIT_LOCKS),
11 => Ok(resource_t::RLIMIT_SIGPENDING),
12 => Ok(resource_t::RLIMIT_MSGQUEUE),
13 => Ok(resource_t::RLIMIT_NICE),
14 => Ok(resource_t::RLIMIT_RTPRIO),
_ => errno!(EINVAL, "invalid resource"),
}
}
}
pub fn do_prlimit(
pid: pid_t,
resource: resource_t,
new_limit: Option<&rlimit_t>,
old_limit: Option<&mut rlimit_t>,
) -> Result<(), Error> {
let process_ref = if pid == 0 {
process::get_current()
}
else {
process::get(pid)?
};
let mut process = process_ref.lock().unwrap();
let rlimits_ref = process.get_rlimits();
let mut rlimits = rlimits_ref.lock().unwrap();
if let Some(old_limit) = old_limit {
*old_limit = *rlimits.get(resource)
}
if let Some(new_limit) = new_limit {
*rlimits.get_mut(resource) = *new_limit;
}
Ok(())
}
pub fn do_getrlimit(resource: resource_t, old_limit: &mut rlimit_t) -> Result<(), Error> {
do_prlimit(0 as pid_t, resource, None, Some(old_limit))
}
pub fn do_setrlimit(resource: resource_t, new_limit: &rlimit_t) -> Result<(), Error> {
do_prlimit(0 as pid_t, resource, Some(new_limit), None)
}

@ -1,8 +1,6 @@
pub use self::process::{Status, IDLE_PROCESS}; pub use self::process::{Status, IDLE_PROCESS};
pub use self::task::{get_current, run_task}; pub use self::task::{get_current, run_task};
pub mod table { pub use self::process_table::{get};
pub use super::process_table::get;
}
pub use self::exit::{do_exit, do_wait4, ChildProcessFilter}; pub use self::exit::{do_exit, do_wait4, ChildProcessFilter};
pub use self::spawn::{do_spawn, FileAction}; pub use self::spawn::{do_spawn, FileAction};
pub use self::wait::{WaitQueue, Waiter}; pub use self::wait::{WaitQueue, Waiter};
@ -30,6 +28,7 @@ pub struct Process {
waiting_children: Option<WaitQueue<ChildProcessFilter, pid_t>>, waiting_children: Option<WaitQueue<ChildProcessFilter, pid_t>>,
vm: ProcessVMRef, vm: ProcessVMRef,
file_table: FileTableRef, file_table: FileTableRef,
rlimits: ResourceLimitsRef,
} }
pub type ProcessRef = Arc<SgxMutex<Process>>; pub type ProcessRef = Arc<SgxMutex<Process>>;
@ -79,3 +78,4 @@ use self::task::Task;
use super::*; use super::*;
use fs::{File, FileRef, FileTable}; use fs::{File, FileRef, FileTable};
use vm::{ProcessVM, VMRangeTrait}; use vm::{ProcessVM, VMRangeTrait};
use misc::{ResourceLimitsRef};

@ -20,6 +20,7 @@ lazy_static! {
waiting_children: Default::default(), waiting_children: Default::default(),
vm: Default::default(), vm: Default::default(),
file_table: Default::default(), file_table: Default::default(),
rlimits: Default::default(),
})) }))
}; };
} }
@ -30,6 +31,7 @@ impl Process {
task: Task, task: Task,
vm_ref: ProcessVMRef, vm_ref: ProcessVMRef,
file_table_ref: FileTableRef, file_table_ref: FileTableRef,
rlimits_ref: ResourceLimitsRef,
) -> Result<(pid_t, ProcessRef), Error> { ) -> Result<(pid_t, ProcessRef), Error> {
let new_pid = process_table::alloc_pid(); let new_pid = process_table::alloc_pid();
let new_process_ref = Arc::new(SgxMutex::new(Process { let new_process_ref = Arc::new(SgxMutex::new(Process {
@ -46,6 +48,7 @@ impl Process {
waiting_children: None, waiting_children: None,
vm: vm_ref, vm: vm_ref,
file_table: file_table_ref, file_table: file_table_ref,
rlimits: rlimits_ref,
})); }));
Ok((new_pid, new_process_ref)) Ok((new_pid, new_process_ref))
} }
@ -97,6 +100,9 @@ impl Process {
self.cwd += path; self.cwd += path;
} }
} }
pub fn get_rlimits(&self) -> &ResourceLimitsRef {
&self.rlimits
}
} }
impl Drop for Process { impl Drop for Process {

@ -14,8 +14,10 @@ pub fn remove(pid: pid_t) {
PROCESS_TABLE.lock().unwrap().remove(&pid); PROCESS_TABLE.lock().unwrap().remove(&pid);
} }
pub fn get(pid: pid_t) -> Option<ProcessRef> { pub fn get(pid: pid_t) -> Result<ProcessRef, Error> {
PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone()) PROCESS_TABLE.lock().unwrap().get(&pid)
.map(|pr| pr.clone())
.ok_or_else(|| Error::new(Errno::ENOENT, "process not found"))
} }
static NEXT_PID: AtomicU32 = AtomicU32::new(1); static NEXT_PID: AtomicU32 = AtomicU32::new(1);

@ -6,6 +6,7 @@ use std::ffi::{CStr, CString};
use std::path::Path; use std::path::Path;
use std::sgxfs::SgxFile; use std::sgxfs::SgxFile;
use vm::{ProcessVM, VMRangeTrait}; use vm::{ProcessVM, VMRangeTrait};
use misc::{ResourceLimitsRef};
use super::*; use super::*;
use super::task::Task; use super::task::Task;
@ -72,7 +73,8 @@ pub fn do_spawn<P: AsRef<Path>>(
let files = init_files(parent_ref, file_actions)?; let files = init_files(parent_ref, file_actions)?;
Arc::new(SgxMutex::new(files)) Arc::new(SgxMutex::new(files))
}; };
Process::new(&cwd, task, vm_ref, files_ref)? let rlimits_ref = Default::default();
Process::new(&cwd, task, vm_ref, files_ref, rlimits_ref)?
}; };
parent_adopts_new_child(&parent_ref, &new_process_ref); parent_adopts_new_child(&parent_ref, &new_process_ref);
process_table::put(new_pid, new_process_ref.clone()); process_table::put(new_pid, new_process_ref.clone());

@ -51,8 +51,9 @@ pub fn do_clone(
let task = new_thread_task(stack_addr, new_tls)?; let task = new_thread_task(stack_addr, new_tls)?;
let vm_ref = current.get_vm().clone(); let vm_ref = current.get_vm().clone();
let files_ref = current.get_files().clone(); let files_ref = current.get_files().clone();
let rlimits_ref = current.get_rlimits().clone();
let cwd = &current.cwd; let cwd = &current.cwd;
Process::new(cwd, task, vm_ref, files_ref)? Process::new(cwd, task, vm_ref, files_ref, rlimits_ref)?
}; };
if let Some(ctid) = ctid { if let Some(ctid) = ctid {

@ -8,7 +8,7 @@ use std::ptr;
use time::timeval_t; use time::timeval_t;
use util::mem_util::from_user::*; use util::mem_util::from_user::*;
use vm::{VMAreaFlags, VMResizeOptions}; use vm::{VMAreaFlags, VMResizeOptions};
use misc::{utsname_t}; use misc::{utsname_t, resource_t, rlimit_t};
use super::*; use super::*;
@ -134,6 +134,8 @@ pub extern "C" fn dispatch_syscall(
SYS_UNAME => do_uname(arg0 as *mut utsname_t), SYS_UNAME => do_uname(arg0 as *mut utsname_t),
SYS_PRLIMIT64 => do_prlimit(arg0 as pid_t, arg1 as u32, arg2 as *const rlimit_t, arg3 as *mut rlimit_t),
_ => do_unknown(num, arg0, arg1, arg2, arg3, arg4, arg5), _ => do_unknown(num, arg0, arg1, arg2, arg3, arg4, arg5),
}; };
debug!("syscall return: {:?}", ret); debug!("syscall return: {:?}", ret);
@ -705,3 +707,26 @@ fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
let name = unsafe { &mut *name }; let name = unsafe { &mut *name };
misc::do_uname(name).map(|_| 0) misc::do_uname(name).map(|_| 0)
} }
fn do_prlimit(pid: pid_t, resource: u32, new_limit: *const rlimit_t, old_limit: *mut rlimit_t) -> Result<isize, Error> {
let resource = resource_t::from_u32(resource)?;
let new_limit = {
if new_limit != ptr::null() {
check_ptr(new_limit)?;
Some(unsafe { &*new_limit })
}
else {
None
}
};
let old_limit = {
if old_limit != ptr::null_mut() {
check_mut_ptr(old_limit)?;
Some(unsafe { &mut *old_limit })
}
else {
None
}
};
misc::do_prlimit(pid, resource, new_limit, old_limit).map(|_| 0)
}

@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../)
# Dependencies: need to be compiled but not to run by any Makefile target # Dependencies: need to be compiled but not to run by any Makefile target
TEST_DEPS := dev_null TEST_DEPS := dev_null
# Tests: need to be compiled and run by test-% target # Tests: need to be compiled and run by test-% target
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread uname TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit
# Benchmarks: need to be compiled and run by bench-% target # Benchmarks: need to be compiled and run by bench-% target
BENCHES := spawn_and_exit_latency pipe_throughput BENCHES := spawn_and_exit_latency pipe_throughput

5
test/rlimit/Makefile Normal file

@ -0,0 +1,5 @@
include ../test_common.mk
EXTRA_C_FLAGS :=
EXTRA_LINK_FLAGS :=
BIN_ARGS :=

15
test/rlimit/main.c Normal file

@ -0,0 +1,15 @@
#include <sys/resource.h>
#include <stdio.h>
int main(int argc, const char* argv[]) {
struct rlimit rlim;
if (getrlimit(RLIMIT_AS, &rlim) < 0) {
printf("ERROR: getrlimit failed\n");
return -1;
}
if (setrlimit(RLIMIT_AS, &rlim) < 0) {
printf("ERROR: getrlimit failed\n");
return -1;
}
return 0;
}