CAP_SYS_ADMIN is not required to iterate bpf objects if a user is in a non-init bpf namespace. The user can iterate bpf maps, progs, and links in his bpf namespace but can't iterate the bpf objects in different bpf namespace. Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> --- include/linux/bpf_namespace.h | 8 ++++++++ kernel/bpf/syscall.c | 10 +++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/linux/bpf_namespace.h b/include/linux/bpf_namespace.h index 50bd68c..f484791 100644 --- a/include/linux/bpf_namespace.h +++ b/include/linux/bpf_namespace.h @@ -5,6 +5,7 @@ #include <linux/idr.h> #include <linux/ns_common.h> #include <linux/user_namespace.h> +#include <linux/capability.h> struct ubpf_obj_id { int nr; @@ -79,4 +80,11 @@ static inline int bpf_obj_id_vnr(struct bpf_obj_id *obj_id) { return bpf_obj_id_nr_ns(obj_id, current->nsproxy->bpf_ns); } + +static inline bool bpfns_capable(void) +{ + if (current->nsproxy->bpf_ns != &init_bpf_ns && capable(CAP_BPF)) + return true; + return false; +} #endif /* _LINUX_BPF_ID_NS_H */ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 855d5f7..8a72694 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3628,7 +3628,7 @@ static int bpf_obj_get_next_id(const union bpf_attr *attr, if (CHECK_ATTR(BPF_OBJ_GET_NEXT_ID) || next_id >= INT_MAX) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN) && !bpfns_capable()) return -EPERM; next_id++; @@ -3712,7 +3712,7 @@ static int bpf_prog_get_fd_by_id(const union bpf_attr *attr) if (CHECK_ATTR(BPF_PROG_GET_FD_BY_ID)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN) && !bpfns_capable()) return -EPERM; prog = bpf_prog_by_id(id); @@ -3740,7 +3740,7 @@ static int bpf_map_get_fd_by_id(const union bpf_attr *attr) attr->open_flags & ~BPF_OBJ_FLAG_MASK) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN) && !bpfns_capable()) return -EPERM; f_flags = bpf_get_file_flag(attr->open_flags); @@ -4386,7 +4386,7 @@ static int bpf_task_fd_query(const union bpf_attr *attr, if (CHECK_ATTR(BPF_TASK_FD_QUERY)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN) && !bpfns_capable()) return -EPERM; if (attr->task_fd_query.flags != 0) @@ -4781,7 +4781,7 @@ static int bpf_link_get_fd_by_id(const union bpf_attr *attr) if (CHECK_ATTR(BPF_LINK_GET_FD_BY_ID)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN) && !bpfns_capable()) return -EPERM; link = bpf_link_by_id(id); -- 1.8.3.1