of the interface, and will later try to + * unlink it from the "active" list, so it is sufficient to only + * hold a weak reference to it. + * Be aware that it is unsafe to access any member of it, until it + * is proven to be safe to ( say it was on the "active" list ). + */ + ifp = ifunit(ifname); + if (ifp == NULL) + return (ENXIO); + /* Try to find the prison within our visibility. */ sx_slock(&allprison_lock); pr = prison_find_child(td->td_ucred->cr_prison, jid); sx_sunlock(&allprison_lock); if (pr == NULL) return (ENXIO); - prison_hold_locked(pr); - mtx_unlock(&pr->pr_mtx); - - /* Do not try to move the iface from and to the same prison. */ - if (pr->pr_vnet == ifp->if_vnet) { - prison_free(pr); + /* Do not try to move the iface from and to the same vnet. */ + if (pr->pr_vnet == TD_TO_VNET(td)) { + mtx_unlock(&pr->pr_mtx); return (EEXIST); } + prison_hold_locked(pr); + mtx_unlock(&pr->pr_mtx); /* Make sure the named iface does not exists in the dst. prison/vnet. */ /* XXX Lock interfaces to avoid races. */ @@ -2701,15 +2714,6 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) error = if_rename(ifp, new_name); break; -#ifdef VIMAGE - case SIOCSIFVNET: - error = priv_check(td, PRIV_NET_SETIFVNET); - if (error) - return (error); - error = if_vmove_loan(td, ifp, ifr->ifr_name, ifr->ifr_jid); - break; -#endif - case SIOCSIFMETRIC: error = priv_check(td, PRIV_NET_SETIFMETRIC); if (error) @@ -2997,6 +3001,12 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) ifr = (struct ifreq *)data; switch (cmd) { #ifdef VIMAGE + case SIOCSIFVNET: + error = priv_check(td, PRIV_NET_SETIFVNET); + if (error == 0) + error = if_vmove_loan(td, ifr->ifr_name, ifr->ifr_jid); + goto out_noref; + case SIOCSIFRVNET: error = priv_check(td, PRIV_NET_SETIFVNET); if (error == 0)