diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 43b3c50..81b0e5c 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -1,5 +1,19 @@ //! Built-in [`RuleSet`](crate::RuleSet)s +pub mod basic; +pub mod danger_zone; +pub mod network; +pub mod pipes; +pub mod systemio; +pub mod time; + +pub use self::{ + basic::BasicCapabilities, + network::{Networking, Netlink, SocketPair}, + systemio::SystemIO, + time::Time, +}; + /// A struct whose purpose is to make you read the documentation for the function you're calling. /// If you're reading this, go read the documentation for the function that is returning this /// object. @@ -16,23 +30,6 @@ impl YesReally { /// Make a [`YesReally`]. pub fn new(inner: T) -> YesReally { - YesReally { - inner, - } + YesReally { inner } } } - -pub mod basic; -pub use basic::BasicCapabilities; - -pub mod systemio; -pub use systemio::SystemIO; - -pub mod network; -pub use network::Networking; - -pub mod time; -pub use time::Time; - -pub mod danger_zone; -pub mod pipes; diff --git a/src/builtins/network.rs b/src/builtins/network/mod.rs similarity index 98% rename from src/builtins/network.rs rename to src/builtins/network/mod.rs index c959c1d..7aa3038 100644 --- a/src/builtins/network.rs +++ b/src/builtins/network/mod.rs @@ -1,11 +1,16 @@ //! Contains a [`RuleSet`] for allowing networking-related syscalls. -use std::collections::{HashMap, HashSet}; +pub mod netlink; +pub mod socket_pair; -use syscalls::Sysno; +use { + super::YesReally, + crate::{RuleSet, SeccompRule}, + std::collections::{HashMap, HashSet}, + syscalls::Sysno, +}; -use super::YesReally; -use crate::{SeccompRule, RuleSet}; +pub use self::{netlink::Netlink, socket_pair::SocketPair}; // TODO: make bind calls conditional on the DGRAM/UNIX/STREAM flag in each function @@ -205,7 +210,7 @@ impl Networking { 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); diff --git a/src/builtins/network/netlink.rs b/src/builtins/network/netlink.rs new file mode 100644 index 0000000..62befbd --- /dev/null +++ b/src/builtins/network/netlink.rs @@ -0,0 +1,62 @@ +//! Allow netlink-sockets. + +use { + crate::{ + RuleSet, SeccompArgumentFilter as Filter, SeccompRule as Rule, + SeccompilerComparator as Comparator, + }, + std::collections::HashMap, + syscalls::Sysno, +}; + +/// Allow the syscall `socket` to open a netlink-socket. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd)] +#[must_use] +pub struct Netlink; + +impl RuleSet for Netlink { + fn simple_rules(&self) -> Vec { + Vec::default() + } + + #[allow(clippy::as_conversions)] + fn conditional_rules(&self) -> HashMap> { + /// `AF_NETLINK` as `u64`. + const AF_NETLINK: u64 = libc::AF_NETLINK as u64; + + /// `SOCK_RAW` as `u64`. + const SOCK_RAW: u64 = libc::SOCK_RAW as u64; + + let rule = Rule::new(Sysno::socket) + .and_condition(Filter::new(0, Comparator::MaskedEq(AF_NETLINK), AF_NETLINK)) + .and_condition(Filter::new(1, Comparator::MaskedEq(SOCK_RAW), SOCK_RAW)); + HashMap::from([(Sysno::socket, Vec::from([rule]))]) + } + + fn name(&self) -> &'static str { + "Netlink" + } +} + +#[cfg(test)] +mod tests { + use {super::Netlink, crate::RuleSet as _, syscalls::Sysno}; + + #[test] + fn name() { + assert_eq!(Netlink.name(), "Netlink"); + } + + #[test] + fn simple_rules() { + let rules = Netlink.simple_rules(); + assert!(rules.is_empty()); + } + + #[test] + fn conditional_rules() { + let rules = Netlink.conditional_rules(); + assert_eq!(rules.len(), 1); + assert!(rules.contains_key(&Sysno::socket)); + } +} diff --git a/src/builtins/network/socket_pair.rs b/src/builtins/network/socket_pair.rs new file mode 100644 index 0000000..1a9c181 --- /dev/null +++ b/src/builtins/network/socket_pair.rs @@ -0,0 +1,40 @@ +//! Allow `sys_socketpair`. + +use {crate::RuleSet, syscalls::Sysno}; + +/// Allow the syscall `socketpair` to create a pair of connected sockets. +#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd)] +#[must_use] +pub struct SocketPair; + +impl RuleSet for SocketPair { + fn simple_rules(&self) -> Vec { + Vec::from([Sysno::socketpair]) + } + + fn name(&self) -> &'static str { + "SocketPair" + } +} + +#[cfg(test)] +mod tests { + use {super::SocketPair, crate::RuleSet as _, syscalls::Sysno}; + + #[test] + fn name() { + assert_eq!(SocketPair.name(), "SocketPair"); + } + + #[test] + fn simple_rules() { + let rules = SocketPair.simple_rules(); + assert_eq!(rules.len(), 1); + assert!(rules.contains(&Sysno::socketpair)); + } + + #[test] + fn conditional_rules() { + assert!(SocketPair.conditional_rules().is_empty()); + } +}