Skip to main content

Crate linprov_common

Crate linprov_common 

Source
Expand description

Types shared between the eBPF program (linprov-ebpf) and the userspace daemon (linprov). Everything here is repr(C) and Pod-friendly so it survives a round-trip through a ring buffer and a kernel xattr.

The crate compiles no_std by default (for the BPF target). Enable the user feature in userspace to pull in bytemuck::Pod / Zeroable derives on the wire types.

Wire shapes at a glance:

  • OriginRecord is what the daemon stores in the xattr and in the BPF INODE_MARKS map. BPF writes most of it in file_open; userspace augments creator_path from /proc/$pid/exe.
  • Event is the ringbuf record streamed from BPF to userspace.
  • AllowRule is one allowlist rule, packed into the BPF ALLOW_RULES array. String dims are stored as fnv_hash values so the BPF side can compare without carrying full byte arrays.
use linprov_common::{fnv_hash, dim};

// Both sides hash strings the same way; same input → same u64.
assert_eq!(fnv_hash("/usr/bin/curl"), fnv_hash("/usr/bin/curl"));
assert_ne!(fnv_hash("/usr/bin/curl"), fnv_hash("/usr/bin/wget"));

// Dimension bits are independent flags on AllowRule::flags.
let two_dim = dim::CREATOR_UID | dim::CREATOR_COMM;
assert_eq!(two_dim.count_ones(), 2);

Modules§

dim
flags bits on AllowRule. Set bits indicate which dims this rule requires the record / execve context to match.

Structs§

AllowRule
One allowlist rule. Set bits in flags mark required dims; the corresponding fields below are then compared against the record / execve context at enforce time. Cleared bits → field ignored.
Event
Ring-buffer record. Two kinds: NetworkFileOpen — informational; eBPF just wrote (or tried to write) the xattr. status is the kfunc return code. Execve — bprm_check fired AND the file already carried the mark. origin is the record we read back; status is unused.
OriginRecord
Provenance record. Carried in the security.bpf.linprov.origin xattr and in the INODE_MARKS storage map.

Constants§

COMM_LEN
CREATOR_PATH_LEN
EVENT_KIND_EXECVE
EVENT_KIND_NETWORK_FILE_OPEN
FNV_OFFSET
FNV_PRIME
MAX_FOLDER_HASHES
Max number of /-separated ancestor hashes we collect per filename for folder-rule matching. Each represents one ancestor directory (/, /opt/, /opt/installed/, …). Bounded so the verifier can reason about the rule-iteration loop and the inner folder match.
MAX_RULES
Maximum number of allowlist rules carried by the BPF Array map. Each rule check is ~30 ops + 2 folder lookups; the verifier walks the full bounded loop, so this caps the per-execve cost.
MODE_ENFORCE
MODE_OBSERVE
Runtime mode communicated to the eBPF program via the CONFIG map.
MODE_SOAK
ORIGIN_VERSION
Current schema version of OriginRecord. Records carrying a different version are treated as unmarked.
PATH_HASH_SCAN_LEN
Max path length the BPF FNV walks inspect (one for target_filename, one for landing_filename). Rules whose path-shaped values exceed this can’t possibly match — userspace rejects them at parse time.
PATH_LEN
XATTR_NAME

Functions§

fnv_hash
Hash a string with FNV-1a-64. Byte-by-byte, no trailing NUL, no padding — identical on the BPF and userspace sides.
fnv_hash_bytes
Same as fnv_hash, but takes a byte slice. Useful when the source isn’t UTF-8 (e.g., a [u8; PATH_LEN] filename buffer read out of a ringbuf event).