Skip to content

Commit 1c58b67

Browse files
committed
Filter mountpoint stored based on configuration
1 parent 4b356e7 commit 1c58b67

File tree

6 files changed

+107
-22
lines changed

6 files changed

+107
-22
lines changed

fact-ebpf/src/bpf/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ int BPF_PROG(trace_file_open, struct file* file) {
4141
return 0;
4242
}
4343

44+
/*
4445
if (!is_monitored(path)) {
4546
goto ignored;
4647
}
48+
*/
4749

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

84+
/*
8285
if (!is_monitored(path)) {
8386
m->path_unlink.ignored++;
8487
return 0;
8588
}
89+
*/
8690

8791
submit_event(&m->path_unlink, FILE_ACTIVITY_UNLINK, path->path, dentry);
8892
return 0;

fact/src/bpf.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use tokio::{
1515
};
1616

1717
use crate::{
18-
event::{parser::EventParser, Event},
18+
event::{
19+
parser::{EventParser, EventParserError},
20+
Event,
21+
},
1922
host_info,
2023
metrics::EventCounter,
2124
};
@@ -51,7 +54,7 @@ impl Bpf {
5154

5255
let paths = Vec::new();
5356
let (tx, _) = broadcast::channel(100);
54-
let parser = EventParser::new()?;
57+
let parser = EventParser::new(paths_config.borrow().as_slice())?;
5558
let mut bpf = Bpf {
5659
obj,
5760
tx,
@@ -182,7 +185,23 @@ impl Bpf {
182185
while let Some(event) = ringbuf.next() {
183186
let event: &event_t = unsafe { &*(event.as_ptr() as *const _) };
184187
let event = match self.parser.parse(event) {
185-
Ok(event) => Arc::new(event),
188+
Ok(event) => event,
189+
Err(EventParserError::NotFound) => {
190+
let paths_config = self.paths_config.borrow();
191+
self.parser.refresh(paths_config.as_slice())?;
192+
if self.parser.mountinfo.get(&event.dev).is_none() {
193+
self.parser.mountinfo.insert_empty(event.dev);
194+
}
195+
match self.parser.parse(event) {
196+
Ok(event) => event,
197+
Err(e) => {
198+
error!("Failed to parse event: '{e}'");
199+
debug!("Event: {event:?}");
200+
event_counter.dropped();
201+
continue;
202+
}
203+
}
204+
}
186205
Err(e) => {
187206
error!("Failed to parse event: '{e}'");
188207
debug!("Event: {event:?}");
@@ -191,6 +210,12 @@ impl Bpf {
191210
}
192211
};
193212

213+
if !event.is_monitored(self.paths_config.borrow().as_slice()) {
214+
event_counter.ignored();
215+
continue;
216+
}
217+
let event = Arc::new(event);
218+
194219
event_counter.added();
195220
if self.tx.send(event).is_err() {
196221
info!("No BPF consumers left, stopping...");

fact/src/event/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ impl Event {
6161
file,
6262
})
6363
}
64+
65+
pub fn is_monitored(&self, paths: &[PathBuf]) -> bool {
66+
let file = match &self.file {
67+
FileData::Open(base_file_data) => base_file_data,
68+
FileData::Creation(base_file_data) => base_file_data,
69+
FileData::Unlink(base_file_data) => base_file_data,
70+
};
71+
72+
paths
73+
.iter()
74+
.any(|prefix| file.filename.starts_with(prefix) || file.host_file.starts_with(prefix))
75+
}
6476
}
6577

6678
impl From<Event> for fact_api::FileActivity {

fact/src/event/parser.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,60 @@
1+
use std::{error::Error, fmt::Display, path::PathBuf};
2+
13
use fact_ebpf::event_t;
24

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

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

9+
#[derive(Debug)]
10+
pub(crate) enum EventParserError {
11+
NotFound,
12+
ProcessParse(String),
13+
FileParse(String),
14+
}
15+
16+
impl Error for EventParserError {}
17+
impl Display for EventParserError {
18+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19+
match self {
20+
EventParserError::NotFound => write!(f, "mountpoint not found"),
21+
EventParserError::ProcessParse(e) => write!(f, "Failed to parse process: {e}"),
22+
EventParserError::FileParse(e) => write!(f, "Failed to parse file: {e}"),
23+
}
24+
}
25+
}
26+
727
pub(crate) struct EventParser {
8-
mountinfo: MountInfo,
28+
pub mountinfo: MountInfo,
929
}
1030

1131
impl EventParser {
12-
pub(crate) fn new() -> anyhow::Result<Self> {
13-
let mountinfo = MountInfo::new()?;
32+
pub(crate) fn new(paths: &[PathBuf]) -> anyhow::Result<Self> {
33+
let mountinfo = MountInfo::new(paths)?;
1434

1535
Ok(EventParser { mountinfo })
1636
}
1737

18-
pub(crate) fn parse(&mut self, event: &event_t) -> anyhow::Result<Event> {
19-
let process = Process::try_from(event.process)?;
38+
pub(crate) fn refresh(&mut self, paths: &[PathBuf]) -> anyhow::Result<()> {
39+
self.mountinfo.refresh(paths)
40+
}
41+
42+
pub(crate) fn parse(&mut self, event: &event_t) -> Result<Event, EventParserError> {
43+
let process = match Process::try_from(event.process) {
44+
Ok(p) => p,
45+
Err(e) => return Err(EventParserError::ProcessParse(e.to_string())),
46+
};
2047
let timestamp = host_info::get_boot_time() + event.timestamp;
2148

2249
let mounts = match self.mountinfo.get(&event.dev) {
2350
Some(mounts) => mounts,
24-
None => {
25-
self.mountinfo.refresh()?;
26-
match self.mountinfo.get(&event.dev) {
27-
Some(mounts) => mounts,
28-
None => self.mountinfo.insert_empty(event.dev),
29-
}
30-
}
51+
None => return Err(EventParserError::NotFound),
3152
};
3253

33-
let file = FileData::new(event.type_, event.filename, event.host_file, mounts)?;
54+
let file = match FileData::new(event.type_, event.filename, event.host_file, mounts) {
55+
Ok(f) => f,
56+
Err(e) => return Err(EventParserError::FileParse(e.to_string())),
57+
};
3458

3559
Ok(Event {
3660
timestamp,

fact/src/metrics/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ impl EventCounter {
9797
.unwrap()
9898
.inc_by(n);
9999
}
100+
101+
/// Increment the counter for the Ignored label.
102+
///
103+
/// Panics if the counter did not add the Ignored label as part of
104+
/// its creation step.
105+
pub fn ignored(&self) {
106+
self.counter
107+
.get(&MetricEvents {
108+
label: LabelValues::Ignored,
109+
})
110+
.unwrap()
111+
.inc();
112+
}
100113
}
101114

102115
#[derive(Debug, Clone)]

fact/src/mount_info.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ pub struct MountEntry {
1818
pub struct MountInfo(HashMap<u32, Vec<MountEntry>>);
1919

2020
impl MountInfo {
21-
pub fn new() -> anyhow::Result<Self> {
22-
let cache = MountInfo::build_cache()?;
21+
pub fn new(paths: &[PathBuf]) -> anyhow::Result<Self> {
22+
let cache = MountInfo::build_cache(paths)?;
2323
Ok(MountInfo(cache))
2424
}
2525

26-
pub fn refresh(&mut self) -> anyhow::Result<()> {
27-
let cache = MountInfo::build_cache()?;
26+
pub fn refresh(&mut self, paths: &[PathBuf]) -> anyhow::Result<()> {
27+
let cache = MountInfo::build_cache(paths)?;
2828
self.0 = cache;
2929
Ok(())
3030
}
@@ -54,7 +54,7 @@ impl MountInfo {
5454
self.0.entry(k).or_default()
5555
}
5656

57-
fn build_cache() -> anyhow::Result<HashMap<u32, Vec<MountEntry>>> {
57+
fn build_cache(paths: &[PathBuf]) -> anyhow::Result<HashMap<u32, Vec<MountEntry>>> {
5858
let host_mount = host_info::get_host_mount();
5959
let path = PathBuf::from("/proc/self/mountinfo");
6060
if !path.exists() {
@@ -93,7 +93,14 @@ impl MountInfo {
9393
for i in mountinfo_it {
9494
let (dev, mountinfo) = i?;
9595
let entry: &mut Vec<MountEntry> = cache.entry(dev).or_default();
96-
if mountinfo.root != Path::new("/") && mountinfo.root != mountinfo.mount_point {
96+
97+
if mountinfo.root != Path::new("/")
98+
&& mountinfo.root != mountinfo.mount_point
99+
&& paths.iter().any(|monitored_path| {
100+
mountinfo.mount_point.starts_with(monitored_path)
101+
|| monitored_path.starts_with(&mountinfo.mount_point)
102+
})
103+
{
97104
entry.push(mountinfo);
98105
}
99106
}

0 commit comments

Comments
 (0)