From f1db25e7ad7f1daa75aefff7944639981f88af98 Mon Sep 17 00:00:00 2001 From: Sebastian Walz Date: Wed, 3 Jul 2024 16:55:57 +0200 Subject: [PATCH] feat(builtins): add builtin `Netlink` --- src/builtins/mod.rs | 30 ++++------ src/builtins/{network.rs => network/mod.rs} | 14 +++-- src/builtins/network/netlink.rs | 62 +++++++++++++++++++++ 3 files changed, 83 insertions(+), 23 deletions(-) rename src/builtins/{network.rs => network/mod.rs} (98%) create mode 100644 src/builtins/network/netlink.rs diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 43b3c50..bbdc1bd 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -1,5 +1,16 @@ //! 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}, 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 +27,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..e583806 100644 --- a/src/builtins/network.rs +++ b/src/builtins/network/mod.rs @@ -1,11 +1,15 @@ //! Contains a [`RuleSet`] for allowing networking-related syscalls. -use std::collections::{HashMap, HashSet}; +pub mod netlink; -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; // TODO: make bind calls conditional on the DGRAM/UNIX/STREAM flag in each function @@ -205,7 +209,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)); + } +}