Widen ifnet_detach_sxlock coverage

Widen the ifnet_detach_sxlock to cover the entire vnet sysuninit code.
This ensures that we can't end up having the vnet_sysuninit free the UDP
pcb while the detach code is running and trying to purge the UDP pcb.

MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D28530
This commit is contained in:
Kristof Provost 2021-02-08 10:04:27 +01:00
parent 6462113b70
commit 6d2a10d96f
3 changed files with 11 additions and 7 deletions

View File

@ -315,7 +315,8 @@ struct sx ifnet_sxlock;
SX_SYSINIT_FLAGS(ifnet_sx, &ifnet_sxlock, "ifnet_sx", SX_RECURSE);
struct sx ifnet_detach_sxlock;
SX_SYSINIT(ifnet_detach, &ifnet_detach_sxlock, "ifnet_detach_sx");
SX_SYSINIT_FLAGS(ifnet_detach, &ifnet_detach_sxlock, "ifnet_detach_sx",
SX_RECURSE);
/*
* The allocation of network interfaces is a rather non-atomic affair; we
@ -546,9 +547,7 @@ vnet_if_return(const void *unused __unused)
IFNET_WUNLOCK();
for (int j = 0; j < i; j++) {
sx_xlock(&ifnet_detach_sxlock);
if_vmove(pending[j], pending[j]->if_home_vnet);
sx_xunlock(&ifnet_detach_sxlock);
}
free(pending, M_IFNET);
@ -1124,9 +1123,9 @@ if_detach(struct ifnet *ifp)
CURVNET_SET_QUIET(ifp->if_vnet);
found = if_unlink_ifnet(ifp, false);
if (found) {
sx_slock(&ifnet_detach_sxlock);
sx_xlock(&ifnet_detach_sxlock);
if_detach_internal(ifp, 0, NULL);
sx_sunlock(&ifnet_detach_sxlock);
sx_xunlock(&ifnet_detach_sxlock);
}
CURVNET_RESTORE();
}
@ -3015,9 +3014,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
error = priv_check(td, PRIV_NET_IFDESTROY);
if (error == 0) {
sx_slock(&ifnet_detach_sxlock);
sx_xlock(&ifnet_detach_sxlock);
error = if_clone_destroy(ifr->ifr_name);
sx_sunlock(&ifnet_detach_sxlock);
sx_xunlock(&ifnet_detach_sxlock);
}
goto out_noref;

View File

@ -604,6 +604,9 @@ struct ifdownreason {
MALLOC_DECLARE(M_IFADDR);
MALLOC_DECLARE(M_IFMADDR);
#endif
extern struct sx ifnet_detach_sxlock;
#endif
#ifndef _KERNEL

View File

@ -283,7 +283,9 @@ vnet_destroy(struct vnet *vnet)
vnet->vnet_shutdown = true;
CURVNET_SET_QUIET(vnet);
sx_xlock(&ifnet_detach_sxlock);
vnet_sysuninit();
sx_xunlock(&ifnet_detach_sxlock);
CURVNET_RESTORE();
/*