]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Consolidate sleepable checks in check_helper_call()
authorPuranjay Mohan <puranjay@kernel.org>
Wed, 18 Mar 2026 17:43:24 +0000 (10:43 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 21 Mar 2026 20:09:34 +0000 (13:09 -0700)
check_helper_call() prints the error message for every
env->cur_state->active* element when calling a sleepable helper.
Consolidate all of them into a single print statement.

The check for env->cur_state->active_locks was not part of the removed
print statements and will not be triggered with the consolidated print
as well because it is checked in do_check() before check_helper_call()
is even reached.

Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
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-2-puranjay@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c
tools/testing/selftests/bpf/prog_tests/summarization.c
tools/testing/selftests/bpf/progs/verifier_async_cb_context.c

index 01c18f4268deb3355f3ab03c41ceacc7e9d712c6..4e0f6be5d2d59ebfb33f883b0f081e1ee39d220e 100644 (file)
@@ -11678,6 +11678,19 @@ static inline bool in_sleepable_context(struct bpf_verifier_env *env)
               in_sleepable(env);
 }
 
+static const char *non_sleepable_context_description(struct bpf_verifier_env *env)
+{
+       if (env->cur_state->active_rcu_locks)
+               return "rcu_read_lock region";
+       if (env->cur_state->active_preempt_locks)
+               return "non-preemptible region";
+       if (env->cur_state->active_irq_id)
+               return "IRQ-disabled region";
+       if (env->cur_state->active_locks)
+               return "lock region";
+       return "non-sleepable prog";
+}
+
 static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                             int *insn_idx_p)
 {
@@ -11717,11 +11730,6 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                return -EINVAL;
        }
 
-       if (!in_sleepable(env) && fn->might_sleep) {
-               verbose(env, "helper call might sleep in a non-sleepable prog\n");
-               return -EINVAL;
-       }
-
        /* With LD_ABS/IND some JITs save/restore skb from r1. */
        changes_data = bpf_helper_changes_pkt_data(func_id);
        if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
@@ -11738,28 +11746,10 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                return err;
        }
 
-       if (env->cur_state->active_rcu_locks) {
-               if (fn->might_sleep) {
-                       verbose(env, "sleepable helper %s#%d in rcu_read_lock region\n",
-                               func_id_name(func_id), func_id);
-                       return -EINVAL;
-               }
-       }
-
-       if (env->cur_state->active_preempt_locks) {
-               if (fn->might_sleep) {
-                       verbose(env, "sleepable helper %s#%d in non-preemptible region\n",
-                               func_id_name(func_id), func_id);
-                       return -EINVAL;
-               }
-       }
-
-       if (env->cur_state->active_irq_id) {
-               if (fn->might_sleep) {
-                       verbose(env, "sleepable helper %s#%d in IRQ-disabled region\n",
-                               func_id_name(func_id), func_id);
-                       return -EINVAL;
-               }
+       if (fn->might_sleep && !in_sleepable_context(env)) {
+               verbose(env, "sleepable helper %s#%d in %s\n", func_id_name(func_id), func_id,
+                       non_sleepable_context_description(env));
+               return -EINVAL;
        }
 
        /* Track non-sleepable context for helpers. */
index 5dd6c120a83861e16a7c11692a36728729c108c0..6951786044cac93371d0742783da1c867b9236b6 100644 (file)
@@ -58,7 +58,7 @@ static void test_aux(const char *main_prog_name,
         * this particular combination can be enabled.
         */
        if (!strcmp("might_sleep", replacement) && err) {
-               ASSERT_HAS_SUBSTR(log, "helper call might sleep in a non-sleepable prog", "error log");
+               ASSERT_HAS_SUBSTR(log, "sleepable helper bpf_copy_from_user#", "error log");
                ASSERT_EQ(err, -EINVAL, "err");
                test__skip();
                goto out;
index 39aff82549c9c661d3f2c9eb9809af978bb0cb35..6bf95550a0248268462b65a17f97fa33b1f28489 100644 (file)
@@ -31,7 +31,7 @@ static int timer_cb(void *map, int *key, struct bpf_timer *timer)
 }
 
 SEC("fentry/bpf_fentry_test1")
-__failure __msg("helper call might sleep in a non-sleepable prog")
+__failure __msg("sleepable helper bpf_copy_from_user#{{[0-9]+}} in non-sleepable prog")
 int timer_non_sleepable_prog(void *ctx)
 {
        struct timer_elem *val;
@@ -47,7 +47,7 @@ int timer_non_sleepable_prog(void *ctx)
 }
 
 SEC("lsm.s/file_open")
-__failure __msg("helper call might sleep in a non-sleepable prog")
+__failure __msg("sleepable helper bpf_copy_from_user#{{[0-9]+}} in non-sleepable prog")
 int timer_sleepable_prog(void *ctx)
 {
        struct timer_elem *val;