summaryrefslogtreecommitdiff
path: root/kernel/bpf
diff options
context:
space:
mode:
authorKumar Kartikeya Dwivedi <memxor@gmail.com>2024-11-03 14:59:38 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-05 14:01:51 +0100
commitaa51be3fa9e0982491c919985a7ffcf02c2d1b4d (patch)
tree9355796e11066a78c102d0ae63bcedc68324ab6e /kernel/bpf
parentcaf27ed9ea739a026e1a6198ea60ee1c67d8b34a (diff)
downloadlinux-aa51be3fa9e0982491c919985a7ffcf02c2d1b4d.tar.gz
linux-aa51be3fa9e0982491c919985a7ffcf02c2d1b4d.tar.bz2
linux-aa51be3fa9e0982491c919985a7ffcf02c2d1b4d.zip
bpf: Tighten tail call checks for lingering locks, RCU, preempt_disable
[ Upstream commit 46f7ed32f7a873d6675ea72e1d6317df41a55f81 ] There are three situations when a program logically exits and transfers control to the kernel or another program: bpf_throw, BPF_EXIT, and tail calls. The former two check for any lingering locks and references, but tail calls currently do not. Expand the checks to check for spin locks, RCU read sections and preempt disabled sections. Spin locks are indirectly preventing tail calls as function calls are disallowed, but the checks for preemption and RCU are more relaxed, hence ensure tail calls are prevented in their presence. Fixes: 9bb00b2895cb ("bpf: Add kfunc bpf_rcu_read_lock/unlock()") Fixes: fc7566ad0a82 ("bpf: Introduce bpf_preempt_[disable,enable] kfuncs") Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20241103225940.1408302-2-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/verifier.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index bb99bada7e2e..011b4a86e2b3 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -10583,11 +10583,26 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
switch (func_id) {
case BPF_FUNC_tail_call:
+ if (env->cur_state->active_lock.ptr) {
+ verbose(env, "tail_call cannot be used inside bpf_spin_lock-ed region\n");
+ return -EINVAL;
+ }
+
err = check_reference_leak(env, false);
if (err) {
verbose(env, "tail_call would lead to reference leak\n");
return err;
}
+
+ if (env->cur_state->active_rcu_lock) {
+ verbose(env, "tail_call cannot be used inside bpf_rcu_read_lock-ed region\n");
+ return -EINVAL;
+ }
+
+ if (env->cur_state->active_preempt_lock) {
+ verbose(env, "tail_call cannot be used inside bpf_preempt_disable-ed region\n");
+ return -EINVAL;
+ }
break;
case BPF_FUNC_get_local_storage:
/* check that flags argument in get_local_storage(map, flags) is 0,