Skip to content

Commit d3ffb89

Browse files
Zhiling Zougregkh
authored andcommitted
inet: frags: publish queues before arming timer
[ Upstream commit 653d7dd ] 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: 648700f ("inet: frags: use rhashtables for reassembly units") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai> Signed-off-by: Ren Wei <enjou1224z@gmail.com> Link: https://patch.msgid.link/bf66785e7c0c139d7a1900e2f01faeeab344b960.1784948849.git.zhilinz@nebusec.ai Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent bb7488c commit d3ffb89

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

net/ipv4/inet_fragment.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,22 +393,22 @@ static struct inet_frag_queue *inet_frag_create(struct fqdir *fqdir,
393393
*prev = ERR_PTR(-ENOMEM);
394394
return NULL;
395395
}
396-
mod_timer(&q->timer, jiffies + fqdir->timeout);
397396

397+
spin_lock_bh(&q->lock);
398398
*prev = rhashtable_lookup_get_insert_key(&fqdir->rhashtable, &q->key,
399399
&q->node, f->rhash_params);
400400
if (*prev) {
401401
/* We could not insert in the hash table,
402402
* we need to cancel what inet_frag_alloc()
403403
* anticipated.
404404
*/
405-
int refs = 1;
406-
407405
q->flags |= INET_FRAG_COMPLETE;
408-
inet_frag_kill(q, &refs);
409-
inet_frag_putn(q, refs);
406+
spin_unlock_bh(&q->lock);
407+
inet_frag_putn(q, 2);
410408
return NULL;
411409
}
410+
mod_timer(&q->timer, jiffies + fqdir->timeout);
411+
spin_unlock_bh(&q->lock);
412412
return q;
413413
}
414414

0 commit comments

Comments
 (0)