From: Ihor Solodrai <[email protected]> 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 <[email protected]> Signed-off-by: Jay Wang <[email protected]> --- 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
