Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: refine kernel.unprivileged_bpf_disabled behaviour

With unprivileged BPF disabled, all cmds associated with the BPF syscall
are blocked to users without CAP_BPF/CAP_SYS_ADMIN. However there are
use cases where we may wish to allow interactions with BPF programs
without being able to load and attach them. So for example, a process
with required capabilities loads/attaches a BPF program, and a process
with less capabilities interacts with it; retrieving perf/ring buffer
events, modifying map-specified config etc. With all BPF syscall
commands blocked as a result of unprivileged BPF being disabled,
this mode of interaction becomes impossible for processes without
CAP_BPF.

As Alexei notes

"The bpf ACL model is the same as traditional file's ACL.
The creds and ACLs are checked at open(). Then during file's write/read
additional checks might be performed. BPF has such functionality already.
Different map_creates have capability checks while map_lookup has:
map_get_sys_perms(map, f) & FMODE_CAN_READ.
In other words it's enough to gate FD-receiving parts of bpf
with unprivileged_bpf_disabled sysctl.
The rest is handled by availability of FD and access to files in bpffs."

So key fd creation syscall commands BPF_PROG_LOAD and BPF_MAP_CREATE
are blocked with unprivileged BPF disabled and no CAP_BPF.

And as Alexei notes, map creation with unprivileged BPF disabled off
blocks creation of maps aside from array, hash and ringbuf maps.

Programs responsible for loading and attaching the BPF program
can still control access to its pinned representation by restricting
permissions on the pin path, as with normal files.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Acked-by: Yonghong Song <yhs@fb.com>
Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
Acked-by: KP Singh <kpsingh@kernel.org>
Link: https://lore.kernel.org/r/1652970334-30510-2-git-send-email-alan.maguire@oracle.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Alan Maguire and committed by
Alexei Starovoitov
c8644cd0 97949767

+13 -1
+13 -1
kernel/bpf/syscall.c
··· 4863 4863 static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size) 4864 4864 { 4865 4865 union bpf_attr attr; 4866 + bool capable; 4866 4867 int err; 4867 4868 4868 - if (sysctl_unprivileged_bpf_disabled && !bpf_capable()) 4869 + capable = bpf_capable() || !sysctl_unprivileged_bpf_disabled; 4870 + 4871 + /* Intent here is for unprivileged_bpf_disabled to block key object 4872 + * creation commands for unprivileged users; other actions depend 4873 + * of fd availability and access to bpffs, so are dependent on 4874 + * object creation success. Capabilities are later verified for 4875 + * operations such as load and map create, so even with unprivileged 4876 + * BPF disabled, capability checks are still carried out for these 4877 + * and other operations. 4878 + */ 4879 + if (!capable && 4880 + (cmd == BPF_MAP_CREATE || cmd == BPF_PROG_LOAD)) 4869 4881 return -EPERM; 4870 4882 4871 4883 err = bpf_check_uarg_tail_zero(uattr, sizeof(attr), size);