Re: [PATCH v1] irq_work: Fix use-after-free in irq_work_single on PREEMPT_RT
From: Sebastian Andrzej Siewior
Date: Thu Mar 26 2026 - 04:19:12 EST
On 2026-03-26 10:27:10 [+0800], Jiayuan Chen wrote:
> Combining your and Steven's suggestions, I think the simplest fix would be:
>
> static void run_irq_workd(unsigned int cpu)
> {
> + guard(rcu)();
> irq_work_run_list(this_cpu_ptr(&lazy_list));
> }
>
> void irq_work_sync(struct irq_work *work)
> {
> lockdep_assert_irqs_enabled();
> might_sleep();
>
> if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
> !arch_irq_work_has_interrupt()) {
> rcuwait_wait_event(&work->irqwait, !irq_work_is_busy(work),
> TASK_UNINTERRUPTIBLE);
> + /*
> + * Ensure run_irq_workd() / irq_work_single() is done
> + * accessing @work before the caller can free it.
Ensure irq_work_single() does not access @work after removing
IRQ_WORK_BUSY. It is always accessed within a RCU-read section.
But, yes, this looks like a simple fix.
> + */
> + synchronize_rcu();
> return;
> }
Sebastian