ip_vs_dest_trash_expire() accesses the per-network-namespace IPVS state
and rearms the destination trash timer while entries remain.  The
cleanup path uses timer_delete_sync(), which waits for a running callback
but still allows a racing callback to rearm the timer.

Use timer_shutdown_sync() when the per-network-namespace destination
trash is finally cleaned up.  This prevents the callback from being
queued again before the IPVS state is released.

Fixes: f2431e6e9255 ("IPVS: netns, trash handling")
Cc: [email protected]
Assisted-by: Codex:GPT-5
Signed-off-by: Runyu Xiao <[email protected]>

diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 4c1c73944..0eb6cdb5f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1192,7 +1192,7 @@ static void ip_vs_trash_cleanup(struct netns_ipvs *ipvs)
 {
        struct ip_vs_dest *dest, *nxt;
 
-       timer_delete_sync(&ipvs->dest_trash_timer);
+       timer_shutdown_sync(&ipvs->dest_trash_timer);
        /* No need to use dest_trash_lock */
        list_for_each_entry_safe(dest, nxt, &ipvs->dest_trash, t_list) {
                list_del(&dest->t_list);
-- 
2.34.1

Reply via email to