Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Simplify bpf_timer_cancel()

Remove lock from the bpf_timer_cancel() helper. The lock does not
protect from concurrent modification of the bpf_async_cb data fields as
those are modified in the callback without locking.

Use guard(rcu)() instead of pair of explicit lock()/unlock().

Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Link: https://lore.kernel.org/r/20260120-timer_nolock-v6-4-670ffdd787b4@meta.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Mykyta Yatsenko and committed by
Alexei Starovoitov
83c9030c 8bb1e32b

+11 -16
+11 -16
kernel/bpf/helpers.c
··· 1471 1471 .arg3_type = ARG_ANYTHING, 1472 1472 }; 1473 1473 1474 - BPF_CALL_1(bpf_timer_cancel, struct bpf_async_kern *, timer) 1474 + BPF_CALL_1(bpf_timer_cancel, struct bpf_async_kern *, async) 1475 1475 { 1476 1476 struct bpf_hrtimer *t, *cur_t; 1477 1477 bool inc = false; ··· 1479 1479 1480 1480 if (in_nmi()) 1481 1481 return -EOPNOTSUPP; 1482 - rcu_read_lock(); 1483 - __bpf_spin_lock_irqsave(&timer->lock); 1484 - t = timer->timer; 1485 - if (!t) { 1486 - ret = -EINVAL; 1487 - goto out; 1488 - } 1482 + 1483 + guard(rcu)(); 1484 + 1485 + t = READ_ONCE(async->timer); 1486 + if (!t) 1487 + return -EINVAL; 1489 1488 1490 1489 cur_t = this_cpu_read(hrtimer_running); 1491 1490 if (cur_t == t) { ··· 1492 1493 * its own timer the hrtimer_cancel() will deadlock 1493 1494 * since it waits for callback_fn to finish. 1494 1495 */ 1495 - ret = -EDEADLK; 1496 - goto out; 1496 + return -EDEADLK; 1497 1497 } 1498 1498 1499 1499 /* Only account in-flight cancellations when invoked from a timer ··· 1515 1517 * cancelling and waiting for it synchronously, since it might 1516 1518 * do the same. Bail! 1517 1519 */ 1518 - ret = -EDEADLK; 1519 - goto out; 1520 + atomic_dec(&t->cancelling); 1521 + return -EDEADLK; 1520 1522 } 1521 1523 drop: 1522 1524 bpf_async_update_prog_callback(&t->cb, NULL, NULL); 1523 - out: 1524 - __bpf_spin_unlock_irqrestore(&timer->lock); 1525 1525 /* Cancel the timer and wait for associated callback to finish 1526 1526 * if it was running. 1527 1527 */ 1528 - ret = ret ?: hrtimer_cancel(&t->timer); 1528 + ret = hrtimer_cancel(&t->timer); 1529 1529 if (inc) 1530 1530 atomic_dec(&t->cancelling); 1531 - rcu_read_unlock(); 1532 1531 return ret; 1533 1532 } 1534 1533