svn commit: r188761 - in stable/7: lib/libc lib/libc/string
lib/libc/sys sys sys/contrib/pf sys/dev/ath/ath_hal
sys/dev/cxgb sys/kern sys/net sys/netinet sys/netinet6 sys/sys
Jamie Gritton
jamie at FreeBSD.org
Wed Feb 18 12:12:10 PST 2009
Author: jamie
Date: Wed Feb 18 20:12:08 2009
New Revision: 188761
URL: http://svn.freebsd.org/changeset/base/188761
Log:
MFC:
r188144:
Standardize the various prison_foo_ip[46] functions and prison_if to
return zero on success and an error code otherwise. The possible errors
are EADDRNOTAVAIL if an address being checked for doesn't match the
prison, and EAFNOSUPPORT if the prison doesn't have any addresses in
that address family. For most callers of these functions, use the
returned error code instead of e.g. a hard-coded EADDRNOTAVAIL or
EINVAL.
Always include a jailed() check in these functions, where a non-jailed
cred always returns success (and makes no changes). Remove the explicit
jailed() checks that preceded many of the function calls.
r188146:
Don't allow creating a socket with a protocol family that the current
jail doesn't support. This involves a new function prison_check_af,
like prison_check_ip[46] but that checks only the family.
With this change, most of the errors generated by jailed sockets
shouldn't ever occur, at least until jails are changeable.
r188148:
Remove redundant calls of prison_local_ip4 in in_pcbbind_setup, and of
prison_local_ip6 in in6_pcbbind.
r188149:
Call prison_if from rtm_get_jailed, instead of splitting it out into
prison_check_ip4 and prison_check_ip6. As prison_if includes a jailed()
check, remove that check before calling rtm_get_jailed.
r188151:
Don't bother null-checking the thread pointer before the prison checks
in udp6_connect (td is already dereferenced elsewhere without such a
check). This makes the conversion from a sockaddr to a sockaddr_in6
always happen, so convert once at the beginning of the function rather
than twice in the middle.
Approved by: bz (mentor)
Modified:
stable/7/lib/libc/ (props changed)
stable/7/lib/libc/string/ffsll.c (props changed)
stable/7/lib/libc/string/flsll.c (props changed)
stable/7/lib/libc/sys/send.2
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/dev/ath/ath_hal/ (props changed)
stable/7/sys/dev/cxgb/ (props changed)
stable/7/sys/kern/kern_jail.c
stable/7/sys/kern/uipc_socket.c
stable/7/sys/net/if.c
stable/7/sys/net/rtsock.c
stable/7/sys/netinet/in.c
stable/7/sys/netinet/in_pcb.c
stable/7/sys/netinet/raw_ip.c
stable/7/sys/netinet/tcp_usrreq.c
stable/7/sys/netinet/udp_usrreq.c
stable/7/sys/netinet6/in6.c
stable/7/sys/netinet6/in6_pcb.c
stable/7/sys/netinet6/in6_src.c
stable/7/sys/netinet6/raw_ip6.c
stable/7/sys/netinet6/udp6_usrreq.c
stable/7/sys/sys/jail.h
Modified: stable/7/lib/libc/sys/send.2
==============================================================================
--- stable/7/lib/libc/sys/send.2 Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/lib/libc/sys/send.2 Wed Feb 18 20:12:08 2009 (r188761)
@@ -28,7 +28,7 @@
.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
.\" $FreeBSD$
.\"
-.Dd September 13, 2006
+.Dd February 5, 2009
.Dt SEND 2
.Os
.Sh NAME
@@ -190,7 +190,7 @@ receiver is not listening on the remote
The remote host was down.
.It Bq Er ENETDOWN
The remote network was down.
-.It Bq Er EPERM
+.It Bq Er EADDRNOTAVAIL
The process using a
.Dv SOCK_RAW
socket was jailed and the source
Modified: stable/7/sys/kern/kern_jail.c
==============================================================================
--- stable/7/sys/kern/kern_jail.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/kern/kern_jail.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -230,7 +230,7 @@ prison_check_conflicting_ips(struct pris
if ((p->pr_ip4s >= 1 && pr->pr_ip4s > 1) ||
(p->pr_ip4s > 1 && pr->pr_ip4s >= 1)) {
for (i = 0; i < p->pr_ip4s; i++) {
- if (_prison_check_ip4(pr, &p->pr_ip4[i]))
+ if (_prison_check_ip4(pr, &p->pr_ip4[i]) == 0)
return (EINVAL);
}
}
@@ -239,7 +239,7 @@ prison_check_conflicting_ips(struct pris
if ((p->pr_ip6s >= 1 && pr->pr_ip6s > 1) ||
(p->pr_ip6s > 1 && pr->pr_ip6s >= 1)) {
for (i = 0; i < p->pr_ip6s; i++) {
- if (_prison_check_ip6(pr, &p->pr_ip6[i]))
+ if (_prison_check_ip6(pr, &p->pr_ip6[i]) == 0)
return (EINVAL);
}
}
@@ -841,9 +841,10 @@ prison_proc_free(struct prison *pr)
* Pass back primary IPv4 address of this jail.
*
* If not jailed return success but do not alter the address. Caller has to
- * make sure to intialize it correctly (INADDR_ANY).
+ * make sure to intialize it correctly (e.g. INADDR_ANY).
*
- * Returns 0 on success, 1 on error. Address returned in NBO.
+ * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4.
+ * Address returned in NBO.
*/
int
prison_get_ip4(struct ucred *cred, struct in_addr *ia)
@@ -857,7 +858,7 @@ prison_get_ip4(struct ucred *cred, struc
return (0);
if (cred->cr_prison->pr_ip4 == NULL)
- return (1);
+ return (EAFNOSUPPORT);
ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
return (0);
@@ -867,8 +868,9 @@ prison_get_ip4(struct ucred *cred, struc
* Make sure our (source) address is set to something meaningful to this
* jail.
*
- * Returns 0 on success, 1 on error. Address passed in in NBO and returned
- * in NBO.
+ * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if
+ * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv4.
+ * Address passed in in NBO and returned in NBO.
*/
int
prison_local_ip4(struct ucred *cred, struct in_addr *ia)
@@ -881,7 +883,7 @@ prison_local_ip4(struct ucred *cred, str
if (!jailed(cred))
return (0);
if (cred->cr_prison->pr_ip4 == NULL)
- return (1);
+ return (EAFNOSUPPORT);
ia0.s_addr = ntohl(ia->s_addr);
if (ia0.s_addr == INADDR_LOOPBACK) {
@@ -889,25 +891,23 @@ prison_local_ip4(struct ucred *cred, str
return (0);
}
- /*
- * In case there is only 1 IPv4 address, bind directly.
- */
- if (ia0.s_addr == INADDR_ANY && cred->cr_prison->pr_ip4s == 1) {
- ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
+ if (ia0.s_addr == INADDR_ANY) {
+ /*
+ * In case there is only 1 IPv4 address, bind directly.
+ */
+ if (cred->cr_prison->pr_ip4s == 1)
+ ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
return (0);
}
- if (ia0.s_addr == INADDR_ANY || prison_check_ip4(cred, ia))
- return (0);
-
- return (1);
+ return (_prison_check_ip4(cred->cr_prison, ia));
}
/*
* Rewrite destination address in case we will connect to loopback address.
*
- * Returns 0 on success, 1 on error. Address passed in in NBO and returned
- * in NBO.
+ * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4.
+ * Address passed in in NBO and returned in NBO.
*/
int
prison_remote_ip4(struct ucred *cred, struct in_addr *ia)
@@ -919,7 +919,8 @@ prison_remote_ip4(struct ucred *cred, st
if (!jailed(cred))
return (0);
if (cred->cr_prison->pr_ip4 == NULL)
- return (1);
+ return (EAFNOSUPPORT);
+
if (ntohl(ia->s_addr) == INADDR_LOOPBACK) {
ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr;
return (0);
@@ -932,23 +933,22 @@ prison_remote_ip4(struct ucred *cred, st
}
/*
- * Check if given address belongs to the jail referenced by cred.
+ * Check if given address belongs to the jail referenced by cred/prison.
*
- * Returns 1 if address belongs to jail, 0 if not. Address passed in in NBO.
+ * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if
+ * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv4.
+ * Address passed in in NBO.
*/
static int
_prison_check_ip4(struct prison *pr, struct in_addr *ia)
{
int i, a, z, d;
- if (pr->pr_ip4 == NULL)
- return (0);
-
/*
* Check the primary IP.
*/
if (pr->pr_ip4[0].s_addr == ia->s_addr)
- return (1);
+ return (0);
/*
* All the other IPs are sorted so we can do a binary search.
@@ -963,9 +963,10 @@ _prison_check_ip4(struct prison *pr, str
else if (d < 0)
a = i + 1;
else
- return (1);
+ return (0);
}
- return (0);
+
+ return (EADDRNOTAVAIL);
}
int
@@ -976,7 +977,9 @@ prison_check_ip4(struct ucred *cred, str
KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
if (!jailed(cred))
- return (1);
+ return (0);
+ if (cred->cr_prison->pr_ip4 == NULL)
+ return (EAFNOSUPPORT);
return (_prison_check_ip4(cred->cr_prison, ia));
}
@@ -987,9 +990,9 @@ prison_check_ip4(struct ucred *cred, str
* Pass back primary IPv6 address for this jail.
*
* If not jailed return success but do not alter the address. Caller has to
- * make sure to intialize it correctly (IN6ADDR_ANY_INIT).
+ * make sure to intialize it correctly (e.g. IN6ADDR_ANY_INIT).
*
- * Returns 0 on success, 1 on error.
+ * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
*/
int
prison_get_ip6(struct ucred *cred, struct in6_addr *ia6)
@@ -1001,7 +1004,8 @@ prison_get_ip6(struct ucred *cred, struc
if (!jailed(cred))
return (0);
if (cred->cr_prison->pr_ip6 == NULL)
- return (1);
+ return (EAFNOSUPPORT);
+
bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr));
return (0);
}
@@ -1012,7 +1016,8 @@ prison_get_ip6(struct ucred *cred, struc
* v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0)
* when needed while binding.
*
- * Returns 0 on success, 1 on error.
+ * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if
+ * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv6.
*/
int
prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only)
@@ -1024,32 +1029,32 @@ prison_local_ip6(struct ucred *cred, str
if (!jailed(cred))
return (0);
if (cred->cr_prison->pr_ip6 == NULL)
- return (1);
+ return (EAFNOSUPPORT);
+
if (IN6_IS_ADDR_LOOPBACK(ia6)) {
bcopy(&cred->cr_prison->pr_ip6[0], ia6,
sizeof(struct in6_addr));
return (0);
}
- /*
- * In case there is only 1 IPv6 address, and v6only is true, then
- * bind directly.
- */
- if (v6only != 0 && IN6_IS_ADDR_UNSPECIFIED(ia6) &&
- cred->cr_prison->pr_ip6s == 1) {
- bcopy(&cred->cr_prison->pr_ip6[0], ia6,
- sizeof(struct in6_addr));
+ if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
+ /*
+ * In case there is only 1 IPv6 address, and v6only is true,
+ * then bind directly.
+ */
+ if (v6only != 0 && cred->cr_prison->pr_ip6s == 1)
+ bcopy(&cred->cr_prison->pr_ip6[0], ia6,
+ sizeof(struct in6_addr));
return (0);
}
- if (IN6_IS_ADDR_UNSPECIFIED(ia6) || prison_check_ip6(cred, ia6))
- return (0);
- return (1);
+
+ return (_prison_check_ip6(cred->cr_prison, ia6));
}
/*
* Rewrite destination address in case we will connect to loopback address.
*
- * Returns 0 on success, 1 on error.
+ * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
*/
int
prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6)
@@ -1061,7 +1066,8 @@ prison_remote_ip6(struct ucred *cred, st
if (!jailed(cred))
return (0);
if (cred->cr_prison->pr_ip6 == NULL)
- return (1);
+ return (EAFNOSUPPORT);
+
if (IN6_IS_ADDR_LOOPBACK(ia6)) {
bcopy(&cred->cr_prison->pr_ip6[0], ia6,
sizeof(struct in6_addr));
@@ -1075,23 +1081,21 @@ prison_remote_ip6(struct ucred *cred, st
}
/*
- * Check if given address belongs to the jail referenced by cred.
+ * Check if given address belongs to the jail referenced by cred/prison.
*
- * Returns 1 if address belongs to jail, 0 if not.
+ * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if
+ * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv6.
*/
static int
_prison_check_ip6(struct prison *pr, struct in6_addr *ia6)
{
int i, a, z, d;
- if (pr->pr_ip6 == NULL)
- return (0);
-
/*
* Check the primary IP.
*/
if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6))
- return (1);
+ return (0);
/*
* All the other IPs are sorted so we can do a binary search.
@@ -1106,9 +1110,10 @@ _prison_check_ip6(struct prison *pr, str
else if (d < 0)
a = i + 1;
else
- return (1);
+ return (0);
}
- return (0);
+
+ return (EADDRNOTAVAIL);
}
int
@@ -1119,18 +1124,63 @@ prison_check_ip6(struct ucred *cred, str
KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
if (!jailed(cred))
- return (1);
+ return (0);
+ if (cred->cr_prison->pr_ip6 == NULL)
+ return (EAFNOSUPPORT);
return (_prison_check_ip6(cred->cr_prison, ia6));
}
#endif
/*
+ * Check if a jail supports the given address family.
+ *
+ * Returns 0 if not jailed or the address family is supported, EAFNOSUPPORT
+ * if not.
+ */
+int
+prison_check_af(struct ucred *cred, int af)
+{
+ int error;
+
+ KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
+
+
+ if (!jailed(cred))
+ return (0);
+
+ error = 0;
+ switch (af)
+ {
+#ifdef INET
+ case AF_INET:
+ if (cred->cr_prison->pr_ip4 == NULL)
+ error = EAFNOSUPPORT;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (cred->cr_prison->pr_ip6 == NULL)
+ error = EAFNOSUPPORT;
+ break;
+#endif
+ case AF_LOCAL:
+ case AF_ROUTE:
+ break;
+ default:
+ if (jail_socket_unixiproute_only)
+ error = EAFNOSUPPORT;
+ }
+ return (error);
+}
+
+/*
* Check if given address belongs to the jail referenced by cred (wrapper to
* prison_check_ip[46]).
*
- * Returns 1 if address belongs to jail, 0 if not. IPv4 Address passed in in
- * NBO.
+ * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if
+ * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow
+ * the address family. IPv4 Address passed in in NBO.
*/
int
prison_if(struct ucred *cred, struct sockaddr *sa)
@@ -1141,35 +1191,31 @@ prison_if(struct ucred *cred, struct soc
#ifdef INET6
struct sockaddr_in6 *sai6;
#endif
- int ok;
+ int error;
KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
KASSERT(sa != NULL, ("%s: sa is NULL", __func__));
- ok = 0;
- switch(sa->sa_family)
+ error = 0;
+ switch (sa->sa_family)
{
#ifdef INET
case AF_INET:
sai = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sai->sin_addr))
- ok = 1;
+ error = prison_check_ip4(cred, &sai->sin_addr);
break;
-
#endif
#ifdef INET6
case AF_INET6:
sai6 = (struct sockaddr_in6 *)sa;
- if (prison_check_ip6(cred, (struct in6_addr *)&sai6->sin6_addr))
- ok = 1;
+ error = prison_check_ip6(cred, &sai6->sin6_addr);
break;
-
#endif
default:
- if (!jail_socket_unixiproute_only)
- ok = 1;
+ if (jailed(cred) && jail_socket_unixiproute_only)
+ error = EAFNOSUPPORT;
}
- return (ok);
+ return (error);
}
/*
Modified: stable/7/sys/kern/uipc_socket.c
==============================================================================
--- stable/7/sys/kern/uipc_socket.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/kern/uipc_socket.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -345,15 +345,8 @@ socreate(int dom, struct socket **aso, i
prp->pr_usrreqs->pru_attach == pru_attach_notsupp)
return (EPROTONOSUPPORT);
- if (jailed(cred) && jail_socket_unixiproute_only &&
- prp->pr_domain->dom_family != PF_LOCAL &&
- prp->pr_domain->dom_family != PF_INET &&
-#ifdef INET6
- prp->pr_domain->dom_family != PF_INET6 &&
-#endif
- prp->pr_domain->dom_family != PF_ROUTE) {
+ if (prison_check_af(cred, prp->pr_domain->dom_family) != 0)
return (EPROTONOSUPPORT);
- }
if (prp->pr_type != type)
return (EPROTOTYPE);
Modified: stable/7/sys/net/if.c
==============================================================================
--- stable/7/sys/net/if.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/net/if.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -2196,8 +2196,7 @@ again:
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa = ifa->ifa_addr;
- if (jailed(curthread->td_ucred) &&
- !prison_if(curthread->td_ucred, sa))
+ if (prison_if(curthread->td_ucred, sa) != 0)
continue;
addrs++;
#ifdef COMPAT_43
Modified: stable/7/sys/net/rtsock.c
==============================================================================
--- stable/7/sys/net/rtsock.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/net/rtsock.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -329,55 +329,48 @@ rtm_get_jailed(struct rt_addrinfo *info,
struct rtentry *rt, union sockaddr_union *saun, struct ucred *cred)
{
+ /* First, see if the returned address is part of the jail. */
+ if (prison_if(cred, rt->rt_ifa->ifa_addr) == 0) {
+ info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+ return (0);
+ }
+
switch (info->rti_info[RTAX_DST]->sa_family) {
#ifdef INET
case AF_INET:
{
struct in_addr ia;
+ struct ifaddr *ifa;
+ int found;
+ found = 0;
/*
- * 1. Check if the returned address is part of the jail.
+ * Try to find an address on the given outgoing interface
+ * that belongs to the jail.
*/
- ia = ((struct sockaddr_in *)rt->rt_ifa->ifa_addr)->sin_addr;
- if (prison_check_ip4(cred, &ia) != 0) {
- info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
-
- } else {
- struct ifaddr *ifa;
- int found;
-
- found = 0;
-
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ struct sockaddr *sa;
+ sa = ifa->ifa_addr;
+ if (sa->sa_family != AF_INET)
+ continue;
+ ia = ((struct sockaddr_in *)sa)->sin_addr;
+ if (prison_check_ip4(cred, &ia) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
/*
- * 2. Try to find an address on the given outgoing
- * interface that belongs to the jail.
+ * As a last resort return the 'default' jail address.
*/
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- struct sockaddr *sa;
- sa = ifa->ifa_addr;
- if (sa->sa_family != AF_INET)
- continue;
- ia = ((struct sockaddr_in *)sa)->sin_addr;
- if (prison_check_ip4(cred, &ia) != 0) {
- found = 1;
- break;
- }
- }
- if (!found) {
- /*
- * 3. As a last resort return the 'default'
- * jail address.
- */
- if (prison_get_ip4(cred, &ia) != 0)
- return (ESRCH);
- }
- bzero(&saun->sin, sizeof(struct sockaddr_in));
- saun->sin.sin_len = sizeof(struct sockaddr_in);
- saun->sin.sin_family = AF_INET;
- saun->sin.sin_addr.s_addr = ia.s_addr;
- info->rti_info[RTAX_IFA] =
- (struct sockaddr *)&saun->sin;
+ if (prison_get_ip4(cred, &ia) != 0)
+ return (ESRCH);
}
+ bzero(&saun->sin, sizeof(struct sockaddr_in));
+ saun->sin.sin_len = sizeof(struct sockaddr_in);
+ saun->sin.sin_family = AF_INET;
+ saun->sin.sin_addr.s_addr = ia.s_addr;
+ info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin;
break;
}
#endif
@@ -385,54 +378,40 @@ rtm_get_jailed(struct rt_addrinfo *info,
case AF_INET6:
{
struct in6_addr ia6;
+ struct ifaddr *ifa;
+ int found;
+ found = 0;
/*
- * 1. Check if the returned address is part of the jail.
+ * Try to find an address on the given outgoing interface
+ * that belongs to the jail.
*/
- bcopy(&((struct sockaddr_in6 *)rt->rt_ifa->ifa_addr)->sin6_addr,
- &ia6, sizeof(struct in6_addr));
- if (prison_check_ip6(cred, &ia6) != 0) {
- info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
- } else {
- struct ifaddr *ifa;
- int found;
-
- found = 0;
-
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ struct sockaddr *sa;
+ sa = ifa->ifa_addr;
+ if (sa->sa_family != AF_INET6)
+ continue;
+ bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
+ &ia6, sizeof(struct in6_addr));
+ if (prison_check_ip6(cred, &ia6) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
/*
- * 2. Try to find an address on the given outgoing
- * interface that belongs to the jail.
+ * As a last resort return the 'default' jail address.
*/
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- struct sockaddr *sa;
- sa = ifa->ifa_addr;
- if (sa->sa_family != AF_INET6)
- continue;
- bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
- &ia6, sizeof(struct in6_addr));
- if (prison_check_ip6(cred, &ia6) != 0) {
- found = 1;
- break;
- }
- }
- if (!found) {
- /*
- * 3. As a last resort return the 'default'
- * jail address.
- */
- if (prison_get_ip6(cred, &ia6) != 0)
- return (ESRCH);
- }
- bzero(&saun->sin6, sizeof(struct sockaddr_in6));
- saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
- saun->sin6.sin6_family = AF_INET6;
- bcopy(&ia6, &saun->sin6.sin6_addr,
- sizeof(struct in6_addr));
- if (sa6_recoverscope(&saun->sin6) != 0)
+ if (prison_get_ip6(cred, &ia6) != 0)
return (ESRCH);
- info->rti_info[RTAX_IFA] =
- (struct sockaddr *)&saun->sin6;
}
+ bzero(&saun->sin6, sizeof(struct sockaddr_in6));
+ saun->sin6.sin6_len = sizeof(struct sockaddr_in6);
+ saun->sin6.sin6_family = AF_INET6;
+ bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr));
+ if (sa6_recoverscope(&saun->sin6) != 0)
+ return (ESRCH);
+ info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin6;
break;
}
#endif
@@ -585,9 +564,10 @@ route_output(struct mbuf *m, struct sock
case RTM_GET:
report:
RT_LOCK_ASSERT(rt);
- if (jailed(curthread->td_ucred) &&
- ((rt->rt_flags & RTF_HOST) == 0 ||
- !prison_if(curthread->td_ucred, rt_key(rt)))) {
+ if ((rt->rt_flags & RTF_HOST) == 0
+ ? jailed(curthread->td_ucred)
+ : prison_if(curthread->td_ucred,
+ rt_key(rt)) != 0) {
RT_UNLOCK(rt);
senderr(ESRCH);
}
@@ -600,17 +580,11 @@ route_output(struct mbuf *m, struct sock
if (ifp) {
info.rti_info[RTAX_IFP] =
ifp->if_addr->ifa_addr;
- if (jailed(curthread->td_ucred)) {
- error = rtm_get_jailed(
- &info, ifp, rt, &saun,
- curthread->td_ucred);
- if (error != 0) {
- RT_UNLOCK(rt);
- senderr(ESRCH);
- }
- } else {
- info.rti_info[RTAX_IFA] =
- rt->rt_ifa->ifa_addr;
+ error = rtm_get_jailed(&info, ifp, rt,
+ &saun, curthread->td_ucred);
+ if (error != 0) {
+ RT_UNLOCK(rt);
+ senderr(error);
}
if (ifp->if_flags & IFF_POINTOPOINT)
info.rti_info[RTAX_BRD] =
@@ -1230,9 +1204,9 @@ sysctl_dumpentry(struct radix_node *rn,
if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
return 0;
- if (jailed(w->w_req->td->td_ucred) &&
- ((rt->rt_flags & RTF_HOST) == 0 ||
- !prison_if(w->w_req->td->td_ucred, rt_key(rt))))
+ if ((rt->rt_flags & RTF_HOST) == 0
+ ? jailed(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));
info.rti_info[RTAX_DST] = rt_key(rt);
@@ -1293,8 +1267,8 @@ sysctl_iflist(int af, struct walkarg *w)
while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
if (af && af != ifa->ifa_addr->sa_family)
continue;
- if (jailed(w->w_req->td->td_ucred) &&
- !prison_if(w->w_req->td->td_ucred, ifa->ifa_addr))
+ if (prison_if(w->w_req->td->td_ucred,
+ ifa->ifa_addr) != 0)
continue;
info.rti_info[RTAX_IFA] = ifa->ifa_addr;
info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
@@ -1341,8 +1315,8 @@ sysctl_ifmalist(int af, struct walkarg *
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (af && af != ifma->ifma_addr->sa_family)
continue;
- if (jailed(w->w_req->td->td_ucred) &&
- !prison_if(w->w_req->td->td_ucred, ifma->ifma_addr))
+ if (prison_if(w->w_req->td->td_ucred,
+ ifma->ifma_addr) != 0)
continue;
info.rti_info[RTAX_IFA] = ifma->ifma_addr;
info.rti_info[RTAX_GATEWAY] =
Modified: stable/7/sys/netinet/in.c
==============================================================================
--- stable/7/sys/netinet/in.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/netinet/in.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -255,7 +255,7 @@ in_control(struct socket *so, u_long cmd
if (iap->ia_ifp == ifp &&
iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
if (td == NULL || prison_check_ip4(
- td->td_ucred, &dst))
+ td->td_ucred, &dst) == 0)
ia = iap;
break;
}
@@ -264,8 +264,8 @@ in_control(struct socket *so, u_long cmd
iap = ifatoia(ifa);
if (iap->ia_addr.sin_family == AF_INET) {
if (td != NULL &&
- !prison_check_ip4(td->td_ucred,
- &iap->ia_addr.sin_addr))
+ prison_check_ip4(td->td_ucred,
+ &iap->ia_addr.sin_addr) != 0)
continue;
ia = iap;
break;
Modified: stable/7/sys/netinet/in_pcb.c
==============================================================================
--- stable/7/sys/netinet/in_pcb.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/netinet/in_pcb.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -296,7 +296,10 @@ in_pcbbind_setup(struct inpcb *inp, stru
return (EINVAL);
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
wild = INPLOOKUP_WILDCARD;
- if (nam) {
+ if (nam == NULL) {
+ if ((error = prison_local_ip4(cred, &laddr)) != 0)
+ return (error);
+ } else {
sin = (struct sockaddr_in *)nam;
if (nam->sa_len != sizeof (*sin))
return (EINVAL);
@@ -308,8 +311,9 @@ in_pcbbind_setup(struct inpcb *inp, stru
if (sin->sin_family != AF_INET)
return (EAFNOSUPPORT);
#endif
- if (prison_local_ip4(cred, &sin->sin_addr))
- return (EINVAL);
+ error = prison_local_ip4(cred, &sin->sin_addr);
+ if (error)
+ return (error);
if (sin->sin_port != *lportp) {
/* Don't allow the port to change. */
if (*lportp != 0)
@@ -365,8 +369,6 @@ in_pcbbind_setup(struct inpcb *inp, stru
t->inp_cred->cr_uid))
return (EADDRINUSE);
}
- if (prison_local_ip4(cred, &sin->sin_addr))
- return (EADDRNOTAVAIL);
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, wild, cred);
if (t && (t->inp_vflag & INP_TIMEWAIT)) {
@@ -400,9 +402,6 @@ in_pcbbind_setup(struct inpcb *inp, stru
u_short first, last;
int count;
- if (prison_local_ip4(cred, &laddr))
- return (EINVAL);
-
if (inp->inp_flags & INP_HIGHPORT) {
first = ipport_hifirstauto; /* sysctl */
last = ipport_hilastauto;
@@ -485,8 +484,6 @@ in_pcbbind_setup(struct inpcb *inp, stru
wild, cred));
}
}
- if (prison_local_ip4(cred, &laddr))
- return (EINVAL);
*laddrp = laddr.s_addr;
*lportp = lport;
return (0);
@@ -606,7 +603,7 @@ in_pcbladdr(struct inpcb *inp, struct in
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)ifa;
break;
}
@@ -617,8 +614,7 @@ in_pcbladdr(struct inpcb *inp, struct in
}
/* 3. As a last resort return the 'default' jail address. */
- if (prison_get_ip4(cred, laddr) != 0)
- error = EADDRNOTAVAIL;
+ error = prison_get_ip4(cred, laddr);
goto done;
}
@@ -643,7 +639,7 @@ in_pcbladdr(struct inpcb *inp, struct in
/* Jailed. */
/* 1. Check if the iface address belongs to the jail. */
sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa;
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
goto done;
@@ -659,7 +655,7 @@ in_pcbladdr(struct inpcb *inp, struct in
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)ifa;
break;
}
@@ -670,8 +666,7 @@ in_pcbladdr(struct inpcb *inp, struct in
}
/* 3. As a last resort return the 'default' jail address. */
- if (prison_get_ip4(cred, laddr) != 0)
- error = EADDRNOTAVAIL;
+ error = prison_get_ip4(cred, laddr);
goto done;
}
@@ -721,7 +716,8 @@ in_pcbladdr(struct inpcb *inp, struct in
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred,
+ &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)ifa;
break;
}
@@ -733,8 +729,7 @@ in_pcbladdr(struct inpcb *inp, struct in
}
/* 3. As a last resort return the 'default' jail address. */
- if (prison_get_ip4(cred, laddr) != 0)
- error = EADDRNOTAVAIL;
+ error = prison_get_ip4(cred, laddr);
goto done;
}
@@ -767,7 +762,7 @@ in_pcbconnect_setup(struct inpcb *inp, s
struct sockaddr_in *sin = (struct sockaddr_in *)nam;
struct in_ifaddr *ia;
struct inpcb *oinp;
- struct in_addr laddr, faddr, jailia;
+ struct in_addr laddr, faddr;
u_short lport, fport;
int error;
@@ -800,15 +795,11 @@ in_pcbconnect_setup(struct inpcb *inp, s
* choose the broadcast address for that interface.
*/
if (faddr.s_addr == INADDR_ANY) {
- if (cred != NULL && jailed(cred)) {
- if (prison_get_ip4(cred, &jailia) != 0)
- return (EADDRNOTAVAIL);
- faddr.s_addr = jailia.s_addr;
- } else {
- faddr =
- IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->
- sin_addr;
- }
+ faddr =
+ IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr;
+ if (cred != NULL &&
+ (error = prison_get_ip4(cred, &faddr)) != 0)
+ return (error);
} else if (faddr.s_addr == (u_long)INADDR_BROADCAST &&
(TAILQ_FIRST(&in_ifaddrhead)->ia_ifp->if_flags &
IFF_BROADCAST))
@@ -1290,7 +1281,8 @@ in_pcblookup_hash(struct inpcbinfo *pcbi
injail = jailed(inp->inp_cred);
if (injail) {
- if (!prison_check_ip4(inp->inp_cred, &laddr))
+ if (prison_check_ip4(inp->inp_cred,
+ &laddr) != 0)
continue;
} else {
if (local_exact != NULL)
Modified: stable/7/sys/netinet/raw_ip.c
==============================================================================
--- stable/7/sys/netinet/raw_ip.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/netinet/raw_ip.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -265,10 +265,8 @@ 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 (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
- continue;
- }
+ if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
+ continue;
if (last) {
struct mbuf *n;
@@ -295,10 +293,8 @@ rip_input(struct mbuf *m, int off)
if (inp->inp_faddr.s_addr &&
inp->inp_faddr.s_addr != ip->ip_src.s_addr)
continue;
- if (jailed(inp->inp_cred)) {
- if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
- continue;
- }
+ if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
+ continue;
if (last) {
struct mbuf *n;
@@ -358,14 +354,12 @@ rip_output(struct mbuf *m, struct socket
ip->ip_off = 0;
ip->ip_p = inp->inp_ip_p;
ip->ip_len = m->m_pkthdr.len;
- if (jailed(inp->inp_cred)) {
- if (prison_get_ip4(inp->inp_cred, &ip->ip_src) != 0) {
- INP_RUNLOCK(inp);
- m_freem(m);
- return (EPERM);
- }
- } else {
- ip->ip_src = inp->inp_laddr;
+ ip->ip_src = inp->inp_laddr;
+ error = prison_get_ip4(inp->inp_cred, &ip->ip_src);
+ if (error != 0) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (error);
}
ip->ip_dst.s_addr = dst;
ip->ip_ttl = inp->inp_ip_ttl;
@@ -376,10 +370,11 @@ rip_output(struct mbuf *m, struct socket
}
INP_RLOCK(inp);
ip = mtod(m, struct ip *);
- if (!prison_check_ip4(inp->inp_cred, &ip->ip_src)) {
+ error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
+ if (error != 0) {
INP_RUNLOCK(inp);
m_freem(m);
- return (EPERM);
+ return (error);
}
/*
@@ -783,12 +778,14 @@ rip_bind(struct socket *so, struct socka
{
struct sockaddr_in *addr = (struct sockaddr_in *)nam;
struct inpcb *inp;
+ int error;
if (nam->sa_len != sizeof(*addr))
return (EINVAL);
- if (!prison_check_ip4(td->td_ucred, &addr->sin_addr))
- return (EADDRNOTAVAIL);
+ error = prison_check_ip4(td->td_ucred, &addr->sin_addr);
+ if (error != 0)
+ return (error);
if (TAILQ_EMPTY(&ifnet) ||
(addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||
Modified: stable/7/sys/netinet/tcp_usrreq.c
==============================================================================
--- stable/7/sys/netinet/tcp_usrreq.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/netinet/tcp_usrreq.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -462,8 +462,8 @@ tcp_usr_connect(struct socket *so, struc
if (sinp->sin_family == AF_INET
&& IN_MULTICAST(ntohl(sinp->sin_addr.s_addr)))
return (EAFNOSUPPORT);
- if (prison_remote_ip4(td->td_ucred, &sinp->sin_addr) != 0)
- return (EINVAL);
+ if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr)) != 0)
+ return (error);
TCPDEBUG0;
INP_INFO_WLOCK(&tcbinfo);
@@ -528,10 +528,9 @@ tcp6_usr_connect(struct socket *so, stru
in6_sin6_2_sin(&sin, sin6p);
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
- if (prison_remote_ip4(td->td_ucred, &sin.sin_addr) != 0) {
- error = EINVAL;
+ if ((error = prison_remote_ip4(td->td_ucred,
+ &sin.sin_addr)) != 0)
goto out;
- }
if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0)
goto out;
error = tcp_output_connect(so, nam);
@@ -540,10 +539,8 @@ tcp6_usr_connect(struct socket *so, stru
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
inp->inp_inc.inc_isipv6 = 1;
- if (prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr) != 0) {
- error = EINVAL;
+ if ((error = prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr)) != 0)
goto out;
- }
if ((error = tcp6_connect(tp, nam, td)) != 0)
goto out;
error = tcp_output_connect(so, nam);
Modified: stable/7/sys/netinet/udp_usrreq.c
==============================================================================
--- stable/7/sys/netinet/udp_usrreq.c Wed Feb 18 19:59:27 2009 (r188760)
+++ stable/7/sys/netinet/udp_usrreq.c Wed Feb 18 20:12:08 2009 (r188761)
@@ -938,10 +938,9 @@ udp_output(struct inpcb *inp, struct mbu
* Jail may rewrite the destination address, so let it do
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-7
mailing list