Drop unnecessary capabilities after BPF initialization#3450
Drop unnecessary capabilities after BPF initialization#3450robbycochran wants to merge 6 commits into
Conversation
After BPF programs are loaded and attached, collector no longer needs CAP_BPF, CAP_PERFMON, or CAP_SYS_RESOURCE. Drop all capabilities except CAP_SYS_PTRACE (needed for ongoing /proc scraping) immediately after InitKernel() succeeds. On kernels < 5.8 (RHEL 8), also keep CAP_SYS_ADMIN since the BPF subsystem may check it on runtime operations. This makes collector self-hardening regardless of how it is deployed — even with privileged:true, the process capability set is minimized before entering the event loop. libcap-ng was already linked but unused; this is the first actual use.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #3450 +/- ##
==========================================
+ Coverage 27.34% 27.37% +0.03%
==========================================
Files 95 96 +1
Lines 5420 5432 +12
Branches 2545 2551 +6
==========================================
+ Hits 1482 1487 +5
- Misses 3211 3214 +3
- Partials 727 731 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
Code audit of falcosecurity-libs found two runtime paths that may need BPF capabilities: 1. bpf_map_lookup_elem() in pman_get_scap_stats() — called periodically for metrics collection via CollectorStatsExporter 2. sinsp::restart_capture() — can re-attach BPF programs via bpf_program__attach() on SCAP_UNEXPECTED_BLOCK events Drop CAP_SYS_RESOURCE (only needed for RLIMIT_MEMLOCK at init) and all other capabilities not in the keep list. On kernel >= 5.8 keep SYS_PTRACE + BPF + PERFMON; on older kernels keep SYS_PTRACE + SYS_ADMIN. This still drops ~38 of 41 capabilities on modern kernels, eliminating NET_RAW, SYS_MODULE, DAC_OVERRIDE, CHOWN, FOWNER, MKNOD, SYS_RAWIO, and all other unneeded privileges.
Add DropCapabilities() utility in DropCapabilities.h and apply it at each thread entry point with only the capabilities that thread needs: - Main thread (event loop): BPF, PERFMON, SYS_PTRACE - CollectorStatsExporter: BPF (map lookups for metrics) - NetworkStatusNotifier: SYS_PTRACE (/proc reads) - SignalServiceClient: none (gRPC only) - ConfigLoader: none (inotify + yaml only) Uses CAPNG_SELECT_ALL to also clear the bounding set, preventing capability regain via execve. Based on prior work by Dmitrii Dolgov in PR #1908.
The main thread drops the bounding set (CAPNG_SELECT_ALL) which requires CAP_SETPCAP. After that, worker threads can no longer modify the bounding set. Fix by having only the main thread clear the bounding set (clear_bounding=true) while worker threads only modify effective + permitted (CAPNG_SELECT_CAPS).
|
/retest collector-on-push |
2 similar comments
|
/retest collector-on-push |
|
/retest collector-on-push |
Summary
Self-harden collector by dropping unnecessary Linux capabilities after BPF initialization, regardless of how it is deployed. Even with
privileged: true, the process capability set is minimized per-thread before entering the event loop.Based on prior work by @erthalion in #1908.
Per-thread capability model
RunService()CollectorStatsExporter::run()bpf_map_lookup_elem()for metricsNetworkStatusNotifier::Run()SignalServiceClient::EstablishGRPCStream()ConfigLoader::WatchFile()On kernels < 5.8 (RHEL 8), the main thread keeps SYS_ADMIN + SYS_PTRACE instead of BPF + PERFMON + SYS_PTRACE.
Implementation
DropCapabilities.h— single utility: clears all caps + bounding set viaCAPNG_SELECT_ALL, adds back only what is specifiedHostInfo::GetKernelVersion()for RHEL 8 fallbackWhat gets dropped (~38 of 41 capabilities)
NET_RAW, SYS_MODULE, DAC_OVERRIDE, CHOWN, FOWNER, KILL, SETUID, SETGID, NET_BIND_SERVICE, MKNOD, SYS_RAWIO, AUDIT_WRITE, SYS_RESOURCE, DAC_READ_SEARCH, NET_ADMIN, and all others not in the keep list above.
Differences from #1908
Companion to #3447 which reduces the deployment-side privileges.
Test plan