[PATCH bpf-next 03/13] bpf: check CAP_SYS_ADMIN before looking up bpffs delegation names
From: Jay Wang
Date: Sat Oct 31 2026 - 09:12:33 EST
From: Ihor Solodrai <ihor.solodrai@xxxxxxxxx>
bpf_parse_param() resolves the symbolic values of the delegate_cmds,
delegate_maps, delegate_progs and delegate_attachs mount options with
find_bpffs_btf_enums(), which fetches the vmlinux BTF, and only then
refuses a non-zero mask from a caller without CAP_SYS_ADMIN. bpffs can
be mounted in a user namespace, so any local user can run
"unshare -Urm mount -t bpf -o delegate_cmds=any bpf /mnt" and get
EPERM, after the lookup.
That is free today because the vmlinux BTF is parsed at boot. Once it
is parsed on first use (CONFIG_DEBUG_INFO_BTF_LAZY, later in this
series), it would let any user make the kernel parse it and keep it
parsed until reboot, which is what the option is meant to avoid on
systems that do not use BTF.
Check the capability first. An unprivileged caller could only ever set
an empty mask; such a no-op delegate option, and a malformed value,
now fail with EPERM as well instead of being accepted or failing with
EINVAL. Privileged callers are not affected.
TODO-NEEDS-IHOR: Signed-off-by: Ihor Solodrai <ihor.solodrai@xxxxxxxxx>
Signed-off-by: Jay Wang <wanjay@xxxxxxxxxx>
---
kernel/bpf/inode.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index c6f328e4752e..39750d4ad401 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -1059,6 +1059,13 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param)
char *p, *str;
int val;
+ /*
+ * Setting delegation mount options requires privileges. Check
+ * before the lookup, which may have to parse the vmlinux BTF.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
/* ignore errors, fallback to hex */
(void)find_bpffs_btf_enums(&info);
@@ -1100,10 +1107,6 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param)
}
}
- /* Setting delegation mount options requires privileges */
- if (msk && !capable(CAP_SYS_ADMIN))
- return -EPERM;
-
*delegate_msk |= msk;
break;
}
--
2.47.3