use crate::policy::ResourceLimits;
fn apply_one(resource: libc::c_int, value: Option<u64>) -> Option<String> {
let value = value?;
let requested = value;
let target = requested as libc::rlim_t;
if target as u128 != requested as u128 {
return Some(format!("setrlimit({resource}) value does not fit this ABI"));
}
let mut current = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
if unsafe { libc::getrlimit(resource, &mut current) } != 0 {
return Some(format!(
"getrlimit({resource}): {}",
std::io::Error::last_os_error()
));
}
let effective = std::cmp::min(current.rlim_max, target);
let limit = libc::rlimit {
rlim_cur: effective,
rlim_max: effective,
};
if unsafe { libc::setrlimit(resource, &limit) } != 0 {
return Some(format!(
"setrlimit({resource}, {effective}): {}",
std::io::Error::last_os_error()
));
}
None
}
pub fn apply_before_exec(limits: &ResourceLimits) -> Vec<String> {
let mut refused = Vec::new();
let entries = [
(libc::RLIMIT_CPU, "cpu", limits.cpu_seconds),
(libc::RLIMIT_AS, "address_space", limits.address_space_bytes),
(libc::RLIMIT_NPROC, "processes", limits.processes),
(libc::RLIMIT_NOFILE, "open_files", limits.open_files),
(libc::RLIMIT_FSIZE, "file_size", limits.file_size_bytes),
];
for (resource, name, value) in entries {
if let Some(error) = apply_one(resource, value) {
refused.push(format!("resource limit '{name}' not enforced: {error}"));
}
}
refused
}