Index: sys/net/if_tap.c =================================================================== --- sys/net/if_tap.c +++ sys/net/if_tap.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +165,9 @@ MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); +static struct sx tap_ioctl_sx; +SX_SYSINIT(tap_ioctl_sx, &tap_ioctl_sx, "tap_ioctl"); + SYSCTL_DECL(_net_link); static SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, "Ethernet tunnel software network interface"); @@ -217,11 +222,14 @@ struct ifnet *ifp = tp->tap_ifp; CURVNET_SET(ifp->if_vnet); + sx_xlock(&tap_ioctl_sx); destroy_dev(tp->tap_dev); seldrain(&tp->tap_rsel); knlist_clear(&tp->tap_rsel.si_note, 0); knlist_destroy(&tp->tap_rsel.si_note); ether_ifdetach(ifp); + ifp->if_softc = NULL; + sx_xunlock(&tap_ioctl_sx); if_free(ifp); mtx_destroy(&tp->tap_mtx); @@ -600,12 +608,18 @@ static int tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { - struct tap_softc *tp = ifp->if_softc; + struct tap_softc *tp; struct ifreq *ifr = (struct ifreq *)data; struct ifstat *ifs = NULL; struct ifmediareq *ifmr = NULL; int dummy, error = 0; + sx_xlock(&tap_ioctl_sx); + tp = ifp->if_softc; + if (tp == NULL) { + error = ENXIO; + goto bad; + } switch (cmd) { case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ case SIOCADDMULTI: @@ -648,6 +662,8 @@ break; } +bad: + sx_xunlock(&tap_ioctl_sx); return (error); } /* tapifioctl */ Index: sys/net/if_tun.c =================================================================== --- sys/net/if_tun.c +++ sys/net/if_tun.c @@ -20,6 +20,7 @@ #include "opt_inet6.h" #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +117,9 @@ static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); +static struct sx tun_ioctl_sx; +SX_SYSINIT(tun_ioctl_sx, &tun_ioctl_sx, "tun_ioctl"); + SYSCTL_DECL(_net_link); static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, "IP tunnel software network interface."); @@ -278,11 +283,15 @@ mtx_unlock(&tp->tun_mtx); CURVNET_SET(TUN2IFP(tp)->if_vnet); + sx_xlock(&tun_ioctl_sx); dev = tp->tun_dev; bpfdetach(TUN2IFP(tp)); if_detach(TUN2IFP(tp)); free_unr(tun_unrhdr, TUN2IFP(tp)->if_dunit); + TUN2IFP(tp)->if_softc = NULL; if_free(TUN2IFP(tp)); + sx_xunlock(&tun_ioctl_sx); + destroy_dev(dev); seldrain(&tp->tun_rsel); knlist_clear(&tp->tun_rsel.si_note, 0); @@ -588,10 +597,16 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ifreq *ifr = (struct ifreq *)data; - struct tun_softc *tp = ifp->if_softc; + struct tun_softc *tp; struct ifstat *ifs; int error = 0; + sx_xlock(&tun_ioctl_sx); + tp = ifp->if_softc; + if (tp == NULL) { + error = ENXIO; + goto bad; + } switch(cmd) { case SIOCGIFSTATUS: ifs = (struct ifstat *)data; @@ -618,6 +633,8 @@ default: error = EINVAL; } +bad: + sx_xunlock(&tun_ioctl_sx); return (error); }