diff --git a/sys/net/if.c b/sys/net/if.c --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1261,25 +1261,23 @@ sx_sunlock(&allprison_lock); if (pr == NULL) return (ENXIO); - prison_hold_locked(pr); - mtx_unlock(&pr->pr_mtx); - /* Make sure the named iface exists in the source prison/vnet. */ CURVNET_SET(pr->pr_vnet); - ifp = ifunit(ifname); /* XXX Lock to avoid races. */ + ifp = ifunit(ifname); if (ifp == NULL) { CURVNET_RESTORE(); - prison_free(pr); + mtx_unlock(&pr->pr_mtx); return (ENXIO); } - - /* Do not try to move the iface from and to the same prison. */ + /* Do not try to move the iface from and to the same vnet. */ vnet_dst = TD_TO_VNET(td); - if (vnet_dst == ifp->if_vnet) { + if (vnet_dst == pr->pr_vnet) { CURVNET_RESTORE(); - prison_free(pr); + mtx_unlock(&pr->pr_mtx); return (EEXIST); } + prison_hold_locked(pr); + mtx_unlock(&pr->pr_mtx); /* Get interface back from child jail/vnet. */ found = if_unlink_ifnet(ifp, true); @@ -1287,12 +1285,12 @@ sx_xlock(&ifnet_detach_sxlock); if_vmove(ifp, vnet_dst); sx_xunlock(&ifnet_detach_sxlock); - CURVNET_RESTORE(); /* Report the new if_xname back to the userland. */ sprintf(ifname, "%s", ifp->if_xname); prison_free(pr); + CURVNET_RESTORE(); return (0); } #endif /* VIMAGE */