From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Richard Patel <ripatel@wii.dev>,
Thomas Gleixner <tglx@kernel.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.1.y] genirq: Defer kfree(irqaction) until irq_thread_dtor() finishes
Date: Wed, 4 Nov 2026 17:54:14 -0500 [thread overview]
Message-ID: <20261104225336.845493-1-sashal@kernel.org> (raw)
In-Reply-To: <2026110452-liability-uncooked-f75f@gregkh>
From: Richard Patel <ripatel@wii.dev>
[ Upstream commit d04adff6860587e843948b0c31174f8ae11b8dfe ]
When an interrupt thread exits abnormally via do_exit() (e.g. the interrupt
handler oopses) without returning from irq_thread(), a concurrent call to
free_irq() could free the irqaction before the irq_thread_dtor() exit task
work runs.
irq thread (oopsed) free_irq()
------------------- ----------
do_exit()
exit_mm()
complete_vfork_done() -------> kthread_stop() returns
exit_files() ... kfree(action)
exit_task_work()
irq_thread_dtor()
action->... <- use-after-free
Track the pending exit work with the IRQTF_EXIT_WORK thread flag, and have
__free_irq() wait for the bit to clear before kfree().
irq_thread_dtor() only runs on irq_thread abnormal exit. If that dtor also
faults, free_irq() will hang indefinitely, but double IRQ thread faults
require a reboot anyways.
[ tglx: Add missing include ]
Fixes: ed3e694d78cc ("move exit_task_work() past exit_files() et.al.")
Signed-off-by: Richard Patel <ripatel@wii.dev>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261009145842.1616117-2-ripatel@wii.dev
[ sashal: Replaced unavailable kthread_stop_put() with kthread_stop() followed by put_task_struct(). ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/irq/internals.h | 2 ++
kernel/irq/manage.c | 32 ++++++++++++++++++++++----------
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 35e85323940c3..7f1b7c1534d18 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -30,6 +30,7 @@ extern struct irqaction chained_action;
* IRQTF_AFFINITY - irq thread is requested to adjust affinity
* IRQTF_FORCED_THREAD - irq action is force threaded
* IRQTF_READY - signals that irq thread is ready
+ * IRQTF_EXIT_WORK - irq thread exit task_work is pending
*/
enum {
IRQTF_RUNTHREAD,
@@ -37,6 +38,7 @@ enum {
IRQTF_AFFINITY,
IRQTF_FORCED_THREAD,
IRQTF_READY,
+ IRQTF_EXIT_WORK,
};
/*
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a5843563d0154..8827e7cb7166e 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -21,6 +21,7 @@
#include <linux/sched/isolation.h>
#include <uapi/linux/sched/types.h>
#include <linux/task_work.h>
+#include <linux/wait_bit.h>
#include "internals.h"
@@ -1216,17 +1217,14 @@ static void wake_threads_waitq(struct irq_desc *desc)
wake_up(&desc->wait_for_threads);
}
-static void irq_thread_dtor(struct callback_head *unused)
+static void __irq_thread_dtor(struct irqaction *action)
{
struct task_struct *tsk = current;
struct irq_desc *desc;
- struct irqaction *action;
if (WARN_ON_ONCE(!(current->flags & PF_EXITING)))
return;
- action = kthread_data(tsk);
-
pr_err("exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
tsk->comm, tsk->pid, action->irq);
@@ -1243,6 +1241,14 @@ static void irq_thread_dtor(struct callback_head *unused)
irq_finalize_oneshot(desc, action);
}
+static void irq_thread_dtor(struct callback_head *unused)
+{
+ struct irqaction *action = kthread_data(current);
+
+ __irq_thread_dtor(action);
+ clear_and_wake_up_bit(IRQTF_EXIT_WORK, &action->thread_flags);
+}
+
static void irq_wake_secondary(struct irq_desc *desc, struct irqaction *action)
{
struct irqaction *secondary = action->secondary;
@@ -1301,6 +1307,7 @@ static int irq_thread(void *data)
else
handler_fn = irq_thread_fn;
+ set_bit(IRQTF_EXIT_WORK, &action->thread_flags);
init_task_work(&on_exit_work, irq_thread_dtor);
task_work_add(current, &on_exit_work, TWA_NONE);
@@ -1325,6 +1332,7 @@ static int irq_thread(void *data)
* oneshot mask bit can be set.
*/
task_work_cancel_func(current, irq_thread_dtor);
+ clear_and_wake_up_bit(IRQTF_EXIT_WORK, &action->thread_flags);
return 0;
}
@@ -1859,6 +1867,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
return ret;
}
+static void irq_stop_thread(struct irqaction *action)
+{
+ kthread_stop(action->thread);
+ put_task_struct(action->thread);
+ wait_on_bit(&action->thread_flags, IRQTF_EXIT_WORK, TASK_UNINTERRUPTIBLE);
+}
+
/*
* Internal function to unregister an irqaction - used to free
* regular and special interrupts that are part of the architecture.
@@ -1963,12 +1978,9 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)
* the same bit to a newly requested action.
*/
if (action->thread) {
- kthread_stop(action->thread);
- put_task_struct(action->thread);
- if (action->secondary && action->secondary->thread) {
- kthread_stop(action->secondary->thread);
- put_task_struct(action->secondary->thread);
- }
+ irq_stop_thread(action);
+ if (action->secondary && action->secondary->thread)
+ irq_stop_thread(action->secondary);
}
/* Last action releases resources */
--
2.53.0
prev parent reply other threads:[~2026-11-04 22:54 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 14:15 FAILED: patch "[PATCH] genirq: Defer kfree(irqaction) until irq_thread_dtor()" failed to apply to 6.1-stable tree gregkh
2026-11-04 22:54 ` Sasha Levin [this message]
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=20261104225336.845493-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=ripatel@wii.dev \
--cc=stable@vger.kernel.org \
--cc=tglx@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.