use eyre::{Result, eyre};
use nix::libc;
use seccompiler::{
BpfProgram, SeccompAction, SeccompCmpArgLen, SeccompCmpOp, SeccompCondition, SeccompFilter,
SeccompRule, TargetArch,
};
use std::collections::BTreeMap;
pub fn apply_seccomp_net_filter() -> Result<()> {
let ret = unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) };
if ret != 0 {
return Err(eyre!(
"failed to set PR_SET_NO_NEW_PRIVS: {}",
std::io::Error::last_os_error()
));
}
let arch = std::env::consts::ARCH;
let target_arch = match arch {
"x86_64" => TargetArch::x86_64,
"aarch64" => TargetArch::aarch64,
_ => return Err(eyre!("unsupported architecture for seccomp: {arch}")),
};
let socket_rule_inet = SeccompRule::new(vec![SeccompCondition::new(
0, SeccompCmpArgLen::Dword,
SeccompCmpOp::Eq,
libc::AF_INET as u64,
)?])?;
let socket_rule_inet6 = SeccompRule::new(vec![SeccompCondition::new(
0,
SeccompCmpArgLen::Dword,
SeccompCmpOp::Eq,
libc::AF_INET6 as u64,
)?])?;
let mut rules: BTreeMap<i64, Vec<SeccompRule>> = BTreeMap::new();
#[allow(clippy::useless_conversion)]
for syscall in [libc::SYS_socket, libc::SYS_socketpair].map(i64::from) {
rules.insert(
syscall,
vec![socket_rule_inet.clone(), socket_rule_inet6.clone()],
);
}
let filter: BpfProgram = SeccompFilter::new(
rules,
SeccompAction::Allow, SeccompAction::Errno(libc::EPERM as u32), target_arch,
)?
.try_into()?;
seccompiler::apply_filter(&filter).map_err(|e| eyre!("failed to apply seccomp filter: {e}"))?;
Ok(())
}