Throughout the network stack we have a few places of

if (jailed(cred))
left.  If you are running with a vnet (virtual network stack) those will
return true and defer you to classic IP-jails handling and thus things
will be "denied" or returned with an error.

Work around this problem by introducing another "jailed()" function,
jailed_without_vnet(), that also takes vnets into account, and permits
the calls, should the jail from the given cred have its own virtual
network stack.

We cannot change the classic jailed() call to do that,  as it is used
outside the network stack as well.

Discussed with:	julian, zec, jamie, rwatson (back in Sept)
MFC after:	5 days
This commit is contained in:
Bjoern A. Zeeb 2009-12-13 13:57:32 +00:00
parent e65a4ba18b
commit de0bd6f76b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=200473
5 changed files with 30 additions and 6 deletions

View File

@ -3161,7 +3161,7 @@ prison_check_af(struct ucred *cred, int af)
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
@ -3222,6 +3222,11 @@ prison_if(struct ucred *cred, struct sockaddr *sa)
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)
{
@ -3278,6 +3283,24 @@ jailed(struct ucred *cred)
return (cred->cr_prison != &prison0);
}
/*
* Return 1 if the passed credential is in a jail and that jail does not
* have its own virtual network stack, otherwise 0.
*/
int
jailed_without_vnet(struct ucred *cred)
{
if (!jailed(cred))
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.
*/

View File

@ -651,7 +651,7 @@ route_output(struct mbuf *m, struct socket *so)
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 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
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));

View File

@ -291,7 +291,7 @@ rip_input(struct mbuf *m, int off)
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 @@ rip_input(struct mbuf *m, int off)
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,

View File

@ -184,7 +184,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
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,

View File

@ -335,6 +335,7 @@ struct mount;
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);