Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fact-ebpf/src/bpf/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ __always_inline static void submit_event(struct metrics_by_hook_t* m, file_activ

event->type = event_type;
event->timestamp = bpf_ktime_get_boot_ns();
event->dev = BPF_CORE_READ(dentry, d_sb, s_dev);
bpf_probe_read_str(event->filename, PATH_MAX, filename);

struct helper_t* helper = get_helper();
Expand Down
4 changes: 4 additions & 0 deletions fact-ebpf/src/bpf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ int BPF_PROG(trace_file_open, struct file* file) {
return 0;
}

/*
if (!is_monitored(path)) {
goto ignored;
}
*/

struct dentry* d = BPF_CORE_READ(file, f_path.dentry);
submit_event(&m->file_open, event_type, path->path, d);
Expand Down Expand Up @@ -79,10 +81,12 @@ int BPF_PROG(trace_path_unlink, struct path* dir, struct dentry* dentry) {
goto error;
}

/*
if (!is_monitored(path)) {
m->path_unlink.ignored++;
return 0;
}
*/

submit_event(&m->path_unlink, FILE_ACTIVITY_UNLINK, path->path, dentry);
return 0;
Expand Down
1 change: 1 addition & 0 deletions fact-ebpf/src/bpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct event_t {
char filename[PATH_MAX];
char host_file[PATH_MAX];
file_activity_type_t type;
unsigned int dev;
};

/**
Expand Down
39 changes: 36 additions & 3 deletions fact/src/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ use tokio::{
task::JoinHandle,
};

use crate::{event::Event, host_info, metrics::EventCounter};
use crate::{
event::{
parser::{EventParser, EventParserError},
Event,
},
host_info,
metrics::EventCounter,
};

use fact_ebpf::{event_t, metrics_t, path_prefix_t, LPM_SIZE_MAX};

Expand All @@ -27,6 +34,8 @@ pub struct Bpf {

paths: Vec<path_prefix_t>,
paths_config: watch::Receiver<Vec<PathBuf>>,

parser: EventParser,
}

impl Bpf {
Expand All @@ -45,11 +54,13 @@ impl Bpf {

let paths = Vec::new();
let (tx, _) = broadcast::channel(100);
let parser = EventParser::new(paths_config.borrow().as_slice())?;
let mut bpf = Bpf {
obj,
tx,
paths,
paths_config,
parser,
};

bpf.load_paths()?;
Expand Down Expand Up @@ -173,8 +184,24 @@ impl Bpf {
let ringbuf = guard.get_inner_mut();
while let Some(event) = ringbuf.next() {
let event: &event_t = unsafe { &*(event.as_ptr() as *const _) };
let event = match Event::try_from(event) {
Ok(event) => Arc::new(event),
let event = match self.parser.parse(event) {
Ok(event) => event,
Err(EventParserError::NotFound) => {
let paths_config = self.paths_config.borrow();
self.parser.refresh(paths_config.as_slice())?;
if self.parser.mountinfo.get(&event.dev).is_none() {
self.parser.mountinfo.insert_empty(event.dev);
}
match self.parser.parse(event) {
Ok(event) => event,
Err(e) => {
error!("Failed to parse event: '{e}'");
debug!("Event: {event:?}");
event_counter.dropped();
continue;
}
}
}
Err(e) => {
error!("Failed to parse event: '{e}'");
debug!("Event: {event:?}");
Expand All @@ -183,6 +210,12 @@ impl Bpf {
}
};

if !event.is_monitored(self.paths_config.borrow().as_slice()) {
event_counter.ignored();
continue;
}
let event = Arc::new(event);

event_counter.added();
if self.tx.send(event).is_err() {
info!("No BPF consumers left, stopping...");
Expand Down
43 changes: 24 additions & 19 deletions fact/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use std::{ffi::CStr, os::raw::c_char, path::PathBuf};

use serde::Serialize;

use fact_ebpf::{event_t, file_activity_type_t, PATH_MAX};
use fact_ebpf::{file_activity_type_t, PATH_MAX};

use crate::host_info;
use crate::mount_info::MountEntry;
use process::Process;

pub(crate) mod parser;
pub(crate) mod process;

fn slice_to_string(s: &[c_char]) -> anyhow::Result<String> {
Expand Down Expand Up @@ -60,22 +61,17 @@ impl Event {
file,
})
}
}

impl TryFrom<&event_t> for Event {
type Error = anyhow::Error;

fn try_from(value: &event_t) -> Result<Self, Self::Error> {
let process = Process::try_from(value.process)?;
let timestamp = host_info::get_boot_time() + value.timestamp;
let file = FileData::new(value.type_, value.filename, value.host_file)?;
pub fn is_monitored(&self, paths: &[PathBuf]) -> bool {
let file = match &self.file {
FileData::Open(base_file_data) => base_file_data,
FileData::Creation(base_file_data) => base_file_data,
FileData::Unlink(base_file_data) => base_file_data,
};

Ok(Event {
timestamp,
hostname: host_info::get_hostname(),
process,
file,
})
paths
.iter()
.any(|prefix| file.filename.starts_with(prefix) || file.host_file.starts_with(prefix))
}
}

Expand Down Expand Up @@ -112,8 +108,9 @@ impl FileData {
event_type: file_activity_type_t,
filename: [c_char; PATH_MAX as usize],
host_file: [c_char; PATH_MAX as usize],
mounts: &Vec<MountEntry>,
) -> anyhow::Result<Self> {
let inner = BaseFileData::new(filename, host_file)?;
let inner = BaseFileData::new(filename, host_file, mounts)?;
let file = match event_type {
file_activity_type_t::FILE_ACTIVITY_OPEN => FileData::Open(inner),
file_activity_type_t::FILE_ACTIVITY_CREATION => FileData::Creation(inner),
Expand Down Expand Up @@ -169,13 +166,21 @@ impl BaseFileData {
pub fn new(
filename: [c_char; PATH_MAX as usize],
host_file: [c_char; PATH_MAX as usize],
mounts: &Vec<MountEntry>,
) -> anyhow::Result<Self> {
let filename = slice_to_string(&filename)?.into();
let host_file = slice_to_string(&host_file)?.into();
let mut host_file: PathBuf = slice_to_string(&host_file)?.into();

for mount in mounts {
if let Ok(hf) = host_file.strip_prefix(&mount.root) {
host_file = mount.mount_point.join(hf);
break;
}
}

Ok(BaseFileData {
filename,
host_file,
host_file: host_file.to_path_buf(),
})
}
}
Expand Down
66 changes: 66 additions & 0 deletions fact/src/event/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::{error::Error, fmt::Display, path::PathBuf};

use fact_ebpf::event_t;

use crate::{host_info, mount_info::MountInfo};

use super::{process::Process, Event, FileData};

#[derive(Debug)]
pub(crate) enum EventParserError {
NotFound,
ProcessParse(String),
FileParse(String),
}

impl Error for EventParserError {}
impl Display for EventParserError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
EventParserError::NotFound => write!(f, "mountpoint not found"),
EventParserError::ProcessParse(e) => write!(f, "Failed to parse process: {e}"),
EventParserError::FileParse(e) => write!(f, "Failed to parse file: {e}"),
}
}
}

pub(crate) struct EventParser {
pub mountinfo: MountInfo,
}

impl EventParser {
pub(crate) fn new(paths: &[PathBuf]) -> anyhow::Result<Self> {
let mountinfo = MountInfo::new(paths)?;

Ok(EventParser { mountinfo })
}

pub(crate) fn refresh(&mut self, paths: &[PathBuf]) -> anyhow::Result<()> {
self.mountinfo.refresh(paths)
}

pub(crate) fn parse(&mut self, event: &event_t) -> Result<Event, EventParserError> {
let process = match Process::try_from(event.process) {
Ok(p) => p,
Err(e) => return Err(EventParserError::ProcessParse(e.to_string())),
};
let timestamp = host_info::get_boot_time() + event.timestamp;

let mounts = match self.mountinfo.get(&event.dev) {
Some(mounts) => mounts,
None => return Err(EventParserError::NotFound),
};

let file = match FileData::new(event.type_, event.filename, event.host_file, mounts) {
Ok(f) => f,
Err(e) => return Err(EventParserError::FileParse(e.to_string())),
};

Ok(Event {
timestamp,
hostname: host_info::get_hostname(),
process,
file,
})
}
}
1 change: 1 addition & 0 deletions fact/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod endpoints;
mod event;
mod host_info;
mod metrics;
mod mount_info;
mod output;
mod pre_flight;

Expand Down
13 changes: 13 additions & 0 deletions fact/src/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ impl EventCounter {
.unwrap()
.inc_by(n);
}

/// Increment the counter for the Ignored label.
///
/// Panics if the counter did not add the Ignored label as part of
/// its creation step.
pub fn ignored(&self) {
self.counter
.get(&MetricEvents {
label: LabelValues::Ignored,
})
.unwrap()
.inc();
}
}

#[derive(Debug, Clone)]
Expand Down
Loading
Loading