]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Consolidate sleepable checks in check_func_call()
authorPuranjay Mohan <puranjay@kernel.org>
Wed, 18 Mar 2026 17:43:26 +0000 (10:43 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 21 Mar 2026 20:09:35 +0000 (13:09 -0700)
The sleepable context check for global function calls in
check_func_call() open-codes the same checks that in_sleepable_context()
already performs. Replace the open-coded check with a call to
in_sleepable_context() and use non_sleepable_context_description() for
the error message, consistent with check_helper_call() and
check_kfunc_call().

Note that in_sleepable_context() also checks active_locks, which
overlaps with the existing active_locks check above it. However, the two
checks serve different purposes: the active_locks check rejects all
global function calls while holding a lock (not just sleepable ones), so
it must remain as a separate guard.

Update the expected error messages in the irq and preempt_lock selftests
to match.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260318174327.3151925-4-puranjay@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c
tools/testing/selftests/bpf/progs/irq.c
tools/testing/selftests/bpf/progs/preempt_lock.c

index a9130c4888f7092fbbb909d12e09bad6ee662d07..80a9eab79cac8b80051820243c40809d4c80cb4a 100644 (file)
@@ -210,6 +210,8 @@ static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env);
 static int ref_set_non_owning(struct bpf_verifier_env *env,
                              struct bpf_reg_state *reg);
 static bool is_trusted_reg(const struct bpf_reg_state *reg);
+static inline bool in_sleepable_context(struct bpf_verifier_env *env);
+static const char *non_sleepable_context_description(struct bpf_verifier_env *env);
 
 static bool bpf_map_ptr_poisoned(const struct bpf_insn_aux_data *aux)
 {
@@ -10948,12 +10950,9 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                        return -EINVAL;
                }
 
-               if (env->subprog_info[subprog].might_sleep &&
-                   (env->cur_state->active_rcu_locks || env->cur_state->active_preempt_locks ||
-                    env->cur_state->active_irq_id || !in_sleepable(env))) {
-                       verbose(env, "global functions that may sleep are not allowed in non-sleepable context,\n"
-                                    "i.e., in a RCU/IRQ/preempt-disabled section, or in\n"
-                                    "a non-sleepable BPF program context\n");
+               if (env->subprog_info[subprog].might_sleep && !in_sleepable_context(env)) {
+                       verbose(env, "sleepable global function %s() called in %s\n",
+                               sub_name, non_sleepable_context_description(env));
                        return -EINVAL;
                }
 
index 74d912b22de903bb1167647a4740a2fcbd491e2d..e11e82d989040b75f928752155c596d33f245d36 100644 (file)
@@ -490,7 +490,7 @@ int irq_non_sleepable_global_subprog(void *ctx)
 }
 
 SEC("?syscall")
-__failure __msg("global functions that may sleep are not allowed in non-sleepable context")
+__failure __msg("sleepable global function")
 int irq_sleepable_helper_global_subprog(void *ctx)
 {
        unsigned long flags;
@@ -502,7 +502,7 @@ int irq_sleepable_helper_global_subprog(void *ctx)
 }
 
 SEC("?syscall")
-__failure __msg("global functions that may sleep are not allowed in non-sleepable context")
+__failure __msg("sleepable global function")
 int irq_sleepable_global_subprog_indirect(void *ctx)
 {
        unsigned long flags;
index 7d04254e61f1ce0c2d81451bfa4df605f484d6c1..6d5fce7e6ffc9097f4bf10a17f7c20f1aecb3c32 100644 (file)
@@ -177,7 +177,7 @@ global_subprog_calling_sleepable_global(int i)
 }
 
 SEC("?syscall")
-__failure __msg("global functions that may sleep are not allowed in non-sleepable context")
+__failure __msg("sleepable global function")
 int preempt_global_sleepable_helper_subprog(struct __sk_buff *ctx)
 {
        preempt_disable();
@@ -188,7 +188,7 @@ int preempt_global_sleepable_helper_subprog(struct __sk_buff *ctx)
 }
 
 SEC("?syscall")
-__failure __msg("global functions that may sleep are not allowed in non-sleepable context")
+__failure __msg("sleepable global function")
 int preempt_global_sleepable_kfunc_subprog(struct __sk_buff *ctx)
 {
        preempt_disable();
@@ -199,7 +199,7 @@ int preempt_global_sleepable_kfunc_subprog(struct __sk_buff *ctx)
 }
 
 SEC("?syscall")
-__failure __msg("global functions that may sleep are not allowed in non-sleepable context")
+__failure __msg("sleepable global function")
 int preempt_global_sleepable_subprog_indirect(struct __sk_buff *ctx)
 {
        preempt_disable();