diff --git a/src/child.rs b/src/child.rs index 5f30c368..c6e01821 100644 --- a/src/child.rs +++ b/src/child.rs @@ -4,7 +4,7 @@ use std::ptr; use libc; use nix; -use libc::{c_void, c_ulong, sigset_t, size_t}; +use libc::{c_void, c_ulong, sigset_t, size_t, rlimit}; use libc::{kill, signal}; use libc::{F_GETFD, F_SETFD, F_DUPFD_CLOEXEC, FD_CLOEXEC, MNT_DETACH}; use libc::{SIG_DFL, SIG_SETMASK}; @@ -215,6 +215,13 @@ pub unsafe fn child_after_clone(child: &ChildInfo) -> ! { } } + for &(rlim_type, rlim_value) in child.rlimits { + let limit = rlimit{rlim_cur: rlim_value, rlim_max: rlim_value}; + if libc::setrlimit(rlim_type, &limit) < 0 { + fail(Err::RLimit, epipe); + } + } + if let Some(callback) = child.pre_exec { if let Err(e) = callback() { fail_errno(Err::PreExec, diff --git a/src/error.rs b/src/error.rs index 8fe2c282..dc602229 100644 --- a/src/error.rs +++ b/src/error.rs @@ -21,6 +21,7 @@ pub enum ErrorCode { SetNs = 12, CapSet = 13, PreExec = 14, + RLimit = 16, } /// Error runnning process @@ -93,6 +94,8 @@ pub enum Error { BeforeUnfreeze(Box), /// Before exec callback error PreExec(i32), + /// Error when calling setrlimit syscall + SetRLimit(i32), } impl Error { @@ -120,6 +123,7 @@ impl Error { &CapSet(x) => Some(x), &BeforeUnfreeze(..) => None, &PreExec(x) => Some(x), + &SetRLimit(x) => Some(x), } } } @@ -148,6 +152,7 @@ impl Error { &CapSet(_) => "error when setting capabilities", &BeforeUnfreeze(_) => "error in before_unfreeze callback", &PreExec(_) => "error in pre_exec callback", + &SetRLimit(_) => "error setting rlimit", } } } @@ -240,6 +245,7 @@ impl ErrorCode { C::SetNs => E::SetNs(errno), C::CapSet => E::CapSet(errno), C::PreExec => E::PreExec(errno), + C::RLimit => E::SetRLimit(errno), } } pub fn from_i32(code: i32, errno: i32) -> Error { diff --git a/src/lib.rs b/src/lib.rs index 06f395c0..9d166669 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,6 +87,7 @@ pub struct Command { id_map_commands: Option<(PathBuf, PathBuf)>, pid_env_vars: HashSet, keep_caps: Option<[u32; 2]>, + rlimits: Vec<(libc::__rlimit_resource_t, libc::rlim_t)>, before_unfreeze: Option Result<(), BoxError>>>, pre_exec: Option Result<(), io::Error>>>, } diff --git a/src/linux.rs b/src/linux.rs index 35130a9f..d708cac3 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -2,7 +2,7 @@ use std::ffi::OsStr; use std::io; use std::os::unix::io::AsRawFd; use std::path::Path; - +use libc::{__rlimit_resource_t, rlim_t}; use nix::sys::signal::{Signal}; use crate::ffi_util::ToCString; @@ -293,4 +293,12 @@ impl Command { } self.keep_caps = Some(buf); } + + /// Set resource limits (rlimit / ulimit) + pub fn set_rlimit(&mut self, resource: __rlimit_resource_t, limit: rlim_t) + -> &mut Command + { + self.rlimits.push((resource, limit)); + self + } } diff --git a/src/run.rs b/src/run.rs index ccce6d11..2a395363 100644 --- a/src/run.rs +++ b/src/run.rs @@ -9,7 +9,7 @@ use std::os::unix::io::{RawFd, AsRawFd}; use std::path::{Path, PathBuf}; use std::ptr; -use libc::{c_char, close}; +use libc::{__rlimit_resource_t, c_char, close, rlim_t}; use nix; use nix::errno::Errno::EINTR; use nix::fcntl::{fcntl, FcntlArg, open}; @@ -52,6 +52,7 @@ pub struct ChildInfo<'a> { pub pid_env_vars: &'a [(usize, usize)], pub keep_caps: &'a Option<[u32; 2]>, pub pre_exec: &'a Option Result<(), io::Error>>>, + pub rlimits: &'a [(__rlimit_resource_t, rlim_t)], } fn raw_with_null(arr: &Vec) -> Vec<*const c_char> { @@ -258,6 +259,7 @@ impl Command { pid_env_vars: &pid_env_vars, keep_caps: &self.keep_caps, pre_exec: &self.pre_exec, + rlimits: &self.rlimits, }; child::child_after_clone(&child_info); }), &mut nstack[..], self.config.namespaces, Some(SIGCHLD as i32)))?; diff --git a/src/std_api.rs b/src/std_api.rs index aebeaf7a..d81665ad 100644 --- a/src/std_api.rs +++ b/src/std_api.rs @@ -46,6 +46,7 @@ impl Command { pid_env_vars: HashSet::new(), keep_caps: None, before_unfreeze: None, + rlimits: Vec::new(), pre_exec: None, } }