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 <[email protected]>

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
> 

Reply via email to