From: sashiko-bot@kernel.org
To: "Mayank Rungta" <mrungta@google.com>
Cc: linux-watchdog@vger.kernel.org
Subject: Re: [PATCH v2 3/5] genirq: Export NMI APIs
Date: Sat, 29 Aug 2026 01:15:50 +0000 [thread overview]
Message-ID: <20260829011550.ECF091F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260828-qcom-wdt-nmi-series-v2-3-363979fe6b6b@google.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Exporting `free_nmi()` and `disable_nmi()` allows loadable modules to manage NMIs, but these APIs fundamentally fail to synchronize with in-flight NMI handlers, introducing a race condition that leads to kernel panics on module unload.
Pre-existing issues:
- [High] `__cleanup_nmi()` fails to acquire `desc->request_mutex` when tearing down an NMI. This allows concurrent IRQ request/free operations to race, corrupting IRQ resource state and bypassing hardware resource allocation.
- [High] Concurrent NMI delivery during `free_nmi()` teardown leads to a NULL pointer dereference in `handle_fasteoi_nmi()` because `desc->action` is cleared before `__synchronize_hardirq()` waits for in-flight NMIs.
- [Medium] `free_nmi()` ignores the provided `dev_id` parameter, bypassing ownership validation and allowing any module to inadvertently or maliciously unregister an NMI owned by another subsystem.
--
commit cf44d4cc82f985321cdf77cbbbd3469b85de0426
Author: Mayank Rungta <mrungta@google.com>
genirq: Export NMI APIs
This commit exports request_nmi(), free_nmi(), enable_nmi(),
disable_nmi_nosync(), and disable_nmi() with EXPORT_SYMBOL_GPL to allow
loadable kernel modules to register and manage NMIs.
> diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
> index 40013aa94481e..ded8cc33381cc 100644
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
[ ... ]
> @@ -2110,6 +2113,7 @@ const void *free_nmi(unsigned int irq, void *dev_id)
>
> return __cleanup_nmi(irq, desc);
> }
> +EXPORT_SYMBOL_GPL(free_nmi);
[Severity: High]
Is it safe to export free_nmi() and disable_nmi() given they can introduce
a race condition that leads to kernel panics on module unload?
When a module unloads, free_nmi() calls __cleanup_nmi(), which uses
__synchronize_hardirq() to wait for handlers on other CPUs to finish.
__synchronize_hardirq() checks the IRQD_IRQ_INPROGRESS flag:
kernel/irq/manage.c:__synchronize_hardirq() {
...
while (irqd_irq_inprogress(&desc->irq_data))
cpu_relax();
...
}
However, NMI handlers like handle_fasteoi_nmi() bypass standard IRQ locking
and never set IRQD_IRQ_INPROGRESS:
kernel/irq/chip.c:handle_fasteoi_nmi() {
...
res = action->handler(irq, action->dev_id);
...
}
Consequently, __synchronize_hardirq() returns immediately. The module's text
segment could then be unmapped while the NMI handler is still executing,
leading to a page fault.
[Severity: High]
This is a pre-existing issue, but can concurrent NMI delivery during
free_nmi() teardown lead to a NULL pointer dereference in
handle_fasteoi_nmi()?
During free_nmi(), __cleanup_nmi() sets desc->action = NULL and drops
desc->lock before calling __synchronize_hardirq():
kernel/irq/manage.c:__cleanup_nmi() {
...
desc->action = NULL;
irq_settings_clr_disable_unlazy(desc);
irq_shutdown(desc);
...
/* Ensure all in-flight NMI handlers on other CPUs complete before freeing action */
__synchronize_hardirq(desc, true);
...
}
If an NMI fires concurrently, the dispatcher handle_fasteoi_nmi() executes
on another CPU without taking desc->lock. It reads desc->action and
unconditionally dereferences it without checking for NULL:
kernel/irq/chip.c:handle_fasteoi_nmi() {
...
struct irqaction *action = desc->action;
...
res = action->handler(irq, action->dev_id);
...
}
[Severity: High]
This isn't a bug introduced by this patch, but it appears __cleanup_nmi()
fails to acquire desc->request_mutex when tearing down an NMI.
__cleanup_nmi() drops desc->lock and performs teardown (including
irq_release_resources()) without holding desc->request_mutex:
kernel/irq/manage.c:__cleanup_nmi() {
...
irq_release_resources(desc);
...
}
Conversely, __setup_irq() relies exclusively on desc->request_mutex for
serialization. If __cleanup_nmi() runs concurrently with __setup_irq() (e.g.
during a rapid module reload or concurrent requests), they can race.
__setup_irq() may read a non-NULL desc->action and skip resource allocation:
kernel/irq/manage.c:__setup_irq() {
...
if (!desc->action) {
ret = irq_request_resources(desc);
...
}
Could this lead to bypassed hardware resource allocation or corrupted hardware
state for IRQ resources?
[Severity: Medium]
This is a pre-existing issue, but I noticed free_nmi() ignores the provided
dev_id parameter.
The free_nmi() API accepts a dev_id parameter, but delegates to
__cleanup_nmi() which drops the token entirely:
kernel/irq/manage.c:free_nmi() {
...
return __cleanup_nmi(irq, desc);
}
Inside __cleanup_nmi(), the action is unconditionally unlinked and torn
down without checking if its dev_id matches the caller's cookie:
kernel/irq/manage.c:__cleanup_nmi() {
...
if (!WARN_ON(desc->action == NULL)) {
action = desc->action;
irq_pm_remove_action(desc, action);
...
}
Unlike free_irq(), which verifies action->dev_id == dev_id, this lacks
ownership validation. Could a buggy loadable module unilaterally destroy
another component's NMI by passing an incorrect IRQ number or a
NULL cookie to free_nmi()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-qcom-wdt-nmi-series-v2-0-363979fe6b6b@google.com?part=3
next prev parent reply other threads:[~2026-08-29 1:15 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-29 0:59 [PATCH v2 0/5] watchdog: qcom: Support NMI pretimeout warnings Mayank Rungta
2026-08-29 0:59 ` [PATCH v2 1/5] genirq: Synchronize in-flight handlers during NMI teardown Mayank Rungta
2026-08-29 1:14 ` sashiko-bot
2026-08-31 18:16 ` Doug Anderson
2026-08-29 0:59 ` [PATCH v2 2/5] genirq: Implement synchronous disable_nmi() Mayank Rungta
2026-08-29 1:18 ` sashiko-bot
2026-08-31 18:16 ` Doug Anderson
2026-08-29 0:59 ` [PATCH v2 3/5] genirq: Export NMI APIs Mayank Rungta
2026-08-29 1:15 ` sashiko-bot [this message]
2026-08-31 18:17 ` Doug Anderson
2026-08-29 0:59 ` [PATCH v2 4/5] watchdog: pretimeout: Protect governor access with RCU for NMI safety Mayank Rungta
2026-08-31 18:17 ` Doug Anderson
2026-08-29 0:59 ` [PATCH v2 5/5] watchdog: qcom: Register pretimeout interrupt as NMI Mayank Rungta
2026-08-29 1:15 ` sashiko-bot
2026-08-31 18:17 ` Doug Anderson
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=20260829011550.ECF091F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-watchdog@vger.kernel.org \
--cc=mrungta@google.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox