Commit 553165c
Rewrite fstrace on eBPF (Rust + Aya) with full feature parity
Replace the C/ptrace implementation with an eBPF tracer written in Rust on
top of Aya. Tracing now happens in-kernel via fexit probes on the traced
syscalls plus sched_process_{fork,exec,exit} tracepoints and a ring buffer,
instead of stopping the target on every syscall from userspace. No features
are dropped: full syscall coverage, path resolution (cwd/dirfd/AT_FDCWD +
normalization), the fd->path cache, process-tree scoping, and exit/signal/
env passthrough are all preserved, alongside filters, debounce, and
per-process logging.
Architecture (privileged/unprivileged split)
- fstrace-daemon: the privileged half. Loads and attaches the embedded eBPF
object, owns the ring buffer and the traced-pid map, and serves multiple
clients over a Unix socket. It routes events purely by root-namespace pid,
so it works correctly from inside its own pid+mount namespace and needs no
--pid=host. When tracefs is absent (e.g. a scratch container) it mounts
tracefs itself before loading.
- fstrace: the unprivileged client. Runs as the invoking user with no sudo,
forks the target, registers it with the daemon, and streams reports on
fd 3. Exit code, signals, and environment are passed through untouched.
- fstrace-common: shared #[repr(C)] POD event structs and typed enums
(Syscall/AccessType/FileType) used by both the eBPF and userspace sides.
- fstrace-ebpf: the eBPF programs (fexit per traced syscall + fork/exec/exit
tracepoints writing into a ring buffer). The fork tracepoint's child_pid
offset is read from tracefs at load time rather than hardcoded, tracking
the ~6.16 __data_loc layout change.
Packaging & deployment
- systemd service + socket units (socket-activation friendly), a SysV
init.d script, and man pages for both binaries.
- A FROM-scratch Dockerfile for the fully static (musl, static-PIE) daemon;
bind-mount the socket dir + /sys/kernel/btf and run --privileged to trace
host commands across namespaces. Rootful runtime required (rootless cannot
create BPF maps).
- npm distribution package retained under node/fstrace.
Tooling & lifecycle (xtask)
- The entire repo lifecycle runs through `cargo xtask`: fmt, lint, test,
check, build, clean, dist (cross-compile), docker-build/docker-test, and
vm-test. All former shell scripts are ported to Rust.
- Cross-compilation for {x86_64, aarch64} x {gnu, musl} produces release
tarballs.
Testing
- Host-side unit tests cover path normalization, filters, debounce,
classification, and resolution.
- The privileged loader and full syscall coverage run end-to-end inside a
throwaway QEMU VM so eBPF never loads on the host. The harness (all Rust)
downloads prebuilt upstream kernels from the Ubuntu mainline archive,
builds an initramfs from a Docker image rootfs (Ubuntu and Alpine/musl),
and direct-boots QEMU, parsing a console result sentinel. A thin
fstrace-scenario binary issues the raw syscalls under trace. Coverage
includes 23 syscall/behavioural tests (incl. near-PATH_MAX paths,
multi-client isolation, passthrough), namespace isolation with a
containerized daemon, and systemd socket-activation.
Kernel support
- Verified across LTS {5.10, 5.15, 6.1, 6.6, 6.12, 6.18}, stable 7.1, and
mainline 7.2-rc. Feature floor is the ring buffer (5.8); 5.4 and older
lack it. Requirements and the support matrix are documented in
docs/kernel-support.md.
Docs
- README plus focused docs/ pages: architecture, building, testing,
deployment, reports-and-fd3, and kernel-support.
CI
- Three jobs, all driven by the cargo xtask alias: format/clippy/host tests,
a vm-e2e matrix (8 kernels x {ubuntu, alpine}), and a cross-dist matrix
(4 targets) uploading release tarballs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent a7a2b40 commit 553165c
69 files changed
Lines changed: 8920 additions & 3497 deletions
File tree
- .cargo
- .devcontainer
- .github/workflows
- .vscode
- docs
- fstrace-common
- src
- fstrace-ebpf
- src
- fstrace
- src
- bin
- node/fstrace
- packaging
- docker
- init.d
- man
- systemd
- src
- tests
- vmtest
- src
- xtask
- src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
| 5 | + | |
9 | 6 | | |
10 | 7 | | |
| 8 | + | |
11 | 9 | | |
12 | 10 | | |
13 | 11 | | |
14 | | - | |
15 | | - | |
| 12 | + | |
| 13 | + | |
16 | 14 | | |
17 | 15 | | |
18 | 16 | | |
19 | | - | |
| 17 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | | - | |
| 6 | + | |
| 7 | + | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
9 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
10 | 80 | | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
| 5 | + | |
| 6 | + | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
| 10 | + | |
| 11 | + | |
70 | 12 | | |
71 | 13 | | |
72 | 14 | | |
This file was deleted.
0 commit comments