public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs
@ 2026-03-20  0:08 Ihor Solodrai
  2026-03-20  0:08 ` [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs Ihor Solodrai
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Ihor Solodrai @ 2026-03-20  0:08 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Martin KaFai Lau
  Cc: Kumar Kartikeya Dwivedi, bpf, linux-kernel, kernel-team

process_bpf_exit_full() passes check_lock = !curframe to
check_resource_leak(), which is false in cases when bpf_throw() is
called from a static subprog. This makes check_resource_leak() to skip
validation of active_rcu_locks, active_preempt_locks, and
active_irq_id on exception exits from subprogs.

At runtime bpf_throw() unwinds the stack via ORC without releasing any
user-acquired locks, which may cause various issues as the result.

Fix by setting check_lock = true for exception exits regardless of
curframe, since exceptions bypass all intermediate frame
cleanup. Update the error message prefix to "bpf_throw" for exception
exits to distinguish them from normal BPF_EXIT.

Fix reject_subprog_with_rcu_read_lock test which was previously
passing for the wrong reason. Test program returned directly from the
subprog call without closing the RCU section, so the error was
triggered by the unclosed RCU lock on normal exit, not by
bpf_throw. Update __msg annotations for affected tests to match the
new "bpf_throw" error prefix.

The spin_lock case is not affected because they are already checked [1]
at the call site in do_check_insn() before bpf_throw can run.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/bpf/verifier.c?h=v7.0-rc4#n21098

Assisted-by: Claude:claude-opus-4-6
Fixes: f18b03fabaa9 ("bpf: Implement BPF exceptions")
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>

---

v1->v2:
  * fix reject_subprog_with_rcu_read_lock test (Kumar)
  * add test case with irq lock (Kumar)
  * remove reject_subprog_throw_rcu_lock test from patch #2, since
    it's essentially a duplicate now

v1: https://lore.kernel.org/bpf/20260317001325.318004-1-ihor.solodrai@linux.dev/

This bug was discovered by an AI bot. You can find the original
AI-generated investigation here:
https://github.com/theihor/bpf/commits/ai-tinkering-20260310-0745/

---
 kernel/bpf/verifier.c                               | 3 ++-
 tools/testing/selftests/bpf/progs/exceptions_fail.c | 9 ++++++---
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index df22bfc572e2..5c0e6809024f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -20911,7 +20911,8 @@ static int process_bpf_exit_full(struct bpf_verifier_env *env,
 	 * state when it exits.
 	 */
 	int err = check_resource_leak(env, exception_exit,
-				      !env->cur_state->curframe,
+				      exception_exit || !env->cur_state->curframe,
+				      exception_exit ? "bpf_throw" :
 				      "BPF_EXIT instruction in main prog");
 	if (err)
 		return err;
diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c
index 8a0fdff89927..d7f1c492e3dd 100644
--- a/tools/testing/selftests/bpf/progs/exceptions_fail.c
+++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c
@@ -8,6 +8,7 @@
 #include "bpf_experimental.h"
 
 extern void bpf_rcu_read_lock(void) __ksym;
+extern void bpf_rcu_read_unlock(void) __ksym;
 
 #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
 
@@ -131,7 +132,7 @@ int reject_subprog_with_lock(void *ctx)
 }
 
 SEC("?tc")
-__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_rcu_read_lock-ed region")
+__failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
 int reject_with_rcu_read_lock(void *ctx)
 {
 	bpf_rcu_read_lock();
@@ -147,11 +148,13 @@ __noinline static int throwing_subprog(struct __sk_buff *ctx)
 }
 
 SEC("?tc")
-__failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_rcu_read_lock-ed region")
+__failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
 int reject_subprog_with_rcu_read_lock(void *ctx)
 {
 	bpf_rcu_read_lock();
-	return throwing_subprog(ctx);
+	throwing_subprog(ctx);
+	bpf_rcu_read_unlock();
+	return 0;
 }
 
 static bool rbless(struct bpf_rb_node *n1, const struct bpf_rb_node *n2)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs
  2026-03-20  0:08 [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Ihor Solodrai
@ 2026-03-20  0:08 ` Ihor Solodrai
  2026-03-21 16:55   ` Yonghong Song
  2026-03-21 18:53   ` Kumar Kartikeya Dwivedi
  2026-03-21 16:34 ` [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Yonghong Song
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 7+ messages in thread
From: Ihor Solodrai @ 2026-03-20  0:08 UTC (permalink / raw)
  To: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Martin KaFai Lau
  Cc: Kumar Kartikeya Dwivedi, bpf, linux-kernel, kernel-team

Add test cases to ensure the verifier correctly rejects bpf_throw from
subprogs when RCU, preempt, or IRQ locks are held:

  * reject_subprog_rcu_lock_throw: subprog acquires bpf_rcu_read_lock and
    then calls bpf_throw
  * reject_subprog_throw_preempt_lock: always-throwing subprog called while
    caller holds bpf_preempt_disable
  * reject_subprog_throw_irq_lock: always-throwing subprog called while
    caller holds bpf_local_irq_save

Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 .../selftests/bpf/progs/exceptions_fail.c     | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c
index d7f1c492e3dd..9ea1353488d7 100644
--- a/tools/testing/selftests/bpf/progs/exceptions_fail.c
+++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c
@@ -9,6 +9,10 @@
 
 extern void bpf_rcu_read_lock(void) __ksym;
 extern void bpf_rcu_read_unlock(void) __ksym;
+extern void bpf_preempt_disable(void) __ksym;
+extern void bpf_preempt_enable(void) __ksym;
+extern void bpf_local_irq_save(unsigned long *) __ksym;
+extern void bpf_local_irq_restore(unsigned long *) __ksym;
 
 #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
 
@@ -349,4 +353,47 @@ int reject_exception_throw_cb_diff(struct __sk_buff *ctx)
 	return 0;
 }
 
+__noinline static int always_throws(void)
+{
+	bpf_throw(0);
+	return 0;
+}
+
+__noinline static int rcu_lock_then_throw(void)
+{
+	bpf_rcu_read_lock();
+	bpf_throw(0);
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
+int reject_subprog_rcu_lock_throw(void *ctx)
+{
+	rcu_lock_then_throw();
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("bpf_throw cannot be used inside bpf_preempt_disable-ed region")
+int reject_subprog_throw_preempt_lock(void *ctx)
+{
+	bpf_preempt_disable();
+	always_throws();
+	bpf_preempt_enable();
+	return 0;
+}
+
+SEC("?tc")
+__failure __msg("bpf_throw cannot be used inside bpf_local_irq_save-ed region")
+int reject_subprog_throw_irq_lock(void *ctx)
+{
+	unsigned long flags;
+
+	bpf_local_irq_save(&flags);
+	always_throws();
+	bpf_local_irq_restore(&flags);
+	return 0;
+}
+
 char _license[] SEC("license") = "GPL";
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs
  2026-03-20  0:08 [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Ihor Solodrai
  2026-03-20  0:08 ` [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs Ihor Solodrai
@ 2026-03-21 16:34 ` Yonghong Song
  2026-03-21 18:52 ` Kumar Kartikeya Dwivedi
  2026-03-21 20:00 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 7+ messages in thread
From: Yonghong Song @ 2026-03-21 16:34 UTC (permalink / raw)
  To: Ihor Solodrai, Alexei Starovoitov, Andrii Nakryiko,
	Daniel Borkmann, Eduard Zingerman, Martin KaFai Lau
  Cc: Kumar Kartikeya Dwivedi, bpf, linux-kernel, kernel-team



On 3/19/26 5:08 PM, Ihor Solodrai wrote:
> process_bpf_exit_full() passes check_lock = !curframe to
> check_resource_leak(), which is false in cases when bpf_throw() is
> called from a static subprog. This makes check_resource_leak() to skip
> validation of active_rcu_locks, active_preempt_locks, and
> active_irq_id on exception exits from subprogs.
>
> At runtime bpf_throw() unwinds the stack via ORC without releasing any
> user-acquired locks, which may cause various issues as the result.
>
> Fix by setting check_lock = true for exception exits regardless of
> curframe, since exceptions bypass all intermediate frame
> cleanup. Update the error message prefix to "bpf_throw" for exception
> exits to distinguish them from normal BPF_EXIT.
>
> Fix reject_subprog_with_rcu_read_lock test which was previously
> passing for the wrong reason. Test program returned directly from the
> subprog call without closing the RCU section, so the error was
> triggered by the unclosed RCU lock on normal exit, not by
> bpf_throw. Update __msg annotations for affected tests to match the
> new "bpf_throw" error prefix.
>
> The spin_lock case is not affected because they are already checked [1]
> at the call site in do_check_insn() before bpf_throw can run.
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/bpf/verifier.c?h=v7.0-rc4#n21098
>
> Assisted-by: Claude:claude-opus-4-6
> Fixes: f18b03fabaa9 ("bpf: Implement BPF exceptions")
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>

Acked-by: Yonghong Song <yonghong.song@linux.dev>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs
  2026-03-20  0:08 ` [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs Ihor Solodrai
@ 2026-03-21 16:55   ` Yonghong Song
  2026-03-21 18:53   ` Kumar Kartikeya Dwivedi
  1 sibling, 0 replies; 7+ messages in thread
From: Yonghong Song @ 2026-03-21 16:55 UTC (permalink / raw)
  To: Ihor Solodrai, Alexei Starovoitov, Andrii Nakryiko,
	Daniel Borkmann, Eduard Zingerman, Martin KaFai Lau
  Cc: Kumar Kartikeya Dwivedi, bpf, linux-kernel, kernel-team



On 3/19/26 5:08 PM, Ihor Solodrai wrote:
> Add test cases to ensure the verifier correctly rejects bpf_throw from
> subprogs when RCU, preempt, or IRQ locks are held:
>
>    * reject_subprog_rcu_lock_throw: subprog acquires bpf_rcu_read_lock and
>      then calls bpf_throw
>    * reject_subprog_throw_preempt_lock: always-throwing subprog called while
>      caller holds bpf_preempt_disable
>    * reject_subprog_throw_irq_lock: always-throwing subprog called while
>      caller holds bpf_local_irq_save
>
> Assisted-by: Claude:claude-opus-4-6
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>

Acked-by: Yonghong Song <yonghong.song@linux.dev>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs
  2026-03-20  0:08 [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Ihor Solodrai
  2026-03-20  0:08 ` [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs Ihor Solodrai
  2026-03-21 16:34 ` [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Yonghong Song
@ 2026-03-21 18:52 ` Kumar Kartikeya Dwivedi
  2026-03-21 20:00 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 7+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-03-21 18:52 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Martin KaFai Lau, bpf, linux-kernel,
	kernel-team

On Fri, 20 Mar 2026 at 01:08, Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> process_bpf_exit_full() passes check_lock = !curframe to
> check_resource_leak(), which is false in cases when bpf_throw() is
> called from a static subprog. This makes check_resource_leak() to skip
> validation of active_rcu_locks, active_preempt_locks, and
> active_irq_id on exception exits from subprogs.
>
> At runtime bpf_throw() unwinds the stack via ORC without releasing any
> user-acquired locks, which may cause various issues as the result.
>
> Fix by setting check_lock = true for exception exits regardless of
> curframe, since exceptions bypass all intermediate frame
> cleanup. Update the error message prefix to "bpf_throw" for exception
> exits to distinguish them from normal BPF_EXIT.
>
> Fix reject_subprog_with_rcu_read_lock test which was previously
> passing for the wrong reason. Test program returned directly from the
> subprog call without closing the RCU section, so the error was
> triggered by the unclosed RCU lock on normal exit, not by
> bpf_throw. Update __msg annotations for affected tests to match the
> new "bpf_throw" error prefix.
>
> The spin_lock case is not affected because they are already checked [1]
> at the call site in do_check_insn() before bpf_throw can run.
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/bpf/verifier.c?h=v7.0-rc4#n21098
>
> Assisted-by: Claude:claude-opus-4-6
> Fixes: f18b03fabaa9 ("bpf: Implement BPF exceptions")
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
>
> ---

Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

> [...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs
  2026-03-20  0:08 ` [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs Ihor Solodrai
  2026-03-21 16:55   ` Yonghong Song
@ 2026-03-21 18:53   ` Kumar Kartikeya Dwivedi
  1 sibling, 0 replies; 7+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-03-21 18:53 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
	Eduard Zingerman, Martin KaFai Lau, bpf, linux-kernel,
	kernel-team

On Fri, 20 Mar 2026 at 01:08, Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> Add test cases to ensure the verifier correctly rejects bpf_throw from
> subprogs when RCU, preempt, or IRQ locks are held:
>
>   * reject_subprog_rcu_lock_throw: subprog acquires bpf_rcu_read_lock and
>     then calls bpf_throw
>   * reject_subprog_throw_preempt_lock: always-throwing subprog called while
>     caller holds bpf_preempt_disable
>   * reject_subprog_throw_irq_lock: always-throwing subprog called while
>     caller holds bpf_local_irq_save
>
> Assisted-by: Claude:claude-opus-4-6
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
> ---

Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

> [...]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs
  2026-03-20  0:08 [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Ihor Solodrai
                   ` (2 preceding siblings ...)
  2026-03-21 18:52 ` Kumar Kartikeya Dwivedi
@ 2026-03-21 20:00 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-21 20:00 UTC (permalink / raw)
  To: Ihor Solodrai
  Cc: ast, andrii, daniel, eddyz87, martin.lau, memxor, bpf,
	linux-kernel, kernel-team

Hello:

This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Thu, 19 Mar 2026 17:08:08 -0700 you wrote:
> process_bpf_exit_full() passes check_lock = !curframe to
> check_resource_leak(), which is false in cases when bpf_throw() is
> called from a static subprog. This makes check_resource_leak() to skip
> validation of active_rcu_locks, active_preempt_locks, and
> active_irq_id on exception exits from subprogs.
> 
> At runtime bpf_throw() unwinds the stack via ORC without releasing any
> user-acquired locks, which may cause various issues as the result.
> 
> [...]

Here is the summary with links:
  - [bpf,v2,1/2] bpf: Fix exception exit lock checking for subprogs
    https://git.kernel.org/bpf/bpf/c/6c2128505f61
  - [bpf,v2,2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs
    https://git.kernel.org/bpf/bpf/c/a1e5c46eaed3

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-03-21 20:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-20  0:08 [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Ihor Solodrai
2026-03-20  0:08 ` [PATCH bpf v2 2/2] selftests/bpf: Add tests for bpf_throw lock leak from subprogs Ihor Solodrai
2026-03-21 16:55   ` Yonghong Song
2026-03-21 18:53   ` Kumar Kartikeya Dwivedi
2026-03-21 16:34 ` [PATCH bpf v2 1/2] bpf: Fix exception exit lock checking for subprogs Yonghong Song
2026-03-21 18:52 ` Kumar Kartikeya Dwivedi
2026-03-21 20:00 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox