use std::collections::{HashMap, HashSet};
use syscalls::Sysno;
use super::YesReally;
use crate::{SeccompRule, RuleSet};
const NET_IO_SYSCALLS: &[Sysno] = &[
Sysno::epoll_create, Sysno::epoll_create1,
Sysno::epoll_ctl, Sysno::epoll_wait, Sysno::epoll_pwait, Sysno::epoll_pwait2,
Sysno::select, Sysno::pselect6,
Sysno::poll, Sysno::ppoll,
Sysno::accept, Sysno::accept4,
Sysno::eventfd, Sysno::eventfd2,
Sysno::fcntl, Sysno::ioctl,
Sysno::getsockopt,
Sysno::setsockopt,
Sysno::getpeername,
Sysno::getsockname,
];
const NET_READ_SYSCALLS: &[Sysno] = &[Sysno::listen,
Sysno::recvfrom, Sysno::recvmsg, Sysno::recvmmsg,
Sysno::read, Sysno::readv, Sysno::preadv, Sysno::preadv2];
const NET_WRITE_SYSCALLS: &[Sysno] = &[Sysno::sendto, Sysno::sendmsg, Sysno::sendmmsg,
Sysno::sendfile,
Sysno::write, Sysno::writev, Sysno::pwritev, Sysno::pwritev2];
#[must_use]
pub struct Networking {
allowed: HashSet<Sysno>,
custom: HashMap<Sysno, Vec<SeccompRule>>,
}
impl Networking {
pub fn nothing() -> Networking {
Networking {
allowed: HashSet::new(),
custom: HashMap::new(),
}
}
pub fn allow_running_tcp_servers(mut self) -> Networking {
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
self
}
pub fn allow_start_tcp_servers(mut self) -> YesReally<Networking> {
const AF_INET: u64 = libc::AF_INET as u64;
const AF_INET6: u64 = libc::AF_INET6 as u64;
const SOCK_STREAM: u64 = libc::SOCK_STREAM as u64;
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_INET == AF_INET))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_STREAM == SOCK_STREAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_INET6 == AF_INET6))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_STREAM == SOCK_STREAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
self.allowed.extend(&[Sysno::bind]);
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
YesReally::new(self)
}
pub fn allow_running_udp_sockets(mut self) -> Networking {
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
self
}
pub fn allow_start_udp_servers(mut self) -> YesReally<Networking> {
const AF_INET: u64 = libc::AF_INET as u64;
const AF_INET6: u64 = libc::AF_INET6 as u64;
const SOCK_DGRAM: u64 = libc::SOCK_DGRAM as u64;
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_INET == AF_INET))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_DGRAM == SOCK_DGRAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_INET6 == AF_INET6))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_DGRAM == SOCK_DGRAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
self.allowed.extend(&[Sysno::bind]);
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
YesReally::new(self)
}
pub fn allow_connect(mut self) -> YesReally<Networking> {
self.allowed.extend(&[Sysno::connect]);
YesReally::new(self)
}
pub fn allow_start_tcp_clients(mut self) -> Networking {
const AF_INET: u64 = libc::AF_INET as u64;
const AF_INET6: u64 = libc::AF_INET6 as u64;
const SOCK_STREAM: u64 = libc::SOCK_STREAM as u64;
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_INET == AF_INET))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_STREAM == SOCK_STREAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_INET6 == AF_INET6))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_STREAM == SOCK_STREAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
self.allowed.extend(&[Sysno::connect]);
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
self
}
pub fn allow_running_tcp_clients(mut self) -> Networking {
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
self
}
pub fn allow_start_unix_servers(mut self) -> YesReally<Networking> {
const AF_UNIX: u64 = libc::AF_UNIX as u64;
const SOCK_STREAM: u64 = libc::SOCK_STREAM as u64;
const SOCK_DGRAM: u64 = libc::SOCK_DGRAM as u64;
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_UNIX == AF_UNIX))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_STREAM == SOCK_STREAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
let rule = SeccompRule::new(Sysno::socket)
.and_condition(seccomp_arg_filter!(arg0 & AF_UNIX == AF_UNIX))
.and_condition(seccomp_arg_filter!(arg1 & SOCK_DGRAM == SOCK_DGRAM));
self.custom.entry(Sysno::socket)
.or_insert_with(Vec::new)
.push(rule);
self.allowed.extend(&[Sysno::bind]);
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
YesReally::new(self)
}
pub fn allow_running_unix_servers(mut self) -> Networking {
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
self
}
pub fn allow_running_unix_clients(mut self) -> Networking {
self.allowed.extend(NET_IO_SYSCALLS);
self.allowed.extend(NET_READ_SYSCALLS);
self.allowed.extend(NET_WRITE_SYSCALLS);
self
}
}
impl RuleSet for Networking {
fn simple_rules(&self) -> Vec<syscalls::Sysno> {
self.allowed.iter().copied().collect()
}
fn conditional_rules(&self) -> HashMap<syscalls::Sysno, Vec<SeccompRule>> {
self.custom.clone()
}
fn name(&self) -> &'static str {
"Networking"
}
}