#![deny(unsafe_code)]
#![warn(missing_docs)]
#![allow(clippy::manual_let_else)]
#![allow(clippy::too_many_lines)]
pub mod arp;
pub mod bash;
pub mod bash_history;
pub mod boot_time;
pub mod bpf;
pub mod capabilities;
pub mod cgroups;
pub mod check_afinfo;
pub mod check_creds;
pub mod check_fops;
pub mod check_hooks;
pub mod check_idt;
pub mod check_modules;
pub mod cmdline;
pub mod container_escape;
pub mod correlate;
pub mod cpu_pinning;
pub mod crontab;
pub mod deleted_exe;
pub mod dentry_cache;
pub mod dmesg;
pub mod ebpf_progs;
pub mod elf_analysis;
pub mod elfinfo;
pub mod envvars;
pub mod files;
pub mod framebuffer;
pub mod fs;
pub mod ftrace;
pub mod fuse_abuse;
pub mod futex_forensics;
pub mod heuristics;
pub mod io_uring;
pub mod iomem;
pub mod ipc;
pub mod kaslr;
pub mod kernel_timers;
pub mod keyboard_notifiers;
pub mod kmsg;
pub mod kthread;
pub mod ld_preload;
pub mod library_list;
pub mod magic_gid;
pub mod malfind;
pub mod maps;
pub mod memfd_create;
pub mod modules;
pub mod modxview;
pub mod mountinfo;
pub mod namespaces;
pub mod netfilter;
pub mod netlink_audit;
pub mod network;
pub mod oom_events;
pub mod pam_hooks;
pub mod perf_event;
pub mod preload_scanner;
pub mod proc_cmdline;
pub mod proc_hidden;
pub mod process;
pub mod psaux;
pub mod psxview;
pub mod ptrace;
pub mod raw_sockets;
pub mod seccomp;
pub mod shared_mem_anomaly;
pub mod signal_handlers;
pub mod ssh_keys;
pub mod syscalls;
pub mod systemd_units;
pub mod thread;
pub mod timerfd_signalfd;
pub mod tmpfs_recovery;
pub mod tty_check;
pub mod types;
pub mod unix_sockets;
pub mod user_ns_escalation;
pub mod vdso_tamper;
pub mod vma_walker;
pub mod zombie_orphan;
#[cfg(test)]
pub mod testing;
use memf_core::object_reader::ObjectReader;
use memf_format::PhysicalMemoryProvider;
pub use types::*;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("core error: {0}")]
Core(#[from] memf_core::Error),
#[error("symbol error: {0}")]
Symbol(#[from] memf_symbols::Error),
#[error("walker error: {0}")]
Walker(String),
#[error("kernel symbol not found: {name}")]
MissingKernelSymbol {
name: String,
},
#[error("ISF missing field: {struct_name}.{field_name}")]
MissingField {
struct_name: String,
field_name: String,
},
#[error("walker '{walker}' failed: {reason}")]
WalkFailed {
walker: &'static str,
reason: String,
},
#[error("list walk failed in walker '{walker}': {reason}")]
ListWalkFailed {
walker: &'static str,
reason: String,
},
}
pub type Result<T> = std::result::Result<T, Error>;
pub trait WalkerPlugin: Send + Sync {
fn name(&self) -> &str;
fn probe<P: PhysicalMemoryProvider>(&self, reader: &ObjectReader<P>) -> u8;
fn processes<P: PhysicalMemoryProvider>(
&self,
reader: &ObjectReader<P>,
) -> Result<Vec<ProcessInfo>>;
fn connections<P: PhysicalMemoryProvider>(
&self,
reader: &ObjectReader<P>,
) -> Result<Vec<ConnectionInfo>>;
fn modules<P: PhysicalMemoryProvider>(
&self,
reader: &ObjectReader<P>,
) -> Result<Vec<ModuleInfo>>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_display() {
let e = Error::Walker("test error".into());
assert_eq!(e.to_string(), "walker error: test error");
}
#[test]
fn error_missing_kernel_symbol_contains_name() {
let e = Error::MissingKernelSymbol {
name: "init_task".to_owned(),
};
assert!(e.to_string().contains("init_task"));
}
#[test]
fn error_missing_field_contains_struct_and_field() {
let e = Error::MissingField {
struct_name: "task_struct".to_owned(),
field_name: "mm".to_owned(),
};
assert!(e.to_string().contains("task_struct"));
assert!(e.to_string().contains("mm"));
}
#[test]
fn error_walk_failed_contains_walker_name() {
let e = Error::WalkFailed {
walker: "walk_processes",
reason: "list corrupted".to_owned(),
};
assert!(e.to_string().contains("walk_processes"));
assert!(e.to_string().contains("list corrupted"));
}
#[test]
fn error_list_walk_failed_contains_walker_and_reason() {
let e = Error::ListWalkFailed {
walker: "walk_processes",
reason: "cycle detected".to_owned(),
};
assert!(e.to_string().contains("walk_processes"));
assert!(e.to_string().contains("cycle detected"));
}
}