ebpfsieve 0.1.0

Byte-frequency prefilter for read-heavy scanning pipelines with optional eBPF offload
Documentation

ebpfsieve

Byte-frequency prefilter for read-heavy scanning pipelines, with optional eBPF offload.

What it does

ebpfsieve slides a fixed-size window over byte streams and reports candidate windows where all required byte-count thresholds are met. The idea is to cheaply reject data before handing it to a more expensive verifier.

  • Userspace filtering — pure Rust, no dependencies on kernel features.
  • Lazy iterationmatching_windows_iter yields matches one at a time without allocating a Vec.
  • Chunked readers — attach the filter to any Read impl and get per-chunk candidate ranges with automatic carry-over across chunk boundaries.
  • Optional eBPF — on Linux with the right features enabled, compile and load classic BPF socket filters or aya-based fentry/vfs_read probes.

Quick start

use ebpfsieve::{ByteFrequencyFilter, ByteThreshold};

let filter = ByteFrequencyFilter::new([
    ByteThreshold::new(b'a', 3),
])?
.with_window_size(5)?;

let matches = filter.matching_windows(b"xyzaaaxyz");
assert_eq!(matches[0].offset, 1); // "yzaaa"

Filtering model

A ByteFrequencyFilter is built from one or more ByteThreshold values. A window matches when every threshold is satisfied. Counts are maintained in a u16 histogram with saturating arithmetic, so very long windows are safe from overflow.

Reading files in chunks

use ebpfsieve::{ByteFrequencyFilter, ByteThreshold};
use std::fs::File;

let filter = ByteFrequencyFilter::new([ByteThreshold::new(b'x', 2)])?
    .with_window_size(64)?
    .with_chunk_size(4096)?;

let mut file = File::open("data.bin")?;
let matches = filter.scan_file(&mut file, Some(1_000_000))?;

Lazy iteration

For internet-scale scanning, avoid collecting all matches into a Vec:

let filter = ByteFrequencyFilter::new([ByteThreshold::new(b'a', 1)])?;
let mut iter = filter.matching_windows_iter(b"banana");
if let Some(first) = iter.next() {
    println!("first match at offset {}", first.offset);
}

Optional features

  • serde — load filter rules from TOML with from_toml_str / from_toml_file.
  • socket-bpf — compile and load classic BPF_PROG_TYPE_SOCKET_FILTER programs via ebpfkit (Linux only).
  • kernel-bpf — load aya-based fentry/vfs_read probes (Linux ≥ 5.8, BTF, root required).

Errors

All fallible operations return ebpfsieve::Result<T>. Errors carry actionable messages, for example:

invalid filter configuration: window_size cannot be zero. Fix: provide a window_size of at least 1

License

MIT