Hello, On Tue, Oct 13, 2026 at 12:47 PM Aoife Moloney via devel-announce < [email protected]> wrote:
> Wiki - https://fedoraproject.org/wiki/Changes/UnprivilegedEBPFRBACDaemon > Discourse poll - > > https://discussion.fedoraproject.org/t/f46-change-proposal-unprivileged-ebpf-rbac-daemon-with-lsm-enforcement-and-rootless-access-system-wide/204731/2 > > This is a proposed Change for Fedora Linux. > This document represents a proposed Change. As part of the Changes > process, proposals are publicly announced in order to receive > community feedback. This proposal will only be implemented if approved > by the Fedora Engineering Steering Committee. > > > == Summary == > > Ship <code>bpf-rbacd</code>, a system daemon that enables > unprivileged, policy-controlled eBPF access in Fedora. It delegates > BPF privileges to containers via BPF tokens with in-kernel LSM > enforcement, and provides rootless BPF access to desktop users via > proxy execution — both governed by a single YAML policy and gated by > an <code>ebpf</code> system group. I don't see anything about integration with the linux audit system. Anything deciding access control or information flow decisions normally needs to be auditable. -Steve > == Owner == > > * Name: [[Fedora eBPF SIG|https://fedoraproject.org/wiki/SIGs/eBPF]] > * FAS group: [https://accounts.fedoraproject.org/group/ebpf-sig/ > @ebpf-sig] > * Email: [email protected] > * Members: > ** Daniel Mellado — [email protected] > ** Toke Høiland-Jørgensen — [email protected] > ** Viktor Malik — [email protected] > > > > == Detailed Description == > > === Background === > > eBPF is a powerful kernel technology for networking, observability, > and security, but its use requires system-wide capabilities > (<code>CAP_BPF</code> combined with <code>CAP_PERFMON</code>, > <code>CAP_NET_ADMIN</code>, or <code>CAP_SYS_ADMIN</code>). This is an > all-or-nothing proposition: applications need privileges close to > root, which blocks adoption in containers and restricts desktop > developers. > > The kernel's BPF token mechanism (Linux 6.9+) allows a privileged > issuer to delegate a constrained set of BPF operations to unprivileged > consumers inside user namespaces. However, tokens alone have two > significant limitations: > > # '''No per-entity enforcement.''' Token constraints are set at the > bpffs mount level and apply uniformly to all consumers. There is no > mechanism to give different containers different allowed program > types, or to revoke access dynamically. > # '''No desktop path.''' BPF tokens are not supported in the initial > user namespace (<code>BPF_TOKEN_CREATE</code> returns > <code>EOPNOTSUPP</code>). Desktop developers running tracers or > profilers must still use <code>sudo</code>. > > This change addresses both gaps through a single daemon that operates > in two complementary modes simultaneously. > > === Dual-mode architecture === > > <code>bpf-rbacd</code> serves two distinct classes of eBPF consumers > from a single process, using the same policy engine and the same YAML > configuration: > > {| class="wikitable" > ! Mode !! Target environment !! Mechanism !! LSM enforcement > |- > | '''Capability granting''' || Containers and services in user > namespaces || BPF token delegation via bpffs mount + "nsenter dance" > || Yes — three LSM hooks enforce per-namespace policy bitmaps > in-kernel > |- > | '''Proxy execution''' || Desktop users and applications in the > initial user namespace (<code>init_user_ns</code>) || Daemon executes > <code>bpf()</code> on behalf of clients, passes FDs via > <code>SCM_RIGHTS</code> over a Unix socket || N/A — policy enforced > daemon-side before executing the syscall > |} > > '''Why two modes?''' BPF tokens only work inside user namespaces — the > kernel explicitly rejects <code>BPF_TOKEN_CREATE</code> in > <code>init_user_ns</code> with <code>EOPNOTSUPP</code>. Containers > naturally have user namespaces, so tokens are the right mechanism > there. Desktop users do not, so they need a different path. The proxy > mode fills that gap without requiring application changes: standard > tools like bpftrace or bcc can be adapted to request FDs from the > daemon instead of calling <code>bpf()</code> directly. > > Both modes share the same policy model (allow-list only, fails closed, > system-policy intersection) and the same group-based role resolution > (<code>ebpf</code>, <code>ebpf-net</code>, <code>ebpf-admin</code>). > An administrator writes one policy file and both modes obey it. > > <pre> > bpf-rbacd (privileged daemon) > ┌──────────────────────────────┐ > │ Policy Engine │ > │ (YAML → role → bitmaps) │ > └──────┬───────────┬────────────┘ > │ │ > ┌───────────▼──┐ ┌────▼──────────────┐ > │ Capability │ │ Proxy execution │ > │ granting │ │ (SCM_RIGHTS) │ > │ mode │ │ mode │ > └──────┬───────┘ └────┬───────────────┘ > │ │ > ┌───────────▼──┐ ┌────────▼────────────┐ > │ Container / │ │ Desktop user │ > │ service in │ │ (init_user_ns) │ > │ user ns │ │ │ > │ │ │ $ bpf-rbac create-map│ > │ Uses BPF │ │ → daemon executes │ > │ token from │ │ → FD passed back │ > │ bpffs │ │ via SCM_RIGHTS │ > │ ↓ │ └──────────────────────┘ > │ LSM enforces │ > │ per-ns policy│ > └──────────────┘ > </pre> > > === What this change delivers === > > ==== BPF token delegation and the ebpf system group ==== > > <code>bpf-rbacd</code> uses systemd-driven bpffs delegation to provide > BPF tokens to containers and services in user namespaces: > > * A fixed <code>ebpf</code> system group gates who may consume the > delegated bpffs/token path. The group is for OS-level discovery and > packaging defaults; the kernel still enforces token constraints > independently. > * The daemon performs the '''"nsenter dance"''' — entering the target > user namespace via <code>setns()</code> before mounting bpffs, so the > <code>s_user_ns</code> is set correctly and > <code>BPF_TOKEN_CREATE</code> works inside the namespace. > * Integration with systemd <code>PrivateBPF=</code> (upstream > [https://github.com/systemd/systemd/pull/36134 PR #36134]) enables > automatic namespace delegation for systemd-managed services. > * Libraries such as libbpf, bpftool, and bcc automatically discover > and use delegated tokens without requiring <code>sudo</code>. > > ==== In-kernel eBPF LSM policy enforcement ==== > > The daemon loads eBPF LSM programs at startup that attach to the > kernel's security hooks for BPF operations. Each hook looks up the > calling process's user namespace inode ID in an eBPF hash map, > retrieves the policy bitmaps for that namespace's role, and returns > allow or deny. This gives administrators '''per-namespace, per-role > granularity''' enforced in-kernel, on top of the bpffs mount-level > token constraints. > > '''Core hooks''' (implemented in both the Aya and C codebases): > > {| class="wikitable" > ! LSM Hook !! What it controls !! Policy dimension > |- > | <code>security_bpf</code> || Every <code>bpf()</code> syscall > invocation || <code>allowed_cmds</code> bitmap (PROG_LOAD, MAP_CREATE, > etc.) > |- > | <code>security_bpf_prog_load</code> || Program loading — inspects > program type || <code>allowed_prog_types</code> bitmap (kprobe, xdp, > etc.) > |- > | <code>security_bpf_map_create</code> || Map creation — inspects map > type || <code>allowed_map_types</code> bitmap (hash, array, etc.) > |} > > '''Extended hooks''' (implemented in the C codebase — > [https://github.com/tohojo/bpf-rbac-lsm tohojo/bpf-rbac-lsm]): > > {| class="wikitable" > ! LSM Hook !! What it controls !! Why it matters > |- > | <code>security_bpf_prog</code> || FD-level access to existing > programs || Controls who can inspect or reuse loaded programs > |- > | <code>security_mmap</code> || Memory-mapping of BPF maps || Controls > map data access mode (read/write/exec) > |} > > '''Bytecode walking for helper/kfunc policy:''' The C implementation > also uses open-coded iterators to walk BPF program bytecode at > <code>security_bpf_prog_load</code> time, extracting the helper > function IDs and kfunc BTF IDs that the program calls. This enables a > future policy dimension: restricting ''which kernel functions'' a > program may invoke, not just which program type it is. Events are > reported to userspace via a BPF ring buffer for audit logging and > policy decisions. > > '''How LSM and tokens complement each other:''' > > <pre> > Token says "you may load LSM checks: "your namespace > kprobe programs" role only permits tracepoint" > ↓ → DENIED > </pre> > > Even if a token is overly permissive (broad bpffs mount options), the > per-namespace LSM policy restricts actual operations to the role's > intersection with the system policy. > > '''eBPF program loading at daemon startup:''' The daemon loads and > attaches the LSM programs before accepting any delegation requests. > This requires <code>CAP_BPF</code> + <code>CAP_SYS_ADMIN</code> on the > daemon itself (granted via the systemd unit's > <code>AmbientCapabilities</code>). Once loaded, the LSM hooks are > active system-wide; the eBPF policy map serves as the control plane > between the daemon and the LSM. > > ==== Rootless BPF for desktop users (proxy mode) ==== > > For users in the initial user namespace (desktops, developer > workstations), <code>bpf-rbacd</code> provides a proxy execution mode: > > # User runs <code>bpf-rbac <command></code> (e.g., <code>bpf-rbac > create-map --type hash ...</code>) > # The CLI connects to the daemon's Unix socket at > <code>/run/bpf-rbac.sock</code> > # The daemon reads <code>SO_PEERCRED</code> — kernel-verified, > tamper-proof credentials > # Group membership is resolved to a policy role > # The daemon executes the allowed <code>bpf()</code> syscall with its > own privileges > # Resulting file descriptors are passed back via <code>SCM_RIGHTS</code> > # Denied operations return actionable error messages > > === Policy model === > > Policies are defined in <code>/etc/bpf-rbac/policy.yaml</code> using > an allow-list model that always fails closed: > > <pre> > system_policy: # System-wide ceiling > commands: [PROG_LOAD, MAP_CREATE, MAP_LOOKUP_ELEM, MAP_UPDATE_ELEM, > LINK_CREATE, OBJ_PIN, OBJ_GET, BTF_LOAD] > prog_types: > kprobe: [load, attach, detach] > tracepoint: [load, attach, detach] > xdp: [load, attach, detach] > map_types: > hash: [create, read, write] > array: [create, read, write] > ringbuf: [create, read] > > roles: > ebpf: # Tracing role > groups: [ebpf] > commands: [PROG_LOAD, MAP_CREATE, MAP_LOOKUP_ELEM, MAP_UPDATE_ELEM, > LINK_CREATE, BTF_LOAD] > prog_types: > kprobe: [load, attach] > tracepoint: [load, attach] > map_types: > hash: [create, read, write] > array: [create, read, write] > ringbuf: [create, read] > > ebpf-net: # Networking role > groups: [ebpf-net] > prog_types: > xdp: [load, attach, detach] > sched_cls: [load, attach, detach] > map_types: > hash: [create, read, write] > devmap: [create, read, write] > > ebpf-admin: # Unrestricted > groups: [ebpf-admin, wheel] > commands: [any] > prog_types: {any: [any]} > map_types: {any: [any]} > </pre> > > The effective policy for any role is the '''set intersection''' of the > role policy and the system policy. A role can never exceed > administrator-defined system limits. > > === Two LSM implementations and the Rust BPF toolchain gap === > > The eBPF LSM programs exist in two parallel implementations. This is > not redundancy — it is a deliberate response to a Rust compiler > limitation that currently prevents the Aya-based implementation from > using advanced BPF features. > > ==== The Rust/DWARF/BTF problem ==== > > eBPF programs that call kernel functions (kfuncs) or reference kernel > symbols (ksyms) require BTF (BPF Type Format) metadata in the compiled > ELF. The toolchain flow is: > > <pre> > Rust source → rustc (BPF target) → LLVM → ELF with DWARF > → bpf-linker → ELF with BTF (including .ksyms DATASEC) > → kernel verifier resolves kfuncs/ksyms at load time > </pre> > > The problem: '''<code>rustc</code> does not emit DWARF debug info for > <code>extern</code> declarations on BPF targets.''' When a Rust eBPF > program declares: > > <pre> > #[link_section = ".ksyms"] > extern "C" { > static LINUX_KERNEL_VERSION: u32; // ksym > fn bpf_iter_num_new(it: *mut bpf_iter_num, start: i32, end: i32); // > kfunc > } > </pre> > > …the compiler produces the LLVM global/function declaration but > attaches no <code>DIGlobalVariable</code> or <code>DISubprogram</code> > metadata. Without DWARF, <code>bpf-linker</code> cannot generate the > <code>.ksyms</code> BTF DATASEC entry, and the kernel verifier cannot > resolve these symbols at load time. The program fails to load. > > This blocks: > * '''Open-coded iterators''' > (<code>bpf_iter_num_new/next/destroy</code>) — needed for bytecode > walking in the <code>security_bpf_prog_load</code> hook > * '''kfunc calls''' (<code>bpf_task_acquire</code>, etc.) — needed for > CO-RE task/namespace introspection > * '''The userns ID resolver''' — > <code>current->nsproxy->user_ns->ns.inum</code> access via BTF, > currently stubbed to return 0 > > The three core bitmap-based hooks (<code>security_bpf</code>, > <code>security_bpf_prog_load</code>, > <code>security_bpf_map_create</code>) work today with Aya because they > only use map lookups and context argument reads — no kfuncs or ksyms. > But the extended hooks (bytecode walking, FD access control, mmap > control) require kfuncs and are blocked. > > ==== The upstream Rust compiler fix ==== > > We are driving the fix in > [https://github.com/rust-lang/rust/pull/161390 rust-lang/rust#161390] > ("Generate debug info for BPF extern declarations"). This patch: > > * Allows <code>#[link_section]</code> on <code>ForeignStatic</code> > and <code>ForeignFn</code> (gated to BPF targets) > * Adds an <code>LLVMRustDIBuilderCreateGlobalVariableExpression</code> > wrapper exposing the <code>isDefinition</code> parameter (the LLVM-C > API hard-codes it to <code>true</code>) > * Emits <code>DIGlobalVariable</code> with <code>isDefinition: > false</code> for extern statics > * Emits <code>DISubprogram</code> without > <code>SPFlagDefinition</code> for extern functions > > This is a reworked version of > [https://github.com/rust-lang/rust/pull/152899 #152899], rebased on > current <code>main</code> with review feedback addressed. It is > currently in review with the Rust compiler team (assigned to > @jdonszelmann, reviews from @bjorn3 and @tamird). The Aya maintainer > (@vadorovsky) is also involved. > > Once this lands in nightly <code>rustc</code>, the full chain works: > Rust eBPF → DWARF with extern metadata → <code>bpf-linker</code> → BTF > with <code>.ksyms</code> → kernel loads kfuncs. This unblocks the > complete Aya-based LSM. > > ==== The C implementation: tohojo/bpf-rbac-lsm ==== > > [https://github.com/tohojo/bpf-rbac-lsm tohojo/bpf-rbac-lsm] is an > actively developed C-based LSM implementation (Toke Høiland-Jørgensen, > latest commits Sep 2026) that sidesteps the Rust toolchain limitation > entirely. It uses: > > * '''C for the eBPF programs''' — compiled with clang/llvm, full > BTF/CO-RE support, no DWARF issues > * '''Rust + libbpf-rs for userspace''' — loads the C eBPF programs via > libbpf skeleton generation, processes ring buffer events, manages > policies > > This implementation is more capable than the Aya version today: > > {| class="wikitable" > ! Feature !! Aya (Rust eBPF) !! C eBPF + libbpf-rs > |- > | <code>security_bpf</code> (command filtering) || ✅ || ✅ > |- > | <code>security_bpf_prog_load</code> (type filtering) || ✅ || ✅ > |- > | <code>security_bpf_map_create</code> (type filtering) || ✅ || ✅ > |- > | <code>security_bpf_prog</code> (FD access) || ❌ || ✅ > |- > | <code>security_mmap</code> (map mmap control) || ❌ || ✅ > |- > | Userns ID resolution (CO-RE/BTF) || ❌ (stubbed) || ✅ > |- > | Bytecode walking (open-coded iterators) || ❌ (blocked on rustc) || ✅ > |- > | Helper/kfunc ID extraction || ❌ (blocked on rustc) || ✅ > |- > | Policy enforcement per namespace || ❌ (stub returns 0) || ✅ > |- > | Ring buffer event reporting || ❌ || ✅ > |} > > ==== Integration strategy and the path to a pure Rust/Aya stack ==== > > The two implementations share the same userspace daemon > (<code>bpf-rbacd</code>) and the same policy engine. They are designed > to converge: > > '''Phase 1 — Fedora 46 delivery (C eBPF + Rust userspace):''' > > Use the C eBPF programs from <code>bpf-rbac-lsm</code> loaded via > <code>libbpf-rs</code> in the <code>bpf-rbacd</code> Rust userspace > daemon. This gives us the full feature set (all hooks, bytecode > walking, namespace resolution, policy enforcement) without waiting for > the Rust compiler fix. The daemon, policy engine, CLI, and all > userspace logic remain in Rust; only the eBPF kernel programs are in > C. This is a pragmatic split — the same pattern used by many > production eBPF projects (e.g., Cilium, bpfman). > > '''Phase 2 — After <code>rustc</code> fix lands (Aya catches up):''' > > Once [https://github.com/rust-lang/rust/pull/161390 > rust-lang/rust#161390] is merged and reaches stable > <code>rustc</code>, we migrate the eBPF programs to Rust/Aya. The > groundwork is already done: > > * The Aya-based LSM in [https://github.com/danielmellado/bpf-rbacd > danielmellado/bpf-rbacd > <https://github.com/danielmellado/bpf-rbacddanielmellado/bpf-rbacd>] > already compiles and produces correct ELF > relocations for the three core hooks. > * The [https://github.com/tohojo/bpf-rbacd/tree/load-lsm load-lsm > branch] already has kfunc declarations and open-coded iterator code > that compiles — it only needs the BTF DATASEC generation that the > <code>rustc</code> fix enables. > * Aya's kfunc relocation support > ([https://github.com/aya-rs/aya/pull/1372 aya-rs/aya#1372]) is > progressing upstream. > > The migration is a drop-in replacement: the userspace daemon, policy > engine, and CLI are unchanged. Only the eBPF binary source changes > from C to Rust. > > '''Phase 3 — Target state (pure Rust):''' > > A fully Rust stack — daemon, CLI, policy engine, ''and'' eBPF kernel > programs — all built with <code>cargo</code>. This is the desired end > state for <code>bpf-rbacd</code> because: > > * '''Single toolchain:''' One <code>cargo build</code> compiles > everything. No separate clang/llvm dependency for the eBPF programs. > * '''Shared types:''' The <code>bpf-rbacd-common</code> crate already > defines <code>#[repr(C)]</code> policy types (<code>PolicyKey</code>, > <code>PolicyValue</code>) that compile for both <code>no_std</code> > (eBPF target) and <code>std</code> (userspace). With Aya, these types > are shared at compile time with full type safety — no manual struct > layout synchronization between C and Rust. > * '''Memory safety:''' Rust's borrow checker and type system apply to > the eBPF programs too. While eBPF's verifier provides runtime safety, > compile-time guarantees from Rust catch bugs earlier. > * '''Ecosystem alignment:''' Aya is the standard Rust eBPF framework. > Contributing improvements back (kfunc support, LSM patterns) benefits > the entire Rust eBPF community. > > The <code>rustc</code> fix is not just a <code>bpf-rbacd</code> > concern — it unblocks kfunc/ksym usage for ''every'' Rust eBPF > program. We are driving this upstream because it is the right thing > for the ecosystem, and <code>bpf-rbacd</code> is a concrete, > high-profile consumer that validates the fix. > > This phased approach means the Fedora 46 deliverable is '''not blocked > by the Rust compiler fix''', while the Rust/Aya migration remains a > first-class goal tracked by the eBPF SIG. > > === Kernel requirements === > > {| class="wikitable" > ! Config !! Required for !! In Fedora? > |- > | <code>CONFIG_BPF_SYSCALL=y</code> || All BPF operations || Yes > |- > | <code>CONFIG_BPF_LSM=y</code> || LSM hook attachment || Yes > |- > | <code>bpf</code> in active LSM list || LSM program loading || Needs > verification > |- > | <code>CONFIG_DEBUG_INFO_BTF=y</code> || CO-RE/BTF for portable eBPF || > Yes > |- > | <code>CONFIG_BPF_TOKEN</code> || BPF token delegation || Yes > |} > > '''Action item:''' Verify that <code>bpf</code> is in the kernel's > compiled-in LSM list or <code>lsm=</code> boot parameter. If not, a > kernel config change is needed to add <code>bpf</code> to the LSM > order alongside <code>lockdown,yama,integrity,selinux</code>. > > == Feedback == > > The design of <code>bpf-rbacd</code> is being presented at > [https://lpc.events/event/20/contributions/2441/ Linux Plumbers > Conference 2026] (Oct 6, eBPF Track) to solicit community feedback. > The talk covers the architecture, policy model, and LSM enforcement, > with the goal of making the design useful to other distributions and > operators. > > Community consultation with kernel, systemd, and security stakeholders > is ongoing. > > == Benefit to Fedora == > > * '''Security posture:''' Moves eBPF access from all-or-nothing > capabilities toward granular, role-based delegation. LSM enforcement > adds a mandatory kernel-level policy layer that token delegation alone > cannot provide. > * '''Per-entity granularity:''' Different containers, services, or > users get different eBPF permissions based on their role — not a > single system-wide delegation. > * '''Developer experience:''' Desktop developers and operators can run > eBPF tools without <code>sudo</code>, with clear errors when an > operation is outside their role's policy. > * '''Unified policy:''' One YAML file governs both container (LSM + > tokens) and desktop (proxy) access. Administrators learn one model. > * '''Dynamic policy and revocation:''' Policies can be updated at > runtime; removing a namespace's map entry causes the LSM to deny > subsequent operations without killing processes. > * '''Downstream alignment:''' Establishes the reference RBAC > implementation for RHEL, OpenShift (user namespaces GA in 4.21+), and > CoreOS. Kubernetes user namespaces are GA as of v1.36. > * '''Rust BPF ecosystem:''' The upstream <code>rustc</code> fix > ([https://github.com/rust-lang/rust/pull/161390 #161390]) benefits the > entire Rust eBPF community. <code>bpf-rbacd</code> is designed to > become a fully pure-Rust eBPF project (daemon + kernel programs via > Aya) once the toolchain gap is closed, demonstrating that production > eBPF LSM programs can be written entirely in Rust. > * '''Community leadership:''' Fedora becomes the first distribution > with a complete, integrated eBPF RBAC stack spanning containers and > desktops. > > == Scope == > > * Proposal owners: > ** Package <code>bpf-rbacd</code> (daemon), <code>bpf-rbac</code> (CLI > client), and <code>bpf-rbacd-common</code> (shared types) as RPMs. > Source is hosted on [https://forge.fedoraproject.org/ebpf/bpf-rbacd > Fedora Forge]. > ** Ship the eBPF LSM programs from > [https://github.com/tohojo/bpf-rbac-lsm tohojo/bpf-rbac-lsm] (C eBPF + > libbpf-rs for loading). Migrate to Rust/Aya once > [https://github.com/rust-lang/rust/pull/161390 rust-lang/rust#161390] > lands. > ** Deliver systemd unit (<code>bpf-rbacd.service</code>) with security > hardening (<code>ProtectSystem=strict</code>, > <code>ProtectHome=true</code>, capability bounding). > ** Deliver default policy (<code>/etc/bpf-rbac/policy.yaml</code>) > reviewed with the Security Team. > ** Create <code>ebpf</code>, <code>ebpf-net</code>, and > <code>ebpf-admin</code> system groups via > <code>systemd-sysusers</code>. > ** Implement systemd-driven bpffs delegation (mount units, > <code>PrivateBPF=</code> coordination). > ** Coordinate with kernel team to ensure <code>bpf</code> is in the > active LSM list. > ** Drive the Rust compiler fix > ([https://github.com/rust-lang/rust/pull/161390 > rust-lang/rust#161390]) or use C fallback. > ** Complete the CO-RE/BTF userns ID resolver in the eBPF LSM. > ** Wire container/namespace discovery into the daemon (cgroup events > or CRI hooks). > ** Coordinate library/tool updates for automatic token usage (libbpf, > bpftool, bcc). > ** File Fedora package review, FESCo process, and tracker bugs. > ** Write Fedora Quick Docs article on usage and security model. > > * Other developers: > ** Kernel maintainers: Confirm <code>CONFIG_BPF_LSM=y</code> and > <code>bpf</code> in LSM list; advise on LSM hook semantics and > regression triage. > ** systemd maintainers: Coordinate on <code>PrivateBPF=</code> > integration so systemd-launched services automatically get delegated > namespaces. > ** Rust compiler team: Review and land > [https://github.com/rust-lang/rust/pull/161390 rust-lang/rust#161390]. > ** Aya maintainers: kfunc relocation support > ([https://github.com/aya-rs/aya/pull/1372 aya-rs/aya#1372]). > ** Security Team: Review default policy, group membership model, and > LSM enforcement guarantees. > ** eBPF tooling maintainers (bcc, bpftool, libbpf consumers): Ensure > tools work with proxy-mode FD passing and token-based flows. > ** Container runtime maintainers (podman, CRI-O): Test user namespace > + BPF token + LSM enforcement end-to-end. > ** Edition WGs (Workstation, Server, CoreOS): Consider default group > membership and documentation per edition. > > * Release engineering: No release engineering changes required. > <code>bpf-rbacd</code> is a new opt-in package with standard RPM > packaging — no mass rebuild, no installer image changes, and no > compose modifications. > > * Policies and guidelines: The initial delivery uses C eBPF programs > compiled with clang/llvm and loaded via libbpf-rs — this follows > standard Fedora packaging (clang and libbpf are already packaged). The > future Aya-based path targets <code>bpfel-unknown-none</code> and > requires nightly Rust + <code>rust-src</code>, which may need a > packaging exemption or pre-built binary vendoring when that migration > occurs. Default policy requires Security Team review. > > * Trademark approval: N/A (not needed for this Change) > > * Alignment with the Fedora Strategy: Aligns with secure-by-default, > developer-friendly platform, and upstream-first goals. The change > drives fixes in <code>rustc</code>, Aya, and systemd rather than > carrying downstream patches. > > == Upgrade/compatibility impact == > > This change introduces a new opt-in package. It does not modify > existing system behavior. > > * '''Existing systems:''' No change unless <code>bpf-rbacd</code> is > installed. Workflows that use root or explicit capabilities continue > to work. > * '''New path:''' Users or administrators who want unprivileged eBPF > install <code>bpf-rbacd</code>, add users to the <code>ebpf</code>, > <code>ebpf-net</code>, or <code>ebpf-admin</code> groups, and enable > the service. > * '''Kernel config:''' If <code>bpf</code> needs to be added to the > LSM list, this could interact with other LSM consumers (notably > SELinux). Must be coordinated with the kernel team. > * '''ABI:''' No Fedora-specific ABI commitment beyond documented > <code>bpf()</code> semantics and the policy YAML format. Tools that > gain automatic token discovery may succeed in situations where they > previously failed without sudo. > > == Early Testing (Optional) == > > Do you require 'QA Blueprint' support? N > > == How To Test == > > # '''Hardware/data:''' Standard x86_64 or aarch64 Fedora install. VM > acceptable if BPF features are not stripped. > # '''Prepare:''' Install <code>bpf-rbacd</code>, start the service, > add test user to <code>ebpf</code> group. > # '''Proxy mode (desktop):''' > #: <pre> > # As a user in the ebpf group: > $ bpf-rbac status > Connected to: /run/bpf-rbac.sock > Your roles: ebpf > Allowed operations: > Maps: hash, array, percpu_hash, percpu_array, ringbuf > Programs: kprobe, uprobe, tracepoint, perf_event > > # Create a map (should succeed) > $ bpf-rbac create-map --type hash --name test \ > --key-size 4 --value-size 8 --max-entries 64 > > # Attempt a denied operation (should fail with clear error) > $ bpf-rbac create-map --type devmap --name test \ > --key-size 4 --value-size 8 --max-entries 64 > Error: map type 'devmap' is not allowed by your role 'ebpf' > </pre> > # '''LSM enforcement (requires root for setup):''' Launch a podman > container in a user namespace (<code>podman run --userns=auto > ...</code>). Verify that the daemon delegates bpffs and populates the > policy map. Inside the container, attempt to load an allowed program > type (should succeed) and a denied type (should fail with > <code>EPERM</code>). > # '''Non-member:''' As a user NOT in any ebpf group, verify that all > operations are denied. > # '''Unit tests (no root required):''' > #: <pre> > cargo test --lib # Policy parsing, bitmaps, intersection > cargo test --test integration # Non-privileged integration tests > </pre> > # '''Expected results:''' Delegated operations succeed within the > role's allowlist; out-of-scope operations fail with clear errors; no > system instability or privilege escalation beyond the documented > policy. > > == User Experience == > > * Most users see no change unless they use eBPF tooling. > * Desktop developers who run tracers or networking experiments may > stop needing <code>sudo</code> for supported scenarios, with clear > errors when an operation is denied. > * Container workloads are transparent — applications use standard > <code>bpf()</code> with automatic token acquisition; the LSM silently > enforces the namespace's policy. > * Administrators get a single documented policy file > (<code>/etc/bpf-rbac/policy.yaml</code>) and <code>journalctl -u > bpf-rbacd</code> for audit logging. > > == Dependencies == > > * Linux kernel: 6.9+ with <code>CONFIG_BPF_TOKEN</code>, > <code>CONFIG_BPF_LSM=y</code>, <code>bpf</code> in active LSM list, > <code>CONFIG_DEBUG_INFO_BTF=y</code> > * Rust: Stable 1.85+ (daemon and CLI) > * [https://github.com/libbpf/libbpf libbpf] and > [https://github.com/libbpf/libbpf-rs libbpf-rs]: For loading C-based > eBPF LSM programs from the Rust daemon (initial delivery path) > * clang/llvm: For compiling the C eBPF programs with full BTF/CO-RE support > * [https://github.com/aya-rs/aya Aya]: eBPF library for Rust > (long-term target once [https://github.com/rust-lang/rust/pull/161390 > rust-lang/rust#161390 > <https://github.com/rust-lang/rust/pull/161390rust-lang/rust#161390>] > lands; requires nightly Rust + > <code>bpfel-unknown-none</code> target) > * systemd: <code>PrivateBPF=</code> support > ([https://github.com/systemd/systemd/pull/36134 PR #36134]) > * Optional: podman with <code>--userns=auto</code>, CRI-O with user > namespace support > > == Contingency Plan == > > * Contingency mechanism: > ** The primary delivery path already uses the C eBPF programs (via > libbpf-rs), so the Rust compiler fix > ([https://github.com/rust-lang/rust/pull/161390 > rust-lang/rust#161390]) is not on the critical path for F46. > ** If BPF LSM cannot be enabled in the Fedora kernel (e.g., SELinux > interaction with <code>bpf</code> in the LSM list): disable LSM > loading in <code>bpf-rbacd</code>; ship proxy mode only and rely on > token-level constraints for container workloads. > ** If proxy mode has unresolved security concerns: ship LSM/container > path only; desktop users fall back to > <code>sudo</code>/<code>CAP_BPF</code>. > ** If neither component is ready: do not ship <code>bpf-rbacd</code>. > eBPF access continues to work as it does today (privileged only). No > regression. > * Contingency deadline: Beta freeze > * Blocks release? No. <code>bpf-rbacd</code> is an opt-in package. > > == Documentation == > > * Upstream code: [https://forge.fedoraproject.org/ebpf/bpf-rbacd > Fedora Forge ebpf/bpf-rbacd] (primary), > [https://github.com/danielmellado/bpf-rbacd GitHub mirror] > * C reference implementation: [https://github.com/tohojo/bpf-rbac-lsm > tohojo/bpf-rbac-lsm > <https://github.com/tohojo/bpf-rbac-lsmtohojo/bpf-rbac-lsm>] > * Rust compiler fix: [https://github.com/rust-lang/rust/pull/161390 > rust-lang/rust#161390 > <https://github.com/rust-lang/rust/pull/161390rust-lang/rust#161390>] > * Kernel docs: [https://docs.kernel.org/bpf/bpf_token.html BPF Token > documentation] > * systemd: [https://github.com/systemd/systemd/pull/36134 PrivateBPF= PR] > * LPC 2026 talk: [https://lpc.events/event/20/contributions/2441/ > BPF-RBACd <https://lpc.events/event/20/contributions/2441/BPF-RBACd>: > Delegating BPF permissions with high granularity] > * Fedora: Quick Docs article covering installation, group membership, > policy customization, security model, and container vs. desktop usage > paths. > * eBPF SIG: [https://fedoraproject.org/wiki/SIGs/eBPF SIGs/eBPF], > Matrix: [https://matrix.to/#/#ebpf:fedoraproject.org > #ebpf:fedoraproject.org] > > == Release Notes == > > Fedora 46 introduces <code>bpf-rbacd</code>, a system daemon that > enables unprivileged, policy-controlled eBPF access through two > complementary modes: > > * '''Capability granting''' for containers and services in user > namespaces — transparent eBPF access via BPF token delegation with > mandatory in-kernel LSM enforcement (three hooks: > <code>security_bpf</code>, <code>security_bpf_prog_load</code>, > <code>security_bpf_map_create</code>). > * '''Proxy execution''' for desktop users in the initial user > namespace — rootless BPF access via the <code>bpf-rbac</code> CLI, > with the daemon executing allowed operations on the user's behalf and > passing file descriptors back via <code>SCM_RIGHTS</code>. > > Both modes are governed by a single YAML policy file > (<code>/etc/bpf-rbac/policy.yaml</code>) and gated by role-based > groups (<code>ebpf</code>, <code>ebpf-net</code>, > <code>ebpf-admin</code>). Install with <code>sudo dnf install > bpf-rbacd</code>. > > > -- > Aoife Moloney > > Fedora Operations Architect > > Fedora Project > > Matrix: @amoloney:fedora.im > > IRC: amoloney > > -- > _______________________________________________ > devel-announce mailing list -- [email protected] > To unsubscribe send an email to > [email protected] > Fedora Code of Conduct: > https://docs.fedoraproject.org/en-US/project/code-of-conduct/ > List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines > List Archives: > https://lists.fedoraproject.org/archives/list/[email protected] > Do not reply to spam, report it: > https://forge.fedoraproject.org/infra/tickets/issues/new > -- > _______________________________________________ > devel mailing list -- [email protected] > To unsubscribe send an email to [email protected] > Fedora Code of Conduct: > https://docs.fedoraproject.org/en-US/project/code-of-conduct/ > List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines > List Archives: > https://lists.fedoraproject.org/archives/list/[email protected] > Do not reply to spam, report it: > https://forge.fedoraproject.org/infra/tickets/issues/new >
-- _______________________________________________ devel mailing list -- [email protected] To unsubscribe send an email to [email protected] Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/[email protected] Do not reply to spam, report it: https://forge.fedoraproject.org/infra/tickets/issues/new
