! ! Throughout the network stack we have a few places of if (jailed()) ! left. If you are running with a vnet those will return true and ! defer you to classic IP-jails handling and thus things will be ! "denied" or returned with an error. ! ! The patch below works around this by introducing another jailed() ! function, that also takes vnets into account. We cannot change ! the classic jailed() call to do that as it is used otherwehere as ! well. ! ! This solution is a rather quick and easy workaround but made me ! wonder if those replaced jailed() checks should actually be ! priv(9) checks or if we will need to generally enhance our ! jailed() version and keep the old one as a wrapper to the new ! one. ! Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c (revision 196740) +++ sys/kern/kern_jail.c (working copy) @@ -3150,7 +3150,7 @@ pr = cred->cr_prison; #ifdef VIMAGE /* Prisons with their own network stack are not limited. */ - if (pr->pr_flags & PR_VNET) + if (prison_owns_vnet(cred)) return (0); #endif @@ -3211,6 +3211,11 @@ KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); KASSERT(sa != NULL, ("%s: sa is NULL", __func__)); +#ifdef VIMAGE + if (prison_owns_vnet(cred)) + return (0); +#endif + error = 0; switch (sa->sa_family) { @@ -3268,6 +3273,24 @@ } /* + * Return 1 if the passed credential is in a jail and does not have its own + * virtual network stack, otherwise 0. + */ +int +jailed_without_vnet(struct ucred *cred) +{ + + if (cred->cr_prison == &prison0) + return (0); +#ifdef VIMAGE + if (prison_owns_vnet(cred)) + return (0); +#endif + + return (1); +} + +/* * Return the correct hostname (domainname, et al) for the passed credential. */ void Index: sys/netinet/raw_ip.c =================================================================== --- sys/netinet/raw_ip.c (revision 196740) +++ sys/netinet/raw_ip.c (working copy) @@ -291,7 +291,7 @@ continue; if (inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; - if (jailed(inp->inp_cred)) { + if (jailed_without_vnet(inp->inp_cred)) { /* * XXX: If faddr was bound to multicast group, * jailed raw socket will drop datagram. @@ -325,7 +325,7 @@ if (!in_nullhost(inp->inp_faddr) && !in_hosteq(inp->inp_faddr, ip->ip_src)) continue; - if (jailed(inp->inp_cred)) { + if (jailed_without_vnet(inp->inp_cred)) { /* * Allow raw socket in jail to receive multicast; * assume process had PRIV_NETINET_RAW at attach, Index: sys/net/rtsock.c =================================================================== --- sys/net/rtsock.c (revision 196740) +++ sys/net/rtsock.c (working copy) @@ -651,7 +651,7 @@ report: RT_LOCK_ASSERT(rt); if ((rt->rt_flags & RTF_HOST) == 0 - ? jailed(curthread->td_ucred) + ? jailed_without_vnet(curthread->td_ucred) : prison_if(curthread->td_ucred, rt_key(rt)) != 0) { RT_UNLOCK(rt); @@ -1312,7 +1312,7 @@ if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) return 0; if ((rt->rt_flags & RTF_HOST) == 0 - ? jailed(w->w_req->td->td_ucred) + ? jailed_without_vnet(w->w_req->td->td_ucred) : prison_if(w->w_req->td->td_ucred, rt_key(rt)) != 0) return (0); bzero((caddr_t)&info, sizeof(info)); Index: sys/netinet6/raw_ip6.c =================================================================== --- sys/netinet6/raw_ip6.c (revision 196740) +++ sys/netinet6/raw_ip6.c (working copy) @@ -184,7 +184,7 @@ if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) continue; - if (jailed(in6p->inp_cred)) { + if (jailed_without_vnet(in6p->inp_cred)) { /* * Allow raw socket in jail to receive multicast; * assume process had PRIV_NETINET_RAW at attach, Index: sys/sys/jail.h =================================================================== --- sys/sys/jail.h (revision 196740) +++ sys/sys/jail.h (working copy) @@ -335,6 +335,7 @@ struct sockaddr; struct statfs; int jailed(struct ucred *cred); +int jailed_without_vnet(struct ucred *); void getcredhostname(struct ucred *, char *, size_t); void getcreddomainname(struct ucred *, char *, size_t); void getcredhostuuid(struct ucred *, char *, size_t);