Skip to content

Commit

Permalink
feat: track current dir
Browse files Browse the repository at this point in the history
  • Loading branch information
desbma committed Jan 16, 2025
1 parent f25364d commit 1d0080b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
31 changes: 29 additions & 2 deletions src/summarize/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::{
};

use super::{
BufferExpression, BufferType, CountableSetSpecifier, Expression, IntegerExpression,
BufferExpression, BufferType, CountableSetSpecifier, Expression, FdOrPath, IntegerExpression,
IntegerExpressionValue, NetworkActivity, NetworkActivityKind, NetworkPort, ProgramAction,
ProgramState, SetSpecifier, SocketFamily, SocketProtocol, Syscall, SyscallArgs,
SyscallArgsInfo,
Expand All @@ -35,14 +35,14 @@ pub(crate) enum HandlerError {
},
}

#[expect(clippy::needless_pass_by_value)]
pub(crate) fn summarize_syscall(
sc: &Syscall,
args: SyscallArgs,
actions: &mut Vec<ProgramAction>,
state: &mut ProgramState,
) -> Result<(), HandlerError> {
match args {
SyscallArgsInfo::Chdir(p) => handle_chdir(&sc.name, p, state),
SyscallArgsInfo::EpollCtl { op, event } => handle_epoll_ctl(&sc.name, op, event, actions),
SyscallArgsInfo::Mkdir { relfd, path } => handle_mkdir(&sc.name, relfd, path, actions),
SyscallArgsInfo::Mknod { mode } => handle_mknod(&sc.name, mode, actions),
Expand Down Expand Up @@ -74,6 +74,32 @@ pub(crate) fn summarize_syscall(
}
}

/// Handle chdir-like syscall
#[expect(clippy::needless_pass_by_value)]
fn handle_chdir(
name: &str,
path: FdOrPath<&Expression>,
state: &mut ProgramState,
) -> Result<(), HandlerError> {
let dir = match path {
FdOrPath::Fd(fd) => resolve_path(Path::new(""), Some(fd)),
FdOrPath::Path(Expression::Buffer(BufferExpression {
value: b,
type_: BufferType::Unknown,
})) => Some(PathBuf::from(OsStr::from_bytes(b))),
FdOrPath::Path(e) => {
return Err(HandlerError::ArgTypeMismatch {
sc_name: name.to_owned(),
arg: e.to_owned(),
});
}
};
if let Some(dir) = dir {
state.cur_dir = Some(dir);
}
Ok(())
}

/// Handle `epoll_ctl` syscall
fn handle_epoll_ctl(
name: &str,
Expand Down Expand Up @@ -562,6 +588,7 @@ fn socket_address_uds_path(members: &HashMap<String, Expression>) -> Option<Path

/// Resolve relative path if possible, and normalize it
fn resolve_path(path: &Path, relfd: Option<&Expression>) -> Option<PathBuf> {
// TODO use current directory
let path = if path.is_relative() {
let metadata = relfd.and_then(|a| a.metadata());
if let Some(metadata) = metadata {
Expand Down
15 changes: 15 additions & 0 deletions src/summarize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,15 @@ impl Display for NetworkPort {
}
}

enum FdOrPath<T> {
Fd(T),
Path(T),
}

/// Meta structure to group syscalls that have similar summary handling
/// and store arguments
enum SyscallArgsInfo<T> {
Chdir(FdOrPath<T>),
EpollCtl {
op: T,
event: T,
Expand Down Expand Up @@ -330,6 +336,10 @@ impl SyscallArgsIndex {
#[expect(clippy::shadow_unrelated)]
fn extract_args<'a>(&self, sc: &'a Syscall) -> anyhow::Result<SyscallArgs<'a>> {
let args = match self {
Self::Chdir(p) => SyscallArgsInfo::Chdir(match p {
FdOrPath::Fd(i) => FdOrPath::Fd(Self::extract_arg(sc, *i)?),
FdOrPath::Path(i) => FdOrPath::Path(Self::extract_arg(sc, *i)?),
}),
Self::EpollCtl { op, event } => SyscallArgs::EpollCtl {
op: Self::extract_arg(sc, *op)?,
event: Self::extract_arg(sc, *event)?,
Expand Down Expand Up @@ -418,6 +428,9 @@ impl SyscallArgsIndex {
//
static SYSCALL_MAP: LazyLock<HashMap<&'static str, SyscallArgsIndex>> = LazyLock::new(|| {
HashMap::from([
// chdir
("chdir", SyscallArgsIndex::Chdir(FdOrPath::Path(0))),
("fchdir", SyscallArgsIndex::Chdir(FdOrPath::Fd(0))),
// epoll_ctl
("epoll_ctl", SyscallArgsIndex::EpollCtl { op: 1, event: 3 }),
// mkdir
Expand Down Expand Up @@ -543,6 +556,8 @@ struct ProgramState {
/// Keep known socket protocols (per process) for bind handling, we don't care for the socket closings
/// because the fd will be reused or never bound again
known_sockets_proto: HashMap<(u32, i32), SocketProtocol>,
/// Current working directory
cur_dir: Option<PathBuf>,
}

pub(crate) fn summarize<I>(syscalls: I) -> anyhow::Result<Vec<ProgramAction>>
Expand Down

0 comments on commit 1d0080b

Please sign in to comment.