eBPF event pipeline with pluggable sources and sinks. Companion for this article about BPF.
- Python 3.12+
- uv
uv syncfrom sources.ebpf import EBPFEventSource
from sinks.kafka import KafkaEventSink
source = EBPFEventSource(bpf_prog=open("prog.c").read())
sink = KafkaEventSink(bootstrap_servers="localhost:9092", topic="events")
for event in source.events():
sink.write(event)uv run python -m pytest # tests
uv run python -m . # type check
uv run ruff format . # format
uv run ruff check . # lint- Detect Copy Fail 2: Electric Boogaloo — unprivileged LPE via xfrm ESP-in-UDP
MSG_SPLICE_PAGESno-COW fast path (same class as CVE-2026-31431). Sensor ideas:- kprobe
esp4_input/esp6_inputcorrelated with unprivileged UID - xfrm_user netlink socket activity from non-root userns
- auto-load of
esp4/xfrm_user/xfrm_algofrom unprivileged context - page-cache writes to
/etc/passwd(and other sensitive files) following ESP traffic on loopback
- kprobe
- Detect the Copy Fail class generically —
MSG_SPLICE_PAGES/splice()/sendfile()fast paths that bypass copy-on-write and let unprivileged writers reach page cache of read-only-mapped files. Sensor ideas:- kprobe
splice_to_pipe,iov_iter_extract_pages,skb_splice_from_iter,__splice_from_pipe— flag when source skb/iter originates from unprivileged socket and target inode is world-readable + root-owned - tracepoint on
MSG_SPLICE_PAGESflag insendmsg(sock_sendmsgkprobe, inspectmsg_flags) - correlate
mark_page_accessed/set_page_dirtyonaddress_spaceof sensitive inodes (/etc/passwd,/etc/shadow, suid binaries) with non-rootcurrent_uid() - LSM
file_permissiondeny-bypass: write-effect on inode without precedingvfs_write/vfs_writevfrom same task
- kprobe
- Detect tampering and privilege abuse around setuid binaries and credential files. Avoid alerting on bare
open(world-readable files = huge noise; open ≠ modify; misses page-cache writes that bypass VFS). Layered approach:- Credential-file tamper: kprobe
vfs_write/notify_change/ LSMsecurity_inode_setattron inode set{/etc/passwd, /etc/shadow, /etc/gshadow, /etc/sudoers, /etc/sudoers.d/*}withcurrent_uid() != 0→ high-signal alert. Match by(dev, ino)captured at boot, not path string (survives bind-mounts, distro variance). - Setuid exec: LSM
bprm_check_security(or kprobeexec_binprm) wherebinprm->file->f_inode->i_mode & (S_ISUID|S_ISGID). Log caller uid, target inode, argv[0]. Cheap inode-mode check, distro-independent. - Privilege transition: kretprobe
commit_creds, compareold->euidvsnew->euid. Flag non-root → root transitions; correlate with recent setuid-exec event for context. - Page-cache tamper (covers Copy Fail class): kprobe
set_page_dirty/mark_buffer_dirtywherepage->mapping->host∈ sensitive inode set and novfs_writefromcurrenttask in last N ms. CatchesMSG_SPLICE_PAGESno-COW writes that never hitfile_open/vfs_write. - Skip: open-only hooks, static path lists, parent-comm allowlists (rot under
systemd-run,tmux, container runtimes),(inode, pid)rate-limits (useless for one-shot exploits).
- Credential-file tamper: kprobe
MIT