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