ng_l2tp: Fix callout synchronization in the rexmit timeout handler

A received control packet may cause the transmit queue to be flushed, in
which case ng_l2tp_seq_recv_nr() cancels the transmit timeout handler.
The handler checks to see if it was cancelled before doing anything, but
did so before acquiring the node lock, so a small race window could
cause ng_l2tp_seq_rack_timeout() to attempt to flush an empty queue,
ultimately causing a null pointer dereference.

PR:		241133
Reviewed by:	bz, glebius, Lutz Donnerhacke
MFC after:	3 days
Sponsored by:	Rubicon Communications, LLC (Netgate)
Differential Revision:	https://reviews.freebsd.org/D26548
This commit is contained in:
Mark Johnston 2020-09-25 18:55:50 +00:00
parent f9f298a2f4
commit e62e4b8594
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=366167

View File

@ -1453,15 +1453,17 @@ ng_l2tp_seq_rack_timeout(node_p node, hook_p hook, void *arg1, int arg2)
struct mbuf *m;
u_int delay;
/* Make sure callout is still active before doing anything */
if (callout_pending(&seq->rack_timer) ||
(!callout_active(&seq->rack_timer)))
return;
/* Sanity check */
L2TP_SEQ_CHECK(seq);
mtx_lock(&seq->mtx);
/* Make sure callout is still active before doing anything */
if (callout_pending(&seq->rack_timer) ||
!callout_active(&seq->rack_timer)) {
mtx_unlock(&seq->mtx);
return;
}
priv->stats.xmitRetransmits++;
/* Have we reached the retransmit limit? If so, notify owner. */