use crate::compat::Compatibility;
use crate::{CompatLevel, CompatState, RestrictSelfError};
use std::io::Error;
fn prctl_set_no_new_privs() -> Result<(), Error> {
match unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) } {
0 => Ok(()),
_ => Err(Error::last_os_error()),
}
}
fn support_no_new_privs() -> bool {
matches!(
unsafe { libc::prctl(libc::PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) },
0 | 1
)
}
pub(crate) fn try_set_no_new_privs(compat: &mut Compatibility) -> Result<bool, RestrictSelfError> {
if let Err(e) = prctl_set_no_new_privs() {
match compat.level.into() {
CompatLevel::BestEffort => {}
CompatLevel::SoftRequirement => {
compat.update(CompatState::Dummy);
}
CompatLevel::HardRequirement => {
return Err(RestrictSelfError::SetNoNewPrivsCall { source: e });
}
}
let support_nnp = support_no_new_privs();
match compat.state {
CompatState::Init | CompatState::No | CompatState::Dummy => {
if support_nnp {
return Err(RestrictSelfError::SetNoNewPrivsCall { source: e });
}
}
CompatState::Full | CompatState::Partial => {
return Err(RestrictSelfError::SetNoNewPrivsCall { source: e })
}
}
Ok(false)
} else {
Ok(true)
}
}