All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Boqun Feng" <boqun@kernel.org>
Cc: ojeda@kernel.org, bpf@vger.kernel.org
Subject: Re: [PATCH v2 05/12] irq & spin_lock: Add counted interrupt disabling/enabling
Date: Tue, 26 May 2026 17:54:08 +0000	[thread overview]
Message-ID: <20260526175409.7CFCC1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260526152148.30514-6-boqun@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] An NMI occurring inside local_interrupt_enable() corrupts the per-CPU saved IRQ flags, leading to permanently disabled hardware interrupts.
- [High] Skipping softirq processing in `__irq_exit_rcu()` without re-triggering it in `local_interrupt_enable()` leads to indefinite softirq starvation.
--

commit 2a089d1e2525d387b14ef2c6eb7f3576f07d6bc4
Author: Boqun Feng <boqun@kernel.org>

irq & spin_lock: Add counted interrupt disabling/enabling

This commit introduces new local interrupt disabling APIs that use a per-CPU
counter to support nesting. This avoids accidental early interrupt enabling
when locks are nested or used with guard facilities.

Link: https://patch.msgid.link/20260121223933.1568682-6-lyude@redhat.com

> diff --git a/include/linux/interrupt_rc.h b/include/linux/interrupt_rc.h
> new file mode 100644
> --- /dev/null
> +++ b/include/linux/interrupt_rc.h
[ ... ]
> +static inline void local_interrupt_enable(void)
> +{
> +	int new_count;
> +
> +	new_count = hardirq_disable_exit();
> +
> +	if ((new_count & HARDIRQ_DISABLE_MASK) == 0) {
> +		unsigned long flags;
> +
> +		flags = raw_cpu_read(local_interrupt_disable_state.flags);

[Severity: Critical]
Can the per-CPU saved IRQ flags be corrupted if an NMI occurs here?

After hardirq_disable_exit() decrements the count to zero, but before the
saved flags are read, there is an unprotected window. If an NMI fires in
this window, the interrupted thread's count is 0 but its hardware IRQs are
still disabled.

If the NMI handler or a function it calls uses local_interrupt_disable() or
spin_lock_irq_disable(), it will see the count is 0, assume it is the
outermost caller, and overwrite the per-CPU flags with its own IRQ state.

Since hardware IRQs were disabled when the NMI hit, the saved flags will
reflect disabled IRQs. When the NMI returns, the interrupted thread reads
these corrupted per-CPU flags and passes them to local_irq_restore(),
which would permanently disable hardware interrupts on that CPU.

> +		local_irq_restore(flags);
> +		/*
> +		 * TODO: re-read preempt count can be avoided, but it needs
> +		 * should_resched() taking another parameter as the current
> +		 * preempt count
> +		 */
> +#ifdef CONFIG_PREEMPTION
> +		if (should_resched(0))
> +			__preempt_schedule();
> +#endif
> +	}
> +}

[ ... ]
> diff --git a/kernel/softirq.c b/kernel/softirq.c
> index 10af5ed859e73..d1ab1799794ca 100644
> --- a/kernel/softirq.c
> +++ b/kernel/softirq.c
[ ... ]
> @@ -728,7 +731,16 @@ static inline void __irq_exit_rcu(void)
>  #endif
>  	account_hardirq_exit(current);
>  	preempt_count_sub(HARDIRQ_OFFSET);
> -	if (!in_interrupt() && local_softirq_pending()) {
> +	/*
> +	 * Interrupts may happen between hardirq_disable_enter() and
> +	 * local_irq_save() in local_interrupt_disable(), if irq_exit() invokes
> +	 * softirq here, we may have a softirq handler calling
> +	 * local_interrupt_disable() but it won't disable the irq because
> +	 * hardirq disabling count is already 1, hence we need to prevent
> +	 * invoking softirq when a local_interrupt_disable() is ongoing.
> +	 */
> +	if (!in_interrupt() && !hardirq_disable_count() &&
> +	    local_softirq_pending()) {

[Severity: High]
Does skipping softirq processing here lead to indefinite softirq starvation?

By skipping invoke_softirq() when hardirq_disable_count() > 0, any scheduled
softirqs (such as timers, RCU callbacks, or networking) are left pending.

When the critical section ends, local_interrupt_enable() decrements the
count and re-enables hardware interrupts, but it does not check
local_softirq_pending() to flush these deferred softirqs.

Will these pending softirqs stall indefinitely until another, unrelated
hardware interrupt fires, potentially causing RCU stalls or network hangs
in low-activity periods?

>  		/*
>  		 * If we left hrtimers unarmed, make sure to arm them now,
>  		 * before enabling interrupts to run SoftIRQ.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260526152148.30514-1-boqun@kernel.org?part=5

  parent reply	other threads:[~2026-05-26 17:54 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-26 15:21 [PATCH v2 00/12] Refcounted interrupt disable and SpinLockIrq for rust (Part 1) Boqun Feng
2026-05-26 15:21 ` [PATCH v2 01/12] preempt: Track NMI nesting to separate per-CPU counter Boqun Feng
2026-05-26 16:12   ` sashiko-bot
2026-06-04 12:36   ` Boqun Feng
2026-05-26 15:21 ` [PATCH v2 02/12] preempt: Introduce HARDIRQ_DISABLE_BITS Boqun Feng
2026-05-26 15:21 ` [PATCH v2 03/12] preempt: Introduce __preempt_count_{sub, add}_return() Boqun Feng
2026-05-26 15:21 ` [PATCH v2 04/12] openrisc: Include <linux/cpumask.h> in smp.h Boqun Feng
2026-05-26 15:21 ` [PATCH v2 05/12] irq & spin_lock: Add counted interrupt disabling/enabling Boqun Feng
2026-05-26 16:19   ` bot+bpf-ci
2026-05-26 17:54   ` sashiko-bot [this message]
2026-05-28 10:43   ` Peter Zijlstra
2026-05-28 14:31     ` Boqun Feng
2026-05-26 15:21 ` [PATCH v2 06/12] irq: Add KUnit test for refcounted interrupt enable/disable Boqun Feng
2026-05-26 18:18   ` sashiko-bot
2026-05-26 15:21 ` [PATCH v2 07/12] locking: Switch to _irq_{disable,enable}() variants in cleanup guards Boqun Feng
2026-05-28 10:45   ` Peter Zijlstra
2026-05-28 14:31     ` Boqun Feng
2026-05-26 15:21 ` [PATCH v2 08/12] sched: Remove the unused preempt_offset parameter of __cant_sleep() Boqun Feng
2026-05-26 15:21 ` [PATCH v2 09/12] sched: Avoid signed comparison of preempt_count() in __cant_migrate() Boqun Feng
2026-05-26 15:21 ` [PATCH v2 10/12] preempt: Introduce HAS_SEPARATE_PREEMPT_RESCHED_BITS Boqun Feng
2026-05-26 19:57   ` sashiko-bot
2026-06-04 12:40   ` Boqun Feng
2026-05-26 15:21 ` [PATCH v2 11/12] arm64: sched/preempt: Enable HAS_SEPARATE_PREEMPT_RESCHED_BITS Boqun Feng
2026-05-28 10:50   ` Peter Zijlstra
2026-05-26 15:21 ` [PATCH v2 12/12] s390/preempt: " Boqun Feng
2026-05-28 10:53   ` Peter Zijlstra
2026-05-28 14:41     ` Boqun Feng
2026-05-28 15:18       ` Heiko Carstens
2026-05-27 16:18 ` [PATCH v2 00/12] Refcounted interrupt disable and SpinLockIrq for rust (Part 1) Peter Zijlstra
2026-05-27 16:33   ` Boqun Feng
2026-06-03 19:20     ` 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=20260526175409.7CFCC1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=boqun@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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.