tuntap: Defer clearing if_softc until after if_detach
r346670 added an sx to close a race between the ifioctl handler and interface destruction. Unfortunately, it clears if_softc immediately after the interface is closed, but before if_detach has been invoked. Any time before detachment, an interface that's part of a bridge may still receive traffic that's pushed through tunstart/tunstart_l2 and promptly lead to a panic because if_softc is now NULL. Fix it by deferring the clearing of if_softc until after the interface has detached and thus been removed from the bridge. if_softc still gets cleared in case another thread has already entered the ioctl handler before it's replaced with ifdead_ioctl. Reported by: markj MFC after: 3 days
This commit is contained in:
parent
367ba2d2a3
commit
db226f0d8e
@ -537,9 +537,6 @@ tun_destroy(struct tuntap_softc *tp)
|
||||
TUN_UNLOCK(tp);
|
||||
|
||||
CURVNET_SET(TUN2IFP(tp)->if_vnet);
|
||||
sx_xlock(&tun_ioctl_sx);
|
||||
TUN2IFP(tp)->if_softc = NULL;
|
||||
sx_xunlock(&tun_ioctl_sx);
|
||||
|
||||
destroy_dev(tp->tun_dev);
|
||||
seldrain(&tp->tun_rsel);
|
||||
@ -551,6 +548,9 @@ tun_destroy(struct tuntap_softc *tp)
|
||||
bpfdetach(TUN2IFP(tp));
|
||||
if_detach(TUN2IFP(tp));
|
||||
}
|
||||
sx_xlock(&tun_ioctl_sx);
|
||||
TUN2IFP(tp)->if_softc = NULL;
|
||||
sx_xunlock(&tun_ioctl_sx);
|
||||
free_unr(tp->tun_drv->unrhdr, TUN2IFP(tp)->if_dunit);
|
||||
if_free(TUN2IFP(tp));
|
||||
mtx_destroy(&tp->tun_mtx);
|
||||
|
Loading…
x
Reference in New Issue
Block a user