FAN_OPEN_EXEC_PERM hands us the open and waits for an answer, so a binary can be refused before it runs. inotify could only report what had already happened. Verified end to end as root against a dedicated tmpfs (examples/ gate-smoke.rs, three phases): benign binary ran 7.2 ms EICAR binary blocked 1.8 ms never executed scanner stalled 5 s ran 1.6 s watchdog rescued 3 events The third phase is the one that matters. A gate that can hold a process forever is a machine-wedging bug wearing a feature's clothes, so the watchdog answers ALLOW for anything unanswered past DEADLINE and counts it. A missed detection is a bad day; a frozen machine ends the product. Two things this cost, both worth recording: * Scanning by re-opening the path deadlocks the daemon against itself. The open() lands on the watched mount and queues a permission event behind the one we are currently answering, and we cannot answer that one until we finish this one. Allowing our own pid does not help — the thread never gets back to the queue to apply the rule. The gate reads through the descriptor the kernel already handed it, with pread so the gated process still sees its own file offset. This is what hung the first smoke run. * The watchdog can only rescue events it has been told about, and it learns of them when the queue is drained. Scanning on the draining thread makes every event behind a slow scan invisible to the deadline. Reader and workers are therefore separate threads: the reader never blocks on a scan, so every event is registered within microseconds of arriving. Also: - ScanEngine::scan_bytes — the seam the gate needs, since it must never scan by path. Engines that cannot do it return None and simply are not usable behind the gate. - Settings gain exec_gate and exec_gate_paths, defaulting to OFF. It needs CAP_SYS_ADMIN and a root-filesystem mark holds every process on the box; that is not a default to ship before Phase 2 soak testing. - ABI constants are defined locally rather than taken from libc, so a version bump cannot quietly change what we ask the kernel for. 78 tests pass, up from 57. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
25 lines
530 B
TOML
25 lines
530 B
TOML
[workspace]
|
|
resolver = "2"
|
|
members = ["crates/*"]
|
|
|
|
[workspace.package]
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
license = "MIT"
|
|
repository = "https://git.joelovestech.com/Hound/Antivirus.git"
|
|
|
|
[workspace.dependencies]
|
|
anyhow = "1"
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
clap = { version = "4", features = ["derive"] }
|
|
colored = "2"
|
|
time = { version = "0.3", features = ["serde", "std", "formatting"] }
|
|
inotify = "0.10"
|
|
yara-x = "1.19"
|
|
libc = "0.2"
|
|
|
|
[profile.release]
|
|
lto = true
|
|
strip = true
|
|
codegen-units = 1
|