Skip to content

Commit

Permalink
feat: support negative sets
Browse files Browse the repository at this point in the history
  • Loading branch information
desbma authored and desbma-s1n committed Nov 14, 2024
1 parent 5c4454b commit baeea83
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 11 deletions.
87 changes: 79 additions & 8 deletions src/summarize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub(crate) struct NetworkActivity {
pub af: SetSpecifier<SocketFamily>,
pub proto: SetSpecifier<SocketProtocol>,
pub kind: SetSpecifier<NetworkActivityKind>,
pub local_port: CountableSetSpecifier<u16>,
}

/// Quantify something that is done or denied
Expand All @@ -62,23 +63,71 @@ pub(crate) enum SetSpecifier<T> {
impl<T: Eq> SetSpecifier<T> {
fn contains_one(&self, needle: &T) -> bool {
match self {
SetSpecifier::None => false,
SetSpecifier::One(e) => e == needle,
SetSpecifier::Some(es) => es.contains(needle),
SetSpecifier::All => true,
Self::None => false,
Self::One(e) => e == needle,
Self::Some(es) => es.contains(needle),
Self::All => true,
}
}

pub(crate) fn intersects(&self, other: &Self) -> bool {
match self {
SetSpecifier::None => false,
SetSpecifier::One(e) => other.contains_one(e),
SetSpecifier::Some(es) => es.iter().any(|e| other.contains_one(e)),
SetSpecifier::All => !matches!(other, SetSpecifier::None),
Self::None => false,
Self::One(e) => other.contains_one(e),
Self::Some(es) => es.iter().any(|e| other.contains_one(e)),
Self::All => !matches!(other, Self::None),
}
}
}

pub(crate) trait ValueCounted {
fn value_count() -> usize;
}

impl ValueCounted for u16 {
fn value_count() -> usize {
Self::MAX as usize - Self::MIN as usize + 1
}
}

impl<T: Eq + ValueCounted> CountableSetSpecifier<T> {
fn contains_one(&self, needle: &T) -> bool {
match self {
Self::None => false,
Self::One(e) => e == needle,
Self::Some(es) => es.contains(needle),
Self::AllExcept(es) => !es.contains(needle),
Self::All => true,
}
}

pub(crate) fn intersects(&self, other: &Self) -> bool {
match self {
Self::None => false,
Self::One(e) => other.contains_one(e),
Self::Some(es) => es.iter().any(|e| other.contains_one(e)),
Self::AllExcept(excs) => match other {
Self::None => false,
Self::One(e) => !excs.contains(e),
Self::Some(es) => es.iter().any(|e| !excs.contains(e)),
Self::AllExcept(other_excs) => excs != other_excs,
Self::All => excs.len() < T::value_count(),
},
Self::All => !matches!(other, Self::None),
}
}
}

/// Quantify something that is done or denied
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub(crate) enum CountableSetSpecifier<T> {
None,
One(T),
Some(Vec<T>),
AllExcept(Vec<T>),
All,
}

/// Socket activity
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub(crate) enum NetworkActivityKind {
Expand Down Expand Up @@ -462,11 +511,32 @@ where
let af = af
.parse()
.map_err(|()| anyhow::anyhow!("Unable to parse socket family {af:?}"))?;
let local_port = match addr
.iter()
.find_map(|(k, v)| k.ends_with("_port").then_some(v))
{
Some(Expression::Macro {
name: macro_name,
args,
}) if macro_name == "htons" => match args.first() {
Some(Expression::Integer(IntegerExpression {
value: IntegerExpressionValue::Literal(port_val),
..
})) =>
{
#[expect(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
CountableSetSpecifier::One(*port_val as u16)
}
_ => todo!(),
},
_ => CountableSetSpecifier::None,
};
if let Some(proto) = known_sockets_proto.get(&(syscall.pid, *fd)) {
actions.push(ProgramAction::NetworkActivity(NetworkActivity {
af: SetSpecifier::One(af),
proto: SetSpecifier::One(proto.to_owned()),
kind: SetSpecifier::One(NetworkActivityKind::Bind),
local_port,
}));
}
}
Expand Down Expand Up @@ -516,6 +586,7 @@ where
af: SetSpecifier::One(af),
proto: SetSpecifier::One(proto),
kind: SetSpecifier::One(NetworkActivityKind::SocketCreation),
local_port: CountableSetSpecifier::All,
}));
}
Some(SyscallInfo::Mknod { mode_idx }) => {
Expand Down
9 changes: 8 additions & 1 deletion src/systemd/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use strum::IntoEnumIterator;

use crate::{
cl::HardeningMode,
summarize::{NetworkActivity, NetworkActivityKind, ProgramAction, SetSpecifier},
summarize::{
CountableSetSpecifier, NetworkActivity, NetworkActivityKind, ProgramAction, SetSpecifier,
},
systemd::{KernelVersion, SystemdVersion},
};

Expand Down Expand Up @@ -1164,6 +1166,7 @@ pub(crate) fn build_options(
af: SetSpecifier::One(af.parse().unwrap()),
proto: SetSpecifier::All,
kind: SetSpecifier::All,
local_port: CountableSetSpecifier::All,
},
))
})
Expand All @@ -1187,6 +1190,7 @@ pub(crate) fn build_options(
af: SetSpecifier::All,
proto: SetSpecifier::All,
kind: SetSpecifier::All,
local_port: CountableSetSpecifier::All,
}),
)),
}],
Expand Down Expand Up @@ -1223,6 +1227,7 @@ pub(crate) fn build_options(
af: SetSpecifier::One(af),
proto: SetSpecifier::One(proto),
kind: SetSpecifier::One(NetworkActivityKind::Bind),
local_port: CountableSetSpecifier::All,
},
))
})
Expand Down Expand Up @@ -1321,6 +1326,7 @@ pub(crate) fn build_options(
af: SetSpecifier::One(SocketFamily::Other("AF_PACKET".into())),
proto: SetSpecifier::All,
kind: SetSpecifier::All,
local_port: CountableSetSpecifier::All,
}),
))
.chain(
Expand All @@ -1332,6 +1338,7 @@ pub(crate) fn build_options(
af: SetSpecifier::One(af.parse().unwrap()),
proto: SetSpecifier::One(SocketProtocol::Other("SOCK_RAW".into())),
kind: SetSpecifier::All,
local_port: CountableSetSpecifier::All,
},
))
}),
Expand Down
9 changes: 7 additions & 2 deletions src/systemd/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ impl OptionValueEffect {
match self {
OptionValueEffect::DenyAction(denied) => match denied {
ProgramAction::NetworkActivity(denied) => {
if let ProgramAction::NetworkActivity(NetworkActivity { af, proto, kind }) =
action
if let ProgramAction::NetworkActivity(NetworkActivity {
af,
proto,
kind,
local_port,
}) = action
{
!denied.af.intersects(af)
|| !denied.proto.intersects(proto)
|| !denied.kind.intersects(kind)
|| !denied.local_port.intersects(local_port)
} else {
true
}
Expand Down

0 comments on commit baeea83

Please sign in to comment.