Re: [PATCH v7] SELinux: Add support for BPF token access control

Christian Göttsche
2026-01-14T17:56:05Z

On Tue, 13 Jan 2026 at 21:45, Paul Moore <paul@paul-moore.com> wrote:
>
> On Dec 4, 2025 Eric Suen <ericsu@linux.microsoft.com> wrote:
> >
> > BPF token support was introduced to allow a privileged process to delegate
> > limited BPF functionality—such as map creation and program loading—to
> > an unprivileged process:
> > https://lore.kernel.org/linux-security-module/20231130185229.2688956-1-andrii@kernel.org/
> >
> > This patch adds SELinux support for controlling BPF token access. With
> > this change, SELinux policies can now enforce constraints on BPF token
> > usage based on both the delegating (privileged) process and the recipient
> > (unprivileged) process.
> >
> > Supported operations currently include:
> > - map_create
> > - prog_load
> >
> > High-level workflow:
> > 1. An unprivileged process creates a VFS context via `fsopen()` and
> > obtains a file descriptor.
> > 2. This descriptor is passed to a privileged process, which configures
> > BPF token delegation options and mounts a BPF filesystem.
> > 3. SELinux records the `creator_sid` of the privileged process during
> > mount setup.
> > 4. The unprivileged process then uses this BPF fs mount to create a
> > token and attach it to subsequent BPF syscalls.
> > 5. During verification of `map_create` and `prog_load`, SELinux uses
> > `creator_sid` and the current SID to check policy permissions via:
> > avc_has_perm(creator_sid, current_sid, SECCLASS_BPF,
> > BPF__MAP_CREATE, NULL);
> >
> > The implementation introduces two new permissions:
> > - map_create_as
> > - prog_load_as
> >
> > At token creation time, SELinux verifies that the current process has the
> > appropriate `*_as` permission (depending on the `allowed_cmds` value in
> > the bpf_token) to act on behalf of the `creator_sid`.
> >
> > Example SELinux policy:
> > allow test_bpf_t self:bpf {
> > map_create map_read map_write prog_load prog_run
> > map_create_as prog_load_as
> > };
> >
> > Additionally, a new policy capability bpf_token_perms is added to ensure
> > backward compatibility. If disabled, previous behavior ((checks based on
> > current process SID)) is preserved.
> >
> > Signed-off-by: Eric Suen <ericsu@linux.microsoft.com>
> > Tested-by: Daniel Durning <danieldurning.work@gmail.com>
> > Reviewed-by: Daniel Durning <danieldurning.work@gmail.com>
> > ---
> > Changes in v2:
> > - Fixed bug in selinux_bpffs_creator_sid(u32 fd) where it retrieved
> > creator_sid from wrong file descriptor
> > - Removed unnecessary checks for null, per review comments from
> > the first patch
> >
> > Changes in v3:
> > - Removed check for 'sid == SECSID_NULL' in selinux_bpf_token_create and
> > allow it to fall through to the permission checks which will fail as
> > access denied to unlabeled_t
> >
> > Changes in v4:
> > - Added initialization of creator_sid in selinux_sb_alloc_security
> > - Enabled handling of creator_sid in selinux_cmp_sb_context and
> > selinux_sb_clone_mnt_opts
> > - Minor updates based on review comments
> >
> > Changes in v5:
> > - Moved to dev-staging branch instead of main
> > - Added implementation of selinux_bpf_token_capable which is originally
> > from Daniel's patch
> > https://lore.kernel.org/selinux/20250801154637.143931-1-danieldurning.work@gmail.com/
> >
> > Changes in v6:
> > - Updated bpf_token_capable to use grantor_sid as object in permission
> > check
> >
> > Changes in v7:
> > - Bug fix in selinux_bpf_token_capable where incorrect source sid
> > was used in avc_has_perm
> >
> > security/selinux/hooks.c | 117 ++++++++++++++++++++-
> > security/selinux/include/classmap.h | 2 +-
> > security/selinux/include/objsec.h | 3 +
> > security/selinux/include/policycap.h | 1 +
> > security/selinux/include/policycap_names.h | 1 +
> > security/selinux/include/security.h | 6 ++
> > 6 files changed, 127 insertions(+), 3 deletions(-)
>
> Merged into selinux/dev with some minor line length and whitespace
> tweaks. Thanks everyone!

I think there is a typo in selinux_bpf_token_capable():

switch (CAP_TO_INDEX(cap)) {
case 0:
sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
break;
case 1:
sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP2_USERNS;
// <-- SECCLASS_CAPABILITY2 ??
break;
default:
pr_err("SELinux: out of range capability %d\n", cap);
return -EINVAL;
}

see https://github.com/SELinuxProject/selinux-kernel/blob/5473a722f782f79f96b4691400d681c01fcacc2f/security/selinux/hooks.c#L7263

> --
> paul-moore.com
>