fix: FeatureBPFFS / FeatureTraceFS verify filesystem type#32
Merged
Conversation
FeatureBPFFS / FeatureTraceFS verify filesystem type
The probe behind FeatureBPFFS and FeatureTraceFS used os.Stat + IsDir, returning Supported=true on any host where the directory existed. On modern systemd distros /sys/fs/bpf and /sys/kernel/tracing exist by default whether or not bpffs/tracefs is actually mounted, so callers gating on these features (e.g. before bpf_obj_pin) silently got a false positive and failed at I/O time. Switch the probe to Statfs + superblock magic comparison (BPF_FS_MAGIC, TRACEFS_MAGIC). Introduce a single internal checkMount helper with an injectable statfs implementation so unit tests can exercise all branches without privileged operations. Diagnostic-only fields SystemFeatures.DebugFS and .SecurityFS keep their previous presence-only semantics (no gated Feature* exists for them today).
237ed5f to
a06216e
Compare
leodido
added a commit
that referenced
this pull request
Apr 23, 2026
Introduces MountRequirement and RequireMount(path, magic) for gating on arbitrary filesystem mounts (path + superblock magic). Fills the gap where FeatureBPFFS / FeatureTraceFS are too restrictive: bpffs at a non-default path, cgroupv2, debugfs, tmpfs in tests, etc. Backed by the same internal checkMount helper introduced for the bug fix in #32, so there is a single Statfs implementation for both the preset features and the parameterized requirement. Tests cover three layers: Layer 1 (always-on, unprivileged): unit tests with the injected statfs fake exercise matching magic, mismatch, missing path, errno wrapping, dedup of identical {path, magic} pairs, and distinct pairs. Layer 2 (Linux integration job, root): a //go:build linux && integration test mounts a real tmpfs in t.TempDir() and asserts RequireMount agrees with the kernel's actual f_type. Skips politely when not root or sandboxed. Layer 3 (Linux integration job, root): a bats suite cross-checks CLI exit codes for 'check --require bpf-fs' / 'trace-fs' against the runner's real mount state via stat -f. A new 'integration' job in ci.yml runs the Layer 2 + Layer 3 tests on ubuntu-latest with sudo (runneradmin has CAP_SYS_ADMIN). The existing 'test' job is unchanged - the integration build tag is opt-in.
leodido
added a commit
that referenced
this pull request
May 3, 2026
Introduces MountRequirement and RequireMount(path, magic) for gating on arbitrary filesystem mounts (path + superblock magic). Fills the gap where FeatureBPFFS / FeatureTraceFS are too restrictive: bpffs at a non-default path, cgroupv2, debugfs, tmpfs in tests, etc. Backed by the same internal checkMount helper introduced for the bug fix in #32, so there is a single Statfs implementation for both the preset features and the parameterized requirement. Tests cover three layers: Layer 1 (always-on, unprivileged): unit tests with the injected statfs fake exercise matching magic, mismatch, missing path, errno wrapping, dedup of identical {path, magic} pairs, and distinct pairs. Layer 2 (Linux integration job, root): a //go:build linux && integration test mounts a real tmpfs in t.TempDir() and asserts RequireMount agrees with the kernel's actual f_type. Skips politely when not root or sandboxed. Layer 3 (Linux integration job, root): a bats suite cross-checks CLI exit codes for 'check --require bpf-fs' / 'trace-fs' against the runner's real mount state via stat -f. A new 'integration' job in ci.yml runs the Layer 2 + Layer 3 tests on ubuntu-latest with sudo (runneradmin has CAP_SYS_ADMIN). The existing 'test' job is unchanged - the integration build tag is opt-in.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The probe behind
FeatureBPFFSandFeatureTraceFSusedos.Stat+IsDir, returningSupported=trueon any host where the directory existed. On modern systemd distros/sys/fs/bpfand/sys/kernel/tracingexist by default whether or not the corresponding pseudo-filesystem is actually mounted, so callers gating on these features (e.g. beforebpf_obj_pin) silently got a false positive and failed at I/O time.A user that does:
would pass the check on a typical systemd box where
/sys/fs/bpfexists as a directory but bpffs is not mounted, then fail atbpf_obj_pin()with a confusing errno.Change
Switch the gated checks to
Statfs+ superblock magic comparison:FeatureBPFFSnow requiresunix.BPF_FS_MAGICat/sys/fs/bpf.FeatureTraceFSnow requiresunix.TRACEFS_MAGICat/sys/kernel/tracingor its legacy fallback/sys/kernel/debug/tracing.Single internal
checkMount(path, magic)helper backs both. An injectable package-levelstatfsfunction variable lets unit tests exercise every branch (matching magic, mismatch, missing path, syscall errno) without privileged operations.The diagnostic-only fields
SystemFeatures.DebugFSand.SecurityFSkeep their previous presence-only semantics — no gatedFeature*exists for them today, so directory-presence is sufficient.Notes
[Unreleased].Statfs_t.Typeis signed on some architectures; comparison casts touint32.RequireMount(path, magic)requirement on top of the samecheckMounthelper, plus integration tests against a real tmpfs mount in a new CI job.Verification
make build && make testgreen (-race -count=1).go vet ./...clean.caps_mount_test.gocovercheckMount,probeFilesystemMounted, andprobeFilesystemMountedAnyagainst a fakestatfsfor: matching magic, magic mismatch, missing path, syscall errno wrapping, primary/fallback path selection.