From 4ed0681dc2c1e0538b79d2fc56190ffcb369dacd Mon Sep 17 00:00:00 2001 From: Zhiling Zou Date: Fri, 21 Aug 2026 23:50:21 -0400 Subject: [PATCH] inet: frags: publish queues before arming timer [ Upstream commit 653d7ddf6cba867777a3d14c4f83ace008c5ad13 ] inet_frag_create() arms the fragment queue timer before inserting the queue into the fqdir rhashtable. If the namespace fragment timeout is zero or negative, the timer can run before the queue is published. The timer callback then marks the queue complete, tries to remove a node that is not in the hash table yet, and drops the anticipated hash reference. Creation can subsequently publish the completed queue without restoring that reference, leaving a stale hash node after the caller drops the remaining reference. Publish the queue first and arm the timer while holding the queue lock. This makes timer expiry wait until the queue is visible in the hash table, so inet_frag_kill() can remove the node and balance the hash reference. Fixes: 648700f76b03 ("inet: frags: use rhashtables for reassembly units") Cc: stable@vger.kernel.org Reported-by: Vega Signed-off-by: Zhiling Zou Signed-off-by: Ren Wei Link: https://patch.msgid.link/bf66785e7c0c139d7a1900e2f01faeeab344b960.1784948849.git.zhilinz@nebusec.ai Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- net/ipv4/inet_fragment.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 7e3817011199..7922b10f360e 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -339,16 +339,18 @@ static struct inet_frag_queue *inet_frag_create(struct fqdir *fqdir, *prev = ERR_PTR(-ENOMEM); return NULL; } - mod_timer(&q->timer, jiffies + fqdir->timeout); + spin_lock_bh(&q->lock); *prev = rhashtable_lookup_get_insert_key(&fqdir->rhashtable, &q->key, &q->node, f->rhash_params); if (*prev) { q->flags |= INET_FRAG_COMPLETE; - inet_frag_kill(q); + spin_unlock_bh(&q->lock); inet_frag_destroy(q); return NULL; } + mod_timer(&q->timer, jiffies + fqdir->timeout); + spin_unlock_bh(&q->lock); return q; }