[PATCH bpf-next 07/10] bpf: record effective capabilities at BPF prog load time

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Determine and remember effective capabilities of the process at the
BPF_PROG_LOAD command time. We store those in prog->aux, so we can check
and use them throughout various places (like BPF verifier) that perform
various checks and enforce various extra conditions on BPF program based
on its effective capabilities. Currently we have explicit calls to
bpf_capable(), perfmon_capable() and capable() spread out throughout
code base, but we'll be refactoring this over next few patches to
consistently use prog->aux->{bpf,perfmon}_capable
fields to perform decisions. This ensures we have a consistent set of
restrictions checked and recorded in one consistent place.

Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
---
 include/linux/bpf.h  |  5 +++++
 kernel/bpf/syscall.c | 23 +++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 479657bb113e..44ccfea0f73b 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1370,6 +1370,11 @@ struct bpf_prog_aux {
 	u32 ctx_arg_info_size;
 	u32 max_rdonly_access;
 	u32 max_rdwr_access;
+
+	/* effective capabilities that were given to BPF program at load time */
+	bool bpf_capable;
+	bool perfmon_capable;
+
 	struct btf *attach_btf;
 	const struct bpf_ctx_arg_aux *ctx_arg_info;
 	struct mutex dst_mutex; /* protects dst_* pointers below, *after* prog becomes visible */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index d960eb476754..839f69d75297 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2568,6 +2568,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
 
 static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 {
+	bool bpf_cap, net_admin_cap, sys_admin_cap, perfmon_cap;
 	enum bpf_prog_type type = attr->prog_type;
 	struct bpf_prog *prog, *dst_prog = NULL;
 	struct btf *attach_btf = NULL;
@@ -2586,6 +2587,12 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 				 BPF_F_XDP_DEV_BOUND_ONLY))
 		return -EINVAL;
 
+	/* remember set of effective capabilities to be used throughout */
+	bpf_cap = bpf_capable();
+	perfmon_cap = perfmon_capable();
+	net_admin_cap = capable(CAP_NET_ADMIN);
+	sys_admin_cap = capable(CAP_SYS_ADMIN);
+
 	/* Intent here is for unprivileged_bpf_disabled to block key object
 	 * creation commands for unprivileged users; other actions depend
 	 * of fd availability and access to bpffs, so are dependent on
@@ -2594,25 +2601,25 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 	 * BPF disabled, capability checks are still carried out for these
 	 * and other operations.
 	 */
-	if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
+	if (sysctl_unprivileged_bpf_disabled && !bpf_cap)
 		return -EPERM;
 
 	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
 	    (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
-	    !bpf_capable())
+	    !bpf_cap)
 		return -EPERM;
 
 	if (attr->insn_cnt == 0 ||
-	    attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
+	    attr->insn_cnt > (bpf_cap ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
 		return -E2BIG;
 	if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
 	    type != BPF_PROG_TYPE_CGROUP_SKB &&
-	    !bpf_capable())
+	    !bpf_cap)
 		return -EPERM;
 
-	if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
+	if (is_net_admin_prog_type(type) && !net_admin_cap && !sys_admin_cap)
 		return -EPERM;
-	if (is_perfmon_prog_type(type) && !perfmon_capable())
+	if (is_perfmon_prog_type(type) && !perfmon_cap)
 		return -EPERM;
 
 	/* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
@@ -2672,6 +2679,10 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 	prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
 	prog->aux->xdp_has_frags = attr->prog_flags & BPF_F_XDP_HAS_FRAGS;
 
+	/* remember effective capabilities prog was given */
+	prog->aux->bpf_capable = bpf_cap;
+	prog->aux->perfmon_capable = perfmon_cap;
+
 	err = security_bpf_prog_alloc(prog->aux);
 	if (err)
 		goto free_prog;
-- 
2.34.1




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux