PATTERN Cited by 1 source
Approver / discarder filter¶
The approver / discarder filter is a named dual used in Datadog's Workload Protection FIM to do correct in-kernel pre-filtering against an evolving rule engine, despite eBPF verifier limits preventing the full rule logic from running in-kernel.
It combines two complementary filter sets stored in eBPF maps:
- Approvers — static, positive filters derived at rule compile time. "This specific value matches some rule's constant condition; forward it."
- Discarders — dynamic, negative filters learned at runtime by the rule engine. "This specific value will never match any active rule; drop it."
Together they approximate the full rule engine's decision boundary closely enough that ~94% of events are resolved in-kernel, with user-space handling only the ambiguous remainder.
How approvers are generated¶
At rule compile time, the rule engine inspects each predicate for concrete extractable values:
/etc/passwd is a concrete constant → added to the open.file.path
approver map. open.flags & O_CREAT > 0 is a bitmask predicate —
whether it yields an approver depends on the engine's handling of
flag fields.
When hundreds of rules each mention different fields and syscalls, "it quickly becomes a complex optimization problem" — the rule engine has to decide which fields to approve on (memory vs. coverage tradeoff).
Wildcards defeat approvers: open.file.path == "/etc/*" has no
concrete string to extract. That's what discarders are for.
How discarders are generated¶
At runtime, when the rule engine observes a value it has not
previously evaluated (e.g. a /tmp/foo file access under a ruleset
targeting /etc/*), it reasons:
Given the current active ruleset, can any rule ever match a value whose
open.file.pathlies under/tmp?
If no → /tmp (as a prefix, or some engine-specific encoding) is
loaded into a discarder LRU map. Future /tmp-prefixed events
are dropped in-kernel by the eBPF program.
The map is LRU deliberately — the working set of discarder keys grows with observed traffic but must stay bounded; least-recently- used entries age out, so only hot noise sources stay resident.
Correctness invariants¶
- Approvers must be a subset of "could match" — no false positives would be silently missed, but a false negative in an approver (a missed concrete value) just means that event follows the slow-path into user-space; no correctness issue.
- Discarders must be a strict subset of "can never match" — a bad discarder silently drops a would-match event → security blind spot. This invariant is what the rule engine's "non-trivial algorithms" protect.
- Rule changes invalidate prior discarders — the rule engine has to flush/rebuild the discarder map on ruleset change.
Generalization beyond FIM¶
The pattern is applicable whenever:
- A high-volume event stream must be matched against a rule engine.
- The full rule engine can't run at emit time (perf, safety, verifier limits).
- Rules are compilable into a mix of static constants (feeding approvers) and wildcard / pattern clauses (feeding discarder-style dynamic learning).
Examples elsewhere: tcpdump-style BPF filters (compile-time only; the approver half), XDP/L4 firewalls, sidecar sampling decisions, observability collector filters.
Seen in¶
- sources/2025-11-18-datadog-ebpf-fim-filtering — Datadog FIM's canonical use: approvers from compiled detection rules, discarders learned from runtime traffic, both stored in eBPF maps; ~94% of ~10B events/min resolved in-kernel.