Re: [PATCH 2/3] genirq: Export NMI APIs
[email protected] Thu, 30 Jul 2026 21:47:58 +0000
| Newsgroups | org.kernel.vger.linux-watchdog |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(= s) to consider: Pre-existing issues: - [Critical] Exporting NMI APIs to loadable modules exposes an unmitigated = Use-After-Free and kernel panic during module unload due to the lack of NMI= synchronization. - [High] Lack of request_mutex locking in free_nmi() and the request_nmi() = error path leads to data races, resource double-frees, and refcount underfl= ows. -- --- Patch [2]: [PATCH 2/3] genirq: Export NMI APIs --- commit dfe5c7d2a97396d411087d0eb1dca59bbf190e69 Author: Mayank Rungta <[email protected]> genirq: Export NMI APIs Currently, request_nmi(), free_nmi(), enable_nmi() and disable_nmi_nosync() are restricted to built-in kernel code because they are not exported to loadable modules. Export these APIs to allow loadable modules to register and manage NMIs. > diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c > index 2fbff2618a1e2..fb0b8da32f4c1 100644 > --- a/kernel/irq/manage.c > +++ b/kernel/irq/manage.c [ ... ] > @@ -2080,6 +2082,7 @@ const void *free_nmi(unsigned int irq, void *dev_id) > =20 > return __cleanup_nmi(irq, desc); > } > +EXPORT_SYMBOL_GPL(free_nmi); [Severity: Critical] This is a pre-existing issue, but does exporting this API to loadable modul= es expose an unmitigated use-after-free and kernel panic during module unload? When a module unloads and calls free_nmi(), __cleanup_nmi() uninstalls the handler and calls kfree(action) without waiting for executing NMI handlers = to finish, such as via synchronize_rcu(): kernel/irq/manage.c:__cleanup_nmi() { ... unregister_handler_proc(irq, action); kfree(action); ... } Concurrent NMIs on other CPUs bypass normal IRQ locks and can continue to execute the handler locklessly: kernel/irq/chip.c:handle_fasteoi_nmi() { ... struct irqaction *action =3D desc->action; ... res =3D action->handler(irq, action->dev_id); ... } Since the module text section is unmapped upon unload, couldn't an actively executing concurrent NMI jump into unmapped memory, resulting in a fatal panic? [ ... ] > @@ -2342,6 +2345,7 @@ int request_nmi(unsigned int irq, irq_handler_t han= dler, > =20 > return retval; > } > +EXPORT_SYMBOL_GPL(request_nmi); [Severity: High] This is a pre-existing issue, but do request_nmi() and free_nmi() lack request_mutex locking around their cleanup paths? According to IRQ subsystem locking rules, desc->request_mutex serializes resource allocation and teardown. However, both free_nmi() and the failure path of request_nmi() invoke __cleanup_nmi() without holding this mutex. In request_nmi(): kernel/irq/manage.c:request_nmi() { ... if (retval) { __cleanup_nmi(irq, desc); return -EINVAL; } ... } Inside __cleanup_nmi(), resource teardowns are executed unconditionally outside of desc->lock: kernel/irq/manage.c:__cleanup_nmi() { ... irq_release_resources(desc); irq_chip_pm_put(&desc->irq_data); module_put(desc->owner); ... } If request_nmi() fails concurrently with another request_nmi() or free_nmi(= ), won't this lead to resource double-frees and unbalanced reference counts? --=20 Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260730-qcom-wdt-n= [email protected]?part=3D2