diff options
author | Kristof Provost <kp@FreeBSD.org> | 2021-02-08 09:04:27 +0000 |
---|---|---|
committer | Kristof Provost <kp@FreeBSD.org> | 2021-02-17 13:13:04 +0000 |
commit | 9cc7bd9a6ab1e2bfc12dabf4d9ef4ad463a05616 (patch) | |
tree | 9129057b9977f92452702832eeb4c197bed82dbb | |
parent | f8d1f2da0922fdff846b13baa7315652b43aa95c (diff) |
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
(cherry picked from commit 6d2a10d96fb5d4ee42fd67b0b07a6d098db5d55a)
-rw-r--r-- | sys/net/if.c | 13 | ||||
-rw-r--r-- | sys/net/if.h | 3 | ||||
-rw-r--r-- | sys/net/vnet.c | 2 |
3 files changed, 11 insertions, 7 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 56b12f594814..2ae8121043b0 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -316,7 +316,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 @@ -552,9 +553,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); @@ -1108,9 +1107,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(); } @@ -3147,9 +3146,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; diff --git a/sys/net/if.h b/sys/net/if.h index 3767033d8265..44a920d844e2 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -600,6 +600,9 @@ struct ifdownreason { MALLOC_DECLARE(M_IFADDR); MALLOC_DECLARE(M_IFMADDR); #endif + +extern struct sx ifnet_detach_sxlock; + #endif #ifndef _KERNEL diff --git a/sys/net/vnet.c b/sys/net/vnet.c index 9a4321a8409b..3fd423d22d1d 100644 --- a/sys/net/vnet.c +++ b/sys/net/vnet.c @@ -281,7 +281,9 @@ vnet_destroy(struct vnet *vnet) VNET_LIST_WUNLOCK(); CURVNET_SET_QUIET(vnet); + sx_xlock(&ifnet_detach_sxlock); vnet_sysuninit(); + sx_xunlock(&ifnet_detach_sxlock); CURVNET_RESTORE(); /* |