Skip to content

Commit

Permalink
feat: improve network activity coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
desbma committed Feb 7, 2025
1 parent 8df9a0c commit d8aa8b5
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 71 deletions.
130 changes: 67 additions & 63 deletions src/summarize/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ fn handle_network(
actions: &mut Vec<ProgramAction>,
state: &mut ProgramState,
) -> Result<(), HandlerError> {
let (af, addr) = if let Expression::Struct(members) = sockaddr {
let (af_str, addr_struct) = if let Expression::Struct(members) = sockaddr {
let Some(Expression::Integer(IntegerExpression {
value: IntegerExpressionValue::NamedConst(af),
..
Expand All @@ -315,33 +315,60 @@ fn handle_network(
// Can be NULL in some cases, ie AF_NETLINK sockets
return Ok(());
};

#[expect(clippy::single_match)]
match af {
match af_str {
"AF_UNIX" => {
if let Some(path) = socket_address_uds_path(addr, state.cur_dir.as_ref()) {
if let Some(path) = socket_address_uds_path(addr_struct, state.cur_dir.as_ref()) {
actions.push(ProgramAction::Read(path));
};
}
_ => (),
}
let af = af_str.parse().map_err(|()| HandlerError::ParsingFailed {
src: af_str.to_owned(),
type_: type_name::<SocketFamily>(),
})?;

if name == "bind" {
let Expression::Integer(IntegerExpression {
value: IntegerExpressionValue::Literal(fd_val),
..
}) = fd
else {
return Err(HandlerError::ArgTypeMismatch {
sc_name: name.to_owned(),
arg: fd.to_owned(),
});
};
let af = af.parse().map_err(|()| HandlerError::ParsingFailed {
src: af.to_owned(),
type_: type_name::<SocketFamily>(),
})?;
let local_port = match addr
let Expression::Integer(IntegerExpression {
value: IntegerExpressionValue::Literal(fd_val),
..
}) = fd
else {
return Err(HandlerError::ArgTypeMismatch {
sc_name: name.to_owned(),
arg: fd.to_owned(),
});
};

let ip_addr = match addr_struct
.iter()
.find_map(|(k, v)| (k == "sin_addr").then_some(v))
{
Some(Expression::Macro {
name: macro_name,
args,
}) if macro_name == "inet_addr" => match args.first() {
Some(Expression::Buffer(BufferExpression { value, .. })) => {
let ip_str = str::from_utf8(value).map_err(|_| HandlerError::ConversionFailed {
src: format!("{value:?}"),
type_src: type_name_of_val(value),
type_dst: type_name::<&str>(),
})?;
let ip =
Ipv4Addr::from_str(ip_str).map_err(|_| HandlerError::ConversionFailed {
src: ip_str.to_owned(),
type_src: type_name_of_val(ip_str),
type_dst: type_name::<Ipv4Addr>(),
})?;
CountableSetSpecifier::One(ip.into())
}
_ => todo!(),
},
_ => CountableSetSpecifier::None,
};

let local_port = if name == "bind" {
match addr_struct
.iter()
.find_map(|(k, v)| k.ends_with("_port").then_some(v))
{
Expand Down Expand Up @@ -373,51 +400,28 @@ fn handle_network(
_ => todo!(),
},
_ => CountableSetSpecifier::None,
};
let ip = match addr
.iter()
.find_map(|(k, v)| (k == "sin_addr").then_some(v))
{
Some(Expression::Macro {
name: macro_name,
args,
}) if macro_name == "inet_addr" => match args.first() {
Some(Expression::Buffer(BufferExpression { value, .. })) => {
let ip = Ipv4Addr::from_str(str::from_utf8(value).map_err(|_| {
HandlerError::ConversionFailed {
src: format!("{value:?}"),
type_src: type_name_of_val(value),
type_dst: type_name::<Ipv4Addr>(),
}
})?)
.map_err(|_| HandlerError::ConversionFailed {
src: fd_val.to_string(),
type_src: type_name_of_val(fd_val),
type_dst: type_name::<RawFd>(),
})?;
CountableSetSpecifier::One(ip.into())
}
_ => todo!(),
},
_ => CountableSetSpecifier::None,
};
if let Some(proto) = state.known_sockets_proto.get(&(
pid,
TryInto::<RawFd>::try_into(*fd_val).map_err(|_| HandlerError::ConversionFailed {
src: fd_val.to_string(),
type_src: type_name_of_val(fd_val),
type_dst: type_name::<RawFd>(),
})?,
)) {
actions.push(ProgramAction::NetworkActivity(NetworkActivity {
af: SetSpecifier::One(af),
proto: SetSpecifier::One(proto.to_owned()),
kind: SetSpecifier::One(NetworkActivityKind::Bind),
local_port,
address: ip,
}));
}
} else {
CountableSetSpecifier::All
};

if let Some(proto) = state.known_sockets_proto.get(&(
pid,
TryInto::<RawFd>::try_into(*fd_val).map_err(|_| HandlerError::ConversionFailed {
src: fd_val.to_string(),
type_src: type_name_of_val(fd_val),
type_dst: type_name::<RawFd>(),
})?,
)) {
actions.push(ProgramAction::NetworkActivity(NetworkActivity {
af: SetSpecifier::One(af),
proto: SetSpecifier::One(proto.to_owned()),
kind: SetSpecifier::One(NetworkActivityKind::from_sc_name(name)),
local_port,
address: ip_addr,
}));
}

Ok(())
}

Expand Down
34 changes: 26 additions & 8 deletions src/summarize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,31 @@ impl<T: Eq + Ord + Clone + Display + ValueCounted + Sub<Output = T> + Add<Output
pub(crate) enum NetworkActivityKind {
SocketCreation,
Bind,
// TODO
// Connect,
// Send,
// Recv,
Connect,
Accept,
SendRecv,
}

impl NetworkActivityKind {
/// All kinds that are linked with one or more addresses
pub(crate) const ADDRESSED: [Self; 1] = [NetworkActivityKind::Bind];
pub(crate) const ADDRESSED: [Self; 4] = [
NetworkActivityKind::Bind,
NetworkActivityKind::Connect,
NetworkActivityKind::Accept,
NetworkActivityKind::SendRecv,
];

/// Get kind from syscall name, panic if it fails
fn from_sc_name(sc: &str) -> Self {
match sc {
"socket" => NetworkActivityKind::SocketCreation,
"bind" => NetworkActivityKind::Bind,
"connect" => NetworkActivityKind::Connect,
"accept" | "accept4" => NetworkActivityKind::Accept,
"sendto" | "recvfrom" => NetworkActivityKind::SendRecv,
_ => unreachable!("{:?}", sc),
}
}
}

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
Expand Down Expand Up @@ -562,12 +578,14 @@ static SYSCALL_MAP: LazyLock<HashMap<&'static str, SyscallArgsIndex>> = LazyLock
SyscallArgsIndex::Mmap { prot: 2, fd: None },
),
// network
("connect", SyscallArgsIndex::Network { fd: 0, sockaddr: 1 }),
// We don't track other send/recv variants because, we can track activity we need
// from other syscalls
("accept", SyscallArgsIndex::Network { fd: 0, sockaddr: 1 }),
("accept4", SyscallArgsIndex::Network { fd: 0, sockaddr: 1 }),
("bind", SyscallArgsIndex::Network { fd: 0, sockaddr: 1 }),
("connect", SyscallArgsIndex::Network { fd: 0, sockaddr: 1 }),
("recvfrom", SyscallArgsIndex::Network { fd: 0, sockaddr: 4 }),
("sendto", SyscallArgsIndex::Network { fd: 0, sockaddr: 4 }),
// TODO send/recv/recvmsg/sendmsg

// open
(
"open",
Expand Down

0 comments on commit d8aa8b5

Please sign in to comment.