[PATCH bpf-next 10/10] bpf: consistenly use program's recorded capabilities in BPF verifier

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

 



Remove remaining direct queries to perfmon_capable() and bpf_capable()
in BPF verifier logic and instead use prog->aux->{bpf,perfmon}_capable
values. This enables to have one place where permissions are checked
and granted for any given BPF program, and after that BPF subsystem will
consistently use the decision.

Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
---
 include/linux/bpf.h    | 16 ++++++++--------
 include/linux/filter.h |  2 +-
 kernel/bpf/core.c      |  2 +-
 kernel/bpf/verifier.c  | 17 ++++++++++-------
 net/core/filter.c      |  4 ++--
 5 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 785b720358f5..8a2af67039fc 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2048,26 +2048,26 @@ bpf_map_alloc_percpu(const struct bpf_map *map, size_t size, size_t align,
 
 extern int sysctl_unprivileged_bpf_disabled;
 
-static inline bool bpf_allow_ptr_leaks(void)
+static inline bool bpf_allow_ptr_leaks(const struct bpf_prog *prog)
 {
-	return perfmon_capable();
+	return prog->aux->perfmon_capable;
 }
 
-static inline bool bpf_allow_uninit_stack(void)
+static inline bool bpf_allow_uninit_stack(const struct bpf_prog *prog)
 {
-	return perfmon_capable();
+	return prog->aux->perfmon_capable;
 }
 
-static inline bool bpf_bypass_spec_v1(void)
+static inline bool bpf_bypass_spec_v1(const struct bpf_prog *prog)
 {
-	return perfmon_capable();
+	return prog->aux->perfmon_capable;
 }
 
 int bpf_array_adjust_for_spec_v1(union bpf_attr *attr);
 
-static inline bool bpf_bypass_spec_v4(void)
+static inline bool bpf_bypass_spec_v4(const struct bpf_prog *prog)
 {
-	return perfmon_capable();
+	return prog->aux->perfmon_capable;
 }
 
 int bpf_map_new_fd(struct bpf_map *map, int flags);
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 9c207d9848e9..95ce7c4ab28d 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1112,7 +1112,7 @@ static inline bool bpf_jit_blinding_enabled(struct bpf_prog *prog)
 		return false;
 	if (!bpf_jit_harden)
 		return false;
-	if (bpf_jit_harden == 1 && bpf_capable())
+	if (bpf_jit_harden == 1 && prog->aux->bpf_capable)
 		return false;
 
 	return true;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 4d057d39c286..c0d60da7e0e0 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -661,7 +661,7 @@ static bool bpf_prog_kallsyms_candidate(const struct bpf_prog *fp)
 void bpf_prog_kallsyms_add(struct bpf_prog *fp)
 {
 	if (!bpf_prog_kallsyms_candidate(fp) ||
-	    !bpf_capable())
+	    !fp->aux->bpf_capable)
 		return;
 
 	bpf_prog_ksym_set_addr(fp);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 481aaf189183..7be0abc196db 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -17194,6 +17194,10 @@ static int jit_subprogs(struct bpf_verifier_env *env)
 		func[i]->aux->poke_tab = prog->aux->poke_tab;
 		func[i]->aux->size_poke_tab = prog->aux->size_poke_tab;
 
+		/* inherit main prog's effective capabilities */
+		func[i]->aux->bpf_capable = prog->aux->bpf_capable;
+		func[i]->aux->perfmon_capable = prog->aux->perfmon_capable;
+
 		for (j = 0; j < prog->aux->size_poke_tab; j++) {
 			struct bpf_jit_poke_descriptor *poke;
 
@@ -18878,7 +18882,12 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
 	env->prog = *prog;
 	env->ops = bpf_verifier_ops[env->prog->type];
 	env->fd_array = make_bpfptr(attr->fd_array, uattr.is_kernel);
-	is_priv = bpf_capable();
+
+	env->allow_ptr_leaks = bpf_allow_ptr_leaks(*prog);
+	env->allow_uninit_stack = bpf_allow_uninit_stack(*prog);
+	env->bypass_spec_v1 = bpf_bypass_spec_v1(*prog);
+	env->bypass_spec_v4 = bpf_bypass_spec_v4(*prog);
+	env->bpf_capable = is_priv = (*prog)->aux->bpf_capable;
 
 	bpf_get_btf_vmlinux();
 
@@ -18910,12 +18919,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
 	if (attr->prog_flags & BPF_F_ANY_ALIGNMENT)
 		env->strict_alignment = false;
 
-	env->allow_ptr_leaks = bpf_allow_ptr_leaks();
-	env->allow_uninit_stack = bpf_allow_uninit_stack();
-	env->bypass_spec_v1 = bpf_bypass_spec_v1();
-	env->bypass_spec_v4 = bpf_bypass_spec_v4();
-	env->bpf_capable = bpf_capable();
-
 	if (is_priv)
 		env->test_state_freq = attr->prog_flags & BPF_F_TEST_STATE_FREQ;
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 8e282797e658..8a7e86230f2a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -8432,7 +8432,7 @@ static bool cg_skb_is_valid_access(int off, int size,
 		return false;
 	case bpf_ctx_range(struct __sk_buff, data):
 	case bpf_ctx_range(struct __sk_buff, data_end):
-		if (!bpf_capable())
+		if (!prog->aux->bpf_capable)
 			return false;
 		break;
 	}
@@ -8444,7 +8444,7 @@ static bool cg_skb_is_valid_access(int off, int size,
 		case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
 			break;
 		case bpf_ctx_range(struct __sk_buff, tstamp):
-			if (!bpf_capable())
+			if (!prog->aux->bpf_capable)
 				return false;
 			break;
 		default:
-- 
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