Skip to content

Commit 26b043d

Browse files
authored
ROX-33199: unlink inode tracking (#429)
1 parent 24c1c22 commit 26b043d

File tree

6 files changed

+36
-5
lines changed

6 files changed

+36
-5
lines changed

fact-ebpf/src/bpf/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ int BPF_PROG(trace_path_unlink, struct path* dir, struct dentry* dentry) {
9494
return 0;
9595
}
9696

97+
// We only support files with one link for now
98+
inode_remove(&inode_key);
99+
97100
submit_unlink_event(&m->path_unlink,
98101
path->path,
99102
inode_to_submit,

fact/src/config/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,14 @@ impl TryFrom<Vec<Yaml>> for FactConfig {
209209
config.hotreload = Some(hotreload);
210210
}
211211
"scan_interval" => {
212+
// scan_internal == 0 disables the scanner
212213
if let Some(scan_interval) = v.as_f64() {
213-
if scan_interval <= 0.0 {
214+
if scan_interval < 0.0 {
214215
bail!("invalid scan_interval: {scan_interval}");
215216
}
216217
config.scan_interval = Some(Duration::from_secs_f64(scan_interval));
217218
} else if let Some(scan_interval) = v.as_i64() {
218-
if scan_interval <= 0 {
219+
if scan_interval < 0 {
219220
bail!("invalid scan_interval: {scan_interval}");
220221
}
221222
config.scan_interval = Some(Duration::from_secs(scan_interval as u64))

fact/src/config/tests.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,6 @@ paths:
465465
"scan_interval: true",
466466
"scan_interval field has incorrect type: Boolean(true)",
467467
),
468-
("scan_interval: 0", "invalid scan_interval: 0"),
469-
("scan_interval: 0.0", "invalid scan_interval: 0"),
470468
("scan_interval: -128", "invalid scan_interval: -128"),
471469
("scan_interval: -128.5", "invalid scan_interval: -128.5"),
472470
("unknown:", "Invalid field 'unknown' with value: Null"),

fact/src/event/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ impl Event {
130130
matches!(self.file, FileData::Creation(_))
131131
}
132132

133+
pub fn is_unlink(&self) -> bool {
134+
matches!(self.file, FileData::Unlink(_))
135+
}
136+
133137
/// Unwrap the inner FileData and return the inode that triggered
134138
/// the event.
135139
///

fact/src/host_scanner.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,19 @@ impl HostScanner {
220220
Ok(())
221221
}
222222

223+
/// Handle unlink events by removing the inode from the inode->path map.
224+
///
225+
/// The probe already cleared the kernel inode map.
226+
fn handle_unlink_event(&self, event: &Event) {
227+
let inode = event.get_inode();
228+
229+
if self.inode_map.borrow_mut().remove(inode).is_some() {
230+
self.metrics.scan_inc(ScanLabels::InodeRemoved);
231+
}
232+
233+
self.metrics.scan_inc(ScanLabels::FileRemoved);
234+
}
235+
223236
/// Periodically notify the host scanner main task that a scan needs
224237
/// to happen.
225238
///
@@ -246,8 +259,14 @@ impl HostScanner {
246259
}
247260

248261
pub fn start(mut self) -> JoinHandle<anyhow::Result<()>> {
262+
let scan_interval_value = *self.scan_interval.borrow();
249263
let scan_trigger = Arc::new(Notify::new());
250-
self.start_scan_notifier(scan_trigger.clone());
264+
265+
if scan_interval_value.is_zero() {
266+
warn!("Host scanner periodic scans permanently disabled (scan_interval is 0)");
267+
} else {
268+
self.start_scan_notifier(scan_trigger.clone());
269+
}
251270

252271
tokio::spawn(async move {
253272
info!("Starting host scanner...");
@@ -277,6 +296,11 @@ impl HostScanner {
277296
event.set_old_host_path(host_path);
278297
}
279298

299+
// Remove inode from the map
300+
if event.is_unlink() {
301+
self.handle_unlink_event(&event);
302+
}
303+
280304
let event = Arc::new(event);
281305
if let Err(e) = self.tx.send(event) {
282306
self.metrics.events.dropped();

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def fact_config(request, monitored_dir, logs_dir):
119119
'health_check': True,
120120
},
121121
'json': True,
122+
'scan_interval': 0,
122123
}
123124
config_file = NamedTemporaryFile(
124125
prefix='fact-config-', suffix='.yml', dir=cwd, mode='w')

0 commit comments

Comments
 (0)