Re: [PATCH] rcutorture: Synchronously wait for all rcu_torture_irq() callbacks to complete
From: Paul E. McKenney
Date: Thu Aug 27 2026 - 13:30:01 EST
On Mon, Aug 24, 2026 at 05:24:27PM +0800, Zqiang wrote:
> The rcu_torture_reader() drives RCU readers from interrupt context via
> smp_call_function_single(cpu, rcu_torture_irq, NULL, 0) with wait=0, to
> runs rcu_torture_irq() on a remote CPU. this is async, nothing waits for
> the remote handler to run.
>
> On shutdown, torture_stop_kthread() only waits for each reader kthread to
> return, and the reader's timer_delete_sync() only drains its timer. Neither
> waits for a rcu_torture_irq() which still pending or executing on a remote
> CPU, so it can run after all readers have exited and rcu_torture_cleanup()
> has already advanced.
>
> 1. rcu_torture_irq() may issue cur_ops->call(rhp, rcu_torture_timer_cb)
> after cur_ops->cb_barrier() has been waiting for all outstanding
> callbacks complete. once the module is unloaded, fires into freed
> module text, a use-after-free happen.
>
> 2. rcu_torture_irq() may still be inside rcu_torture_one_read(), holding
> a read-side critical section, when cur_ops->cleanup() tears the flavor
> down (e.g. cleanup_srcu_struct()), triggering an active-reader warning
> or use-after-free of the torn-down structure.
>
> This commit therefore issue a kick_all_cpus_sync() after all readers
> kthread have returned and before cur_ops->cb_barrier(), synchronous IPI
> round trip to every CPU guarantees that every rcu_torture_irq() which
> previously issued by any reader has completed.
>
> Signed-off-by: Zqiang <qiang.zhang@xxxxxxxxx>
Good catch! Queued for further review and testing, thank you!
Thanx, Paul
> ---
> kernel/rcu/rcutorture.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
> index 4b4d9c70e827..f177ba9cb604 100644
> --- a/kernel/rcu/rcutorture.c
> +++ b/kernel/rcu/rcutorture.c
> @@ -4476,6 +4476,8 @@ rcu_torture_cleanup(void)
> for (i = 0; i < nrealreaders; i++)
> torture_stop_kthread(rcu_torture_reader,
> reader_tasks[i]);
> + if (irqreader && cur_ops->irq_capable)
> + kick_all_cpus_sync();
> kfree(reader_tasks);
> reader_tasks = NULL;
> }
> --
> 2.17.1
>