dummynet: fix ip_dn_vnet_init() / dummynet_task() race

If dummynet_task() is run on a vnet where dummynet is still initialising
(i.e. still running ip_dn_vnet_init()) we can attempt to use an
uninitialised mutex.

We can use the existing init_done field to check if the per-vnet
V_dn_cfg is fully set up, if we ensure that it's only set to 1 when
we've done all of the init work.

Reported by:	Alfredo Dal'Ava Júnior <alfredo@freebsd.org>
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D35716
This commit is contained in:
Kristof Provost 2022-07-04 22:36:43 +02:00
parent 9576bca583
commit cbb019b831
2 changed files with 8 additions and 1 deletions

View file

@ -669,6 +669,11 @@ dummynet_task(void *context, int pending)
memset(&q, 0, sizeof(struct mq));
CURVNET_SET(vnet_iter);
if (! V_dn_cfg.init_done) {
CURVNET_RESTORE();
continue;
}
DN_BH_WLOCK();
/* Update number of lost(coalesced) ticks. */

View file

@ -2562,7 +2562,7 @@ ip_dn_vnet_init(void)
{
if (V_dn_cfg.init_done)
return;
V_dn_cfg.init_done = 1;
/* Set defaults here. MSVC does not accept initializers,
* and this is also useful for vimages
*/
@ -2601,6 +2601,8 @@ ip_dn_vnet_init(void)
/* Initialize curr_time adjustment mechanics. */
getmicrouptime(&V_dn_cfg.prev_t);
V_dn_cfg.init_done = 1;
}
static void