Add prlimit64, getrlimit, and setrlimit
This commit is contained in:
		
							parent
							
								
									8846c62b5e
								
							
						
					
					
						commit
						b003f4ce43
					
				| @ -1,5 +1,7 @@ | ||||
| use super::*; | ||||
| 
 | ||||
| mod uname; | ||||
| mod rlimit; | ||||
| 
 | ||||
| pub use self::uname::{utsname_t, do_uname}; | ||||
| pub use self::rlimit::{rlimit_t, resource_t, ResourceLimits, ResourceLimitsRef, do_prlimit}; | ||||
|  | ||||
							
								
								
									
										123
									
								
								src/libos/src/misc/rlimit.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										123
									
								
								src/libos/src/misc/rlimit.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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::task::{get_current, run_task}; | ||||
| pub mod table { | ||||
|     pub use super::process_table::get; | ||||
| } | ||||
| pub use self::process_table::{get}; | ||||
| pub use self::exit::{do_exit, do_wait4, ChildProcessFilter}; | ||||
| pub use self::spawn::{do_spawn, FileAction}; | ||||
| pub use self::wait::{WaitQueue, Waiter}; | ||||
| @ -30,6 +28,7 @@ pub struct Process { | ||||
|     waiting_children: Option<WaitQueue<ChildProcessFilter, pid_t>>, | ||||
|     vm: ProcessVMRef, | ||||
|     file_table: FileTableRef, | ||||
|     rlimits: ResourceLimitsRef, | ||||
| } | ||||
| 
 | ||||
| pub type ProcessRef = Arc<SgxMutex<Process>>; | ||||
| @ -79,3 +78,4 @@ use self::task::Task; | ||||
| use super::*; | ||||
| use fs::{File, FileRef, FileTable}; | ||||
| use vm::{ProcessVM, VMRangeTrait}; | ||||
| use misc::{ResourceLimitsRef}; | ||||
|  | ||||
| @ -20,6 +20,7 @@ lazy_static! { | ||||
|             waiting_children: Default::default(), | ||||
|             vm: Default::default(), | ||||
|             file_table: Default::default(), | ||||
|             rlimits: Default::default(), | ||||
|         })) | ||||
|     }; | ||||
| } | ||||
| @ -30,6 +31,7 @@ impl Process { | ||||
|         task: Task, | ||||
|         vm_ref: ProcessVMRef, | ||||
|         file_table_ref: FileTableRef, | ||||
|         rlimits_ref: ResourceLimitsRef, | ||||
|     ) -> Result<(pid_t, ProcessRef), Error> { | ||||
|         let new_pid = process_table::alloc_pid(); | ||||
|         let new_process_ref = Arc::new(SgxMutex::new(Process { | ||||
| @ -46,6 +48,7 @@ impl Process { | ||||
|             waiting_children: None, | ||||
|             vm: vm_ref, | ||||
|             file_table: file_table_ref, | ||||
|             rlimits: rlimits_ref, | ||||
|         })); | ||||
|         Ok((new_pid, new_process_ref)) | ||||
|     } | ||||
| @ -97,6 +100,9 @@ impl Process { | ||||
|             self.cwd += path; | ||||
|         } | ||||
|     } | ||||
|     pub fn get_rlimits(&self) -> &ResourceLimitsRef { | ||||
|         &self.rlimits | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Drop for Process { | ||||
|  | ||||
| @ -14,8 +14,10 @@ pub fn remove(pid: pid_t) { | ||||
|     PROCESS_TABLE.lock().unwrap().remove(&pid); | ||||
| } | ||||
| 
 | ||||
| pub fn get(pid: pid_t) -> Option<ProcessRef> { | ||||
|     PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone()) | ||||
| pub fn get(pid: pid_t) -> Result<ProcessRef, Error> { | ||||
|     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); | ||||
|  | ||||
| @ -6,6 +6,7 @@ use std::ffi::{CStr, CString}; | ||||
| use std::path::Path; | ||||
| use std::sgxfs::SgxFile; | ||||
| use vm::{ProcessVM, VMRangeTrait}; | ||||
| use misc::{ResourceLimitsRef}; | ||||
| 
 | ||||
| use super::*; | ||||
| use super::task::Task; | ||||
| @ -72,7 +73,8 @@ pub fn do_spawn<P: AsRef<Path>>( | ||||
|             let files = init_files(parent_ref, file_actions)?; | ||||
|             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); | ||||
|     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 vm_ref = current.get_vm().clone(); | ||||
|         let files_ref = current.get_files().clone(); | ||||
|         let rlimits_ref = current.get_rlimits().clone(); | ||||
|         let cwd = ¤t.cwd; | ||||
|         Process::new(cwd, task, vm_ref, files_ref)? | ||||
|         Process::new(cwd, task, vm_ref, files_ref, rlimits_ref)? | ||||
|     }; | ||||
| 
 | ||||
|     if let Some(ctid) = ctid { | ||||
|  | ||||
| @ -8,7 +8,7 @@ use std::ptr; | ||||
| use time::timeval_t; | ||||
| use util::mem_util::from_user::*; | ||||
| use vm::{VMAreaFlags, VMResizeOptions}; | ||||
| use misc::{utsname_t}; | ||||
| use misc::{utsname_t, resource_t, rlimit_t}; | ||||
| 
 | ||||
| use super::*; | ||||
| 
 | ||||
| @ -134,6 +134,8 @@ pub extern "C" fn dispatch_syscall( | ||||
| 
 | ||||
|         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), | ||||
|     }; | ||||
|     debug!("syscall return: {:?}", ret); | ||||
| @ -705,3 +707,26 @@ fn do_uname(name: *mut utsname_t) -> Result<isize, Error> { | ||||
|     let name = unsafe { &mut *name }; | ||||
|     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
 | ||||
| TEST_DEPS := dev_null | ||||
| # 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
 | ||||
| BENCHES := spawn_and_exit_latency pipe_throughput | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										5
									
								
								test/rlimit/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user