From: Boqun Feng <boqun@kernel.org>
To: Thomas Gleixner <tglx@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
linux-kernel@vger.kernel.org, linux-tip-commits@vger.kernel.org,
x86@kernel.org
Subject: Re: [PATCH] locking: Revert switching guards to _irq_{disable,enable}()
Date: Tue, 25 Aug 2026 18:33:34 -0700 [thread overview]
Message-ID: <ao5CbqVDCZvBaLSy@tardis.local> (raw)
In-Reply-To: <ao4ps1OXRluyu_aa@tardis.local>
On Tue, Aug 25, 2026 at 04:48:03PM -0700, Boqun Feng wrote:
> On Tue, Aug 25, 2026 at 04:28:59PM -0700, Boqun Feng wrote:
> > On Wed, Aug 26, 2026 at 12:59:25AM +0200, Thomas Gleixner wrote:
> > > On Mon, Aug 24 2026 at 18:33, Boqun Feng wrote:
> > > > On Mon, Aug 24, 2026 at 12:55:23PM +0200, Peter Zijlstra wrote:
> > > >>
> > > >> While the guards are properly nested, not all wrapped code is nice, as already
> > > >> highlighted by that fair.c hunk.
> > > >>
> > > >> Syzbot found another instance of this pattern in posix_timer_delete(), which
> > > >> does spin_unlock_irq()+spin_lock_irq() inside scoped_guard(spinlock_irq).
> > > >> Combined with this patch, that goes sideways most spectacular.
> > > >>
>
> I'm not saying the posix_timer_delete() implementation has any problem,
> but TBH allowing spin_unlock_irq()+spin_lock_irq() inside
> scoped_guard(spinlock_irq) is questionable design, and can result into
> foot-gun code like:
>
> scoped_guard(spinlock_irq) {
> ...
> spin_unlock_irq();
> if (cond)
> return; // BOOM, double unlock
> spin_lock_irq();
> }
>
> Sure, if handling carefully, it won't cause problem, but it undermines
> the easy-to-use and less-err-prone features of scoped_guard().
>
One idea is since each scoped_guard() creates a scope guard, the guard
should be used as token for the inner unlock (guard_drop()) and lock
(guard_retake()). So the above code become:
scoped_guard(spinlock_irq, ...) {
guard_drop(spinlock_irq, &scope);
// ^ scope is modified to know that no more unlock is
// needed.
if (cond)
return; // no double unlock
guard_retake(spinlock_irq, &scope, ...);
}
The following shows the idea (only compile test). Also applies to
lock_timer as well.
Regards,
Boqun
--------------------------------->8
diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
index b1b5698cbf1b..459c533e4cc8 100644
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -249,6 +249,19 @@ const volatile void * __must_check_fn(const volatile void *val)
*/
#define retain_and_null_ptr(p) ((void)__get_and_null(p, NULL))
+/*
+ * Drops a scoped guard
+ */
+#define guard_drop(name, p) class_##name##_destructor(p)
+
+/*
+ * Re-takes a scoped guard
+ */
+#define guard_retake(name, p, ...) \
+do { \
+ class_##name##_retake(p, __VA_ARGS__); \
+} while (0)
+
/*
* DEFINE_CLASS(name, type, exit, init, init_args...):
* helper to define the destructor and constructor for a type.
@@ -492,7 +505,10 @@ typedef struct { \
static __always_inline void class_##_name##_destructor(class_##_name##_t *_T) \
__no_context_analysis \
{ \
- _unlock; \
+ if ((_T)->lock) { \
+ _unlock; \
+ (_T)->lock = NULL; \
+ } \
} \
\
__DEFINE_GUARD_LOCK_PTR(_name, &_T->lock)
@@ -505,6 +521,14 @@ class_##_name##_t class_##_name##_constructor(_type *l) \
class_##_name##_t _t = { .lock = l }, *_T = &_t; \
__VA_ARGS__; \
return _t; \
+} \
+static __always_inline __nonnull_args(2) \
+void class_##_name##_retake(class_##_name##_t *_T, _type *l) \
+ __no_context_analysis \
+{ \
+ BUG_ON((_T)->lock); \
+ (_T)->lock = l; \
+ __VA_ARGS__; \
}
#define __DEFINE_LOCK_GUARD_0(_name, ...) \
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 436ba794cc0b..b34e8292e989 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1026,7 +1026,8 @@ static inline void posix_timer_cleanup_ignored(struct k_itimer *tmr)
}
}
-static void posix_timer_delete(struct k_itimer *timer)
+static void posix_timer_delete(struct k_itimer *timer,
+ class_spinlock_irq_t *guard)
{
/*
* Invalidate the timer, remove it from the linked list and remove
@@ -1057,9 +1058,10 @@ static void posix_timer_delete(struct k_itimer *timer)
while (timer->kclock->timer_del(timer) == TIMER_RETRY) {
guard(rcu)();
- spin_unlock_irq(&timer->it_lock);
+
+ guard_drop(spinlock_irq, guard);
timer_wait_running(timer);
- spin_lock_irq(&timer->it_lock);
+ guard_retake(spinlock_irq, guard, &timer->it_lock);
}
}
@@ -1069,8 +1071,14 @@ SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
struct k_itimer *timer;
scoped_timer_get_or_fail(timer_id) {
+ // Needs a better to "cast" a guard of "lock_timer" to
+ // "spinlock_irq".
+ class_spinlock_irq_t guard = {
+ .lock = &scoped_timer->it_lock,
+ };
+
timer = scoped_timer;
- posix_timer_delete(timer);
+ posix_timer_delete(timer, &guard);
}
/* Remove it from the hash, which frees up the timer ID */
posix_timer_unhash_and_free(timer);
@@ -1101,7 +1109,7 @@ void exit_itimers(struct task_struct *tsk)
/* The timers are not longer accessible via tsk::signal */
hlist_for_each_entry_safe(timer, next, &timers, list) {
scoped_guard (spinlock_irq, &timer->it_lock)
- posix_timer_delete(timer);
+ posix_timer_delete(timer, &scope);
posix_timer_unhash_and_free(timer);
cond_resched();
}
next prev parent reply other threads:[~2026-08-26 1:33 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 16:14 [PATCH v4 00/17] Refcounted interrupt disable and SpinLockIrq for Rust Boqun Feng
2026-08-04 16:14 ` [PATCH v4 01/17] preempt: Track NMI nesting to separate per-CPU counter Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Joel Fernandes
2026-08-04 16:14 ` [PATCH v4 02/17] preempt: Introduce HARDIRQ_DISABLE_BITS Boqun Feng
2026-08-05 6:31 ` Peter Zijlstra
2026-08-05 6:59 ` Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 03/17] preempt: Introduce __preempt_count_{sub,add}_return() Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 04/17] openrisc: Include <linux/cpumask.h> in smp.h Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Lyude Paul
2026-08-04 16:14 ` [PATCH v4 05/17] irq & spin_lock: Add counted interrupt disabling/enabling Boqun Feng
2026-08-04 18:20 ` Boqun Feng
2026-08-04 18:26 ` [PATCH v4.1 " Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` [tip: locking/core] irq,spin_lock: " tip-bot2 for Boqun Feng
2026-08-04 20:51 ` [PATCH v4 05/17] irq & spin_lock: " Shrikanth Hegde
2026-08-04 21:08 ` Boqun Feng
2026-08-05 6:36 ` Peter Zijlstra
2026-08-05 7:07 ` Boqun Feng
2026-08-05 7:09 ` Shrikanth Hegde
2026-08-05 7:19 ` Boqun Feng
2026-08-05 13:53 ` Boqun Feng
2026-08-05 14:10 ` Shrikanth Hegde
2026-08-05 14:20 ` Boqun Feng
2026-08-05 14:56 ` Shrikanth Hegde
2026-08-05 15:11 ` Boqun Feng
2026-08-05 16:53 ` Shrikanth Hegde
2026-08-05 17:38 ` Boqun Feng
2026-08-05 18:07 ` Boqun Feng
2026-08-04 16:14 ` [PATCH v4 06/17] irq: Add KUnit test for refcounted interrupt enable/disable Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Lyude Paul
2026-08-10 8:57 ` tip-bot2 for Lyude Paul
2026-08-04 16:14 ` [PATCH v4 07/17] locking: Switch to _irq_{disable,enable}() variants in cleanup guards Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-24 10:47 ` Peter Zijlstra
2026-08-24 10:55 ` [PATCH] locking: Revert switching guards to _irq_{disable,enable}() Peter Zijlstra
2026-08-24 11:01 ` [tip: locking/urgent] " tip-bot2 for Peter Zijlstra
2026-08-25 1:33 ` [PATCH] " Boqun Feng
2026-08-25 22:59 ` Thomas Gleixner
2026-08-25 23:28 ` Boqun Feng
2026-08-25 23:48 ` Boqun Feng
2026-08-26 1:33 ` Boqun Feng [this message]
2026-08-04 16:14 ` [PATCH v4 08/17] sched: Remove the unused preempt_offset parameter of __cant_sleep() Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 09/17] sched: Avoid signed comparison of preempt_count() in __cant_migrate() Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 10/17] preempt: Introduce HAS_SEPARATE_PREEMPT_RESCHED_BITS Boqun Feng
2026-08-04 20:11 ` Shrikanth Hegde
2026-08-05 6:54 ` Boqun Feng
2026-08-05 7:15 ` Shrikanth Hegde
2026-08-05 7:27 ` Boqun Feng
2026-08-06 0:58 ` Boqun Feng
2026-08-04 21:09 ` Shrikanth Hegde
2026-08-04 23:14 ` Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 11/17] arm64: sched/preempt: Enable HAS_SEPARATE_PREEMPT_RESCHED_BITS Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 12/17] s390/preempt: " Boqun Feng
2026-08-04 20:27 ` Shrikanth Hegde
2026-08-05 9:42 ` Peter Zijlstra
2026-08-05 12:37 ` Shrikanth Hegde
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Heiko Carstens
2026-08-10 8:57 ` tip-bot2 for Heiko Carstens
2026-08-04 16:14 ` [PATCH v4 13/17] rust: Introduce interrupt module Boqun Feng
2026-08-04 16:14 ` [PATCH v4 14/17] rust: helper: Add spin_{un,}lock_irq_{enable,disable}() helpers Boqun Feng
2026-08-04 16:14 ` [PATCH v4 15/17] rust: sync: Use super::* in spinlock.rs Boqun Feng
2026-08-04 16:14 ` [PATCH v4 16/17] rust: sync: Add SpinLockIrq Boqun Feng
2026-08-04 16:14 ` [PATCH v4 17/17] rust: sync: Introduce SpinLockIrq::lock_with() and friends Boqun Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ao5CbqVDCZvBaLSy@tardis.local \
--to=boqun@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.