mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf v1 RESEND] bpf: Fix timer_lockup deadlock using atomic_fetch_inc()
@ 2026-09-02  0:51 Tiezhu Yang
  2026-09-02  1:13 ` Kumar Kartikeya Dwivedi
  2026-09-02  1:46 ` bot+bpf-ci
  0 siblings, 2 replies; 4+ messages in thread
From: Tiezhu Yang @ 2026-09-02  0:51 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
	Ihor Solodrai
  Cc: loongarch, bpf, linux-kernel

When testing the BPF selftest "sudo ./test_progs -t timer_lockup", there
is a kernel lockup and panic on LoongArch:

  watchdog: BUG: soft lockup - CPU#1 stuck for 8s! [test_progs:39601]
  Kernel panic - not syncing: softlockup: hung tasks
  ...
  Call Trace:
  ...
  [<9000000000c40e98>] panic+0x44/0x48
  [<9000000000e8b000>] watchdog_timer_fn+0x500/0x520
  [<9000000000dfd9a4>] __hrtimer_run_queues+0xc4/0x530
  [<9000000000dffe90>] hrtimer_interrupt+0x140/0x320
  ...
  [<9000000002ad9e4c>] _raw_spin_unlock_irqrestore+0x8c/0xc0
  [<9000000000dfe9e0>] hrtimer_try_to_cancel.part.0+0x70/0x350
  [<9000000000dfed58>] hrtimer_cancel+0x38/0x80
  [<9000000000f6d944>] bpf_timer_cancel+0x94/0x1e0
  [<ffff80000200fad0>] bpf_prog_108ab87b32f22e44_timer_cb1+0xb0/0xfc
  [<9000000000f6b838>] bpf_timer_cb+0x98/0x170
  [<9000000000dfdaac>] __hrtimer_run_queues+0x1cc/0x530
  [<9000000000dfde94>] hrtimer_run_softirq+0x84/0xd0
  ...
  [<900000000271d9e0>] bpf_test_run+0x1c0/0x5c0
  [<900000000271f548>] bpf_prog_test_run_skb+0x6e8/0xe20
  [<9000000000f39940>] __sys_bpf+0x1690/0x2c50
  [<9000000000f3af28>] sys_bpf+0x28/0x40
  [<9000000002ac2d68>] do_syscall+0x108/0x5e0
  [<9000000000c6a850>] handle_syscall+0xd0/0x170

In bpf_timer_cancel() of kernel/bpf/helpers.c, it explicitly notes that
"Need full barrier after relaxed atomic_inc" to ensure global visibility
of the cancelling state before performing the lockless dependency checks.

However, on weakly-ordered architectures such as LoongArch, the current
combination of a relaxed atomic_inc() followed by smp_mb__after_atomic()
fails to guarantee the physical store-load ordering because the latter
currently expands to an empty compiler barrier rather than a hardware
data barrier on LoongArch.

This allows a subsequent read to bypass the prior write due to store-load
reordering, enabling concurrent CPUs to simultaneously bypass the software
deadlock detection, enter hrtimer_cancel(), and then trigger a severe ABBA
deadlock in the hrtimer core.

Instead of relying on arch-specific macro implementations which may vary
in strictness, fix this issue directly in the BPF core helper by replacing
atomic_inc() and smp_mb__after_atomic() with a single atomic_fetch_inc()
to provide full ordering natively.

This ensures that the BPF core satisfies its strict store-load ordering
requirement in a self-contained manner to eliminate the deadlock under
weak memory models, and also hardens the defensive programming in the
BPF core, making the lockless deadlock detection logic immune to any
platform-level barrier interpretation variations.

With this patch, the BPF timer_lockup selftest was stressed for 10000
consecutive loops on a physical LoongArch machine without encountering
any further lockups or warnings on LoongArch:

  for i in {1..10000}; do sudo ./test_progs -t timer_lockup; done

Reported-by: Vincent Li <vincent.mc.li@gmail.com>
Closes: https://lore.kernel.org/loongarch/CAK3+h2xOSEZUHhou7N2cRL-aGrZCNSm45g+P7thObMe+fpgYCA@mail.gmail.com/
Fixes: d4523831f07a ("bpf: Fail bpf_timer_cancel when callback is being cancelled")
Cc: stable@vger.kernel.org
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
Resend due to
"Can not connect to recipient's server because of unstable network or firewall filter."

 kernel/bpf/helpers.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index b3cc5c8fc875..7d89dc143883 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -1591,9 +1591,7 @@ BPF_CALL_1(bpf_timer_cancel, struct bpf_async_kern *, async)
 	 */
 	if (!cur_t)
 		goto drop;
-	atomic_inc(&t->cancelling);
-	/* Need full barrier after relaxed atomic_inc */
-	smp_mb__after_atomic();
+	atomic_fetch_inc(&t->cancelling);
 	inc = true;
 	if (atomic_read(&cur_t->cancelling)) {
 		/* We're cancelling timer t, while some other timer callback is
-- 
2.42.0


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

end of thread, other threads:[~2026-09-02  3:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-02  0:51 [PATCH bpf v1 RESEND] bpf: Fix timer_lockup deadlock using atomic_fetch_inc() Tiezhu Yang
2026-09-02  1:13 ` Kumar Kartikeya Dwivedi
2026-09-02  2:42   ` Tiezhu Yang
2026-09-02  1:46 ` bot+bpf-ci

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

all inboxes | Powered by JetHome®