diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2 index 6a61426bd7a..8fa2c64354d 100644 --- a/lib/libc/sys/send.2 +++ b/lib/libc/sys/send.2 @@ -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 port. 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 diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index b87de0b9d71..9b2f6d8a8f8 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -217,7 +217,7 @@ prison_check_conflicting_ips(struct prison *p) 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); } } @@ -226,7 +226,7 @@ prison_check_conflicting_ips(struct prison *p) 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); } } @@ -807,9 +807,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) @@ -823,7 +824,7 @@ prison_get_ip4(struct ucred *cred, struct in_addr *ia) 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); @@ -833,8 +834,9 @@ prison_get_ip4(struct ucred *cred, struct in_addr *ia) * 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) @@ -847,7 +849,7 @@ prison_local_ip4(struct ucred *cred, struct in_addr *ia) 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) { @@ -855,25 +857,23 @@ prison_local_ip4(struct ucred *cred, struct in_addr *ia) 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) @@ -885,7 +885,8 @@ prison_remote_ip4(struct ucred *cred, struct in_addr *ia) 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); @@ -898,23 +899,22 @@ prison_remote_ip4(struct ucred *cred, struct in_addr *ia) } /* - * 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. @@ -929,9 +929,10 @@ _prison_check_ip4(struct prison *pr, struct in_addr *ia) else if (d < 0) a = i + 1; else - return (1); + return (0); } - return (0); + + return (EADDRNOTAVAIL); } int @@ -942,7 +943,9 @@ prison_check_ip4(struct ucred *cred, struct in_addr *ia) 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)); } @@ -953,9 +956,9 @@ prison_check_ip4(struct ucred *cred, struct in_addr *ia) * 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) @@ -967,7 +970,8 @@ prison_get_ip6(struct ucred *cred, struct in6_addr *ia6) 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); } @@ -978,7 +982,8 @@ prison_get_ip6(struct ucred *cred, struct in6_addr *ia6) * 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) @@ -990,32 +995,32 @@ prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only) 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) @@ -1027,7 +1032,8 @@ prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6) 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)); @@ -1041,23 +1047,21 @@ prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6) } /* - * 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. @@ -1072,9 +1076,10 @@ _prison_check_ip6(struct prison *pr, struct in6_addr *ia6) else if (d < 0) a = i + 1; else - return (1); + return (0); } - return (0); + + return (EADDRNOTAVAIL); } int @@ -1085,7 +1090,9 @@ prison_check_ip6(struct ucred *cred, struct in6_addr *ia6) 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)); } @@ -1095,8 +1102,9 @@ prison_check_ip6(struct ucred *cred, struct in6_addr *ia6) * 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) @@ -1107,35 +1115,31 @@ prison_if(struct ucred *cred, struct sockaddr *sa) #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); } /* diff --git a/sys/net/if.c b/sys/net/if.c index 2fb8e236fa7..6966a51462b 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2271,8 +2271,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 diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 12a3cba4b80..8d2d07af4c8 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -347,7 +347,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, * 1. Check if the returned address is part of the jail. */ ia = ((struct sockaddr_in *)rt->rt_ifa->ifa_addr)->sin_addr; - if (prison_check_ip4(cred, &ia) != 0) { + if (prison_check_ip4(cred, &ia) == 0) { info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } else { @@ -366,7 +366,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, if (sa->sa_family != AF_INET) continue; ia = ((struct sockaddr_in *)sa)->sin_addr; - if (prison_check_ip4(cred, &ia) != 0) { + if (prison_check_ip4(cred, &ia) == 0) { found = 1; break; } @@ -399,7 +399,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, */ bcopy(&((struct sockaddr_in6 *)rt->rt_ifa->ifa_addr)->sin6_addr, &ia6, sizeof(struct in6_addr)); - if (prison_check_ip6(cred, &ia6) != 0) { + if (prison_check_ip6(cred, &ia6) == 0) { info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } else { struct ifaddr *ifa; @@ -418,7 +418,7 @@ rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, continue; bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr, &ia6, sizeof(struct in6_addr)); - if (prison_check_ip6(cred, &ia6) != 0) { + if (prison_check_ip6(cred, &ia6) == 0) { found = 1; break; } @@ -612,9 +612,10 @@ route_output(struct mbuf *m, struct socket *so) 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); } @@ -1263,9 +1264,9 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) 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); @@ -1327,8 +1328,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; @@ -1376,8 +1377,8 @@ sysctl_ifmalist(int af, struct walkarg *w) 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] = diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 03c72697c12..bf1ebae81e8 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -264,7 +264,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, 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; } @@ -273,8 +273,8 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, 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; @@ -1199,8 +1199,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr) if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID) continue; /* Skip if jailed and not a valid IP of the prison. */ - if (jailed(wr->td->td_ucred) && - !prison_if(wr->td->td_ucred, L3_ADDR(lle))) + if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0) continue; /* * produce a msg made of: diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 4a7e4f92a18..25494cfbfb9 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -325,8 +325,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, 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) @@ -391,8 +392,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, t->inp_cred->cr_uid)) return (EADDRINUSE); } - if (prison_local_ip4(cred, &sin->sin_addr)) - return (EADDRNOTAVAIL); + error = prison_local_ip4(cred, &sin->sin_addr); + if (error) + return (error); t = in_pcblookup_local(pcbinfo, sin->sin_addr, lport, wild, cred); if (t && (t->inp_vflag & INP_TIMEWAIT)) { @@ -426,8 +428,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, u_short first, last, aux; int count; - if (prison_local_ip4(cred, &laddr)) - return (EINVAL); + error = prison_local_ip4(cred, &laddr); + if (error) + return (error); if (inp->inp_flags & INP_HIGHPORT) { first = V_ipport_hifirstauto; /* sysctl */ @@ -493,8 +496,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, } while (in_pcblookup_local(pcbinfo, laddr, lport, wild, cred)); } - if (prison_local_ip4(cred, &laddr)) - return (EINVAL); + error = prison_local_ip4(cred, &laddr); + if (error) + return (error); *laddrp = laddr.s_addr; *lportp = lport; return (0); @@ -614,7 +618,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, 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; } @@ -625,8 +629,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, } /* 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; } @@ -651,7 +654,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, /* 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; @@ -667,7 +670,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, 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; } @@ -678,8 +681,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, } /* 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; } @@ -729,7 +731,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, 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; } @@ -741,8 +744,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, } /* 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; } @@ -776,7 +778,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, 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; @@ -809,15 +811,11 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, * 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(&V_in_ifaddrhead))-> - sin_addr; - } + faddr = + IA_SIN(TAILQ_FIRST(&V_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(&V_in_ifaddrhead)->ia_ifp->if_flags & IFF_BROADCAST)) @@ -1375,7 +1373,8 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, 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) diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 8f6d8ecd4a5..27f4b9ca179 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -276,10 +276,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 != NULL) { struct mbuf *n; @@ -306,10 +304,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 != NULL) { struct mbuf *n; @@ -370,14 +366,12 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) 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; @@ -388,10 +382,11 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) } 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); } /* @@ -803,12 +798,14 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td) INIT_VNET_INET(so->so_vnet); 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(&V_ifnet) || (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) || diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index f6dcae1a20b..89987c4c7e4 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -441,8 +441,8 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 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(&V_tcbinfo); @@ -508,10 +508,9 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 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); @@ -520,10 +519,8 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; inp->inp_inc.inc_flags |= INC_ISIPV6; - 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); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 7eaa0e36546..804f5fe78d4 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -982,10 +982,9 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, * Jail may rewrite the destination address, so let it do * that before we use it. */ - if (prison_remote_ip4(td->td_ucred, &sin->sin_addr) != 0) { - error = EINVAL; + error = prison_remote_ip4(td->td_ucred, &sin->sin_addr); + if (error) goto release; - } /* * If a local address or port hasn't yet been selected, or if @@ -1271,10 +1270,11 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) return (EISCONN); } sin = (struct sockaddr_in *)nam; - if (prison_remote_ip4(td->td_ucred, &sin->sin_addr) != 0) { + error = prison_remote_ip4(td->td_ucred, &sin->sin_addr); + if (error != 0) { INP_WUNLOCK(inp); INP_INFO_WUNLOCK(&V_udbinfo); - return (EAFNOSUPPORT); + return (error); } error = in_pcbconnect(inp, nam, td->td_ucred); if (error == 0) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 693a2f979d3..81a37f845b7 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -330,9 +330,9 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, error = in6_setscope(&sa6->sin6_addr, ifp, NULL); if (error != 0) return (error); - if (td != NULL && !prison_check_ip6(td->td_ucred, - &sa6->sin6_addr)) - return (EADDRNOTAVAIL); + if (td != NULL && (error = prison_check_ip6(td->td_ucred, + &sa6->sin6_addr)) != 0) + return (error); ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); } else ia = NULL; @@ -2241,8 +2241,7 @@ in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr) if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID) continue; /* Skip if jailed and not a valid IP of the prison. */ - if (jailed(wr->td->td_ucred) && - !prison_if(wr->td->td_ucred, L3_ADDR(lle))) + if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0) continue; /* * produce a msg made of: diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 753f45df0e0..13c55cdeb83 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -119,7 +119,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; u_short lport = 0; - int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); + int error, wild = 0, reuseport = (so->so_options & SO_REUSEPORT); INP_INFO_WLOCK_ASSERT(pcbinfo); INP_WLOCK_ASSERT(inp); @@ -131,8 +131,6 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) wild = INPLOOKUP_WILDCARD; if (nam) { - int error; - sin6 = (struct sockaddr_in6 *)nam; if (nam->sa_len != sizeof(*sin6)) return (EINVAL); @@ -145,9 +143,9 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) return(error); - if (prison_local_ip6(cred, &sin6->sin6_addr, - ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) - return (EINVAL); + if ((error = prison_local_ip6(cred, &sin6->sin6_addr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) + return (error); lport = sin6->sin6_port; if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { @@ -223,9 +221,9 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, return (EADDRINUSE); } } - if (prison_local_ip6(cred, &sin6->sin6_addr, - ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) - return (EADDRNOTAVAIL); + if ((error = prison_local_ip6(cred, &sin6->sin6_addr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) + return (error); t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, lport, wild, cred); if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ? @@ -258,13 +256,12 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, } inp->in6p_laddr = sin6->sin6_addr; } - if (prison_local_ip6(cred, &inp->in6p_laddr, - ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) - return (EINVAL); + if ((error = prison_local_ip6(cred, &inp->in6p_laddr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) + return (error); if (lport == 0) { - int e; - if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) - return (e); + if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) + return (error); } else { inp->inp_lport = lport; if (in_pcbinshash(inp) != 0) { @@ -320,8 +317,8 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam, if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) sin6->sin6_addr = in6addr_loopback; } - if (prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr) != 0) - return (EADDRNOTAVAIL); + if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0) + return (error); /* * XXX: in6_selectsrc might replace the bound local address @@ -885,7 +882,8 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, injail = jailed(inp->inp_cred); if (injail) { - if (!prison_check_ip6(inp->inp_cred, laddr)) + if (prison_check_ip6(inp->inp_cred, + laddr) != 0) continue; } else { if (local_exact != NULL) diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index ca65bc9a856..80304169490 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -240,11 +240,10 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, if (*errorp != 0) return (NULL); } - if (cred != NULL && prison_local_ip6(cred, &srcsock.sin6_addr, - (inp != NULL && (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { - *errorp = EADDRNOTAVAIL; + if (cred != NULL && (*errorp = prison_local_ip6(cred, + &srcsock.sin6_addr, (inp != NULL && + (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) return (NULL); - } ia6 = (struct in6_ifaddr *)ifa_ifwithaddr((struct sockaddr *)(&srcsock)); if (ia6 == NULL || @@ -262,11 +261,10 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, * Otherwise, if the socket has already bound the source, just use it. */ if (inp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { - if (cred != NULL && prison_local_ip6(cred, &inp->in6p_laddr, - ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { - *errorp = EADDRNOTAVAIL; + if (cred != NULL && + (*errorp = prison_local_ip6(cred, &inp->in6p_laddr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) return (NULL); - } return (&inp->in6p_laddr); } @@ -823,15 +821,16 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred) INIT_VNET_INET(curvnet); struct socket *so = inp->inp_socket; u_int16_t lport = 0, first, last, *lastport; - int count, error = 0, wild = 0, dorandom; + int count, error, wild = 0, dorandom; struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; INP_INFO_WLOCK_ASSERT(pcbinfo); INP_WLOCK_ASSERT(inp); - if (prison_local_ip6(cred, laddr, - ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) - return(EINVAL); + error = prison_local_ip6(cred, laddr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)); + if (error) + return(error); /* XXX: this is redundant when called from in6_pcbbind */ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 18b8131fc6e..da781a06a02 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -179,10 +179,8 @@ 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 (!prison_check_ip6(in6p->inp_cred, &ip6->ip6_dst)) - continue; - } + if (prison_check_ip6(in6p->inp_cred, &ip6->ip6_dst) != 0) + continue; INP_RLOCK(in6p); if (in6p->in6p_cksum != -1) { V_rip6stat.rip6s_isum++; @@ -411,11 +409,9 @@ rip6_output(m, va_alist) error = EADDRNOTAVAIL; goto bad; } - if (jailed(in6p->inp_cred)) - if (prison_get_ip6(in6p->inp_cred, in6a) != 0) { - error = EPERM; - goto bad; - } + error = prison_get_ip6(in6p->inp_cred, in6a); + if (error != 0) + goto bad; ip6->ip6_src = *in6a; if (oifp && scope_ambiguous) { @@ -678,8 +674,8 @@ rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) if (nam->sa_len != sizeof(*addr)) return (EINVAL); - if (!prison_check_ip6(td->td_ucred, &addr->sin6_addr)) - return (EADDRNOTAVAIL); + if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0) + return (error); if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6) return (EADDRNOTAVAIL); if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0) diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index dea8ed22013..d0bcfc02132 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -902,12 +902,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) goto out; } in6_sin6_2_sin(&sin, sin6_p); - if (td && jailed(td->td_ucred)) - if (prison_remote_ip4(td->td_ucred, - &sin.sin_addr) != 0) { - error = EAFNOSUPPORT; - goto out; - } + if (td && (error = prison_remote_ip4(td->td_ucred, + &sin.sin_addr)) != 0) + goto out; error = in_pcbconnect(inp, (struct sockaddr *)&sin, td->td_ucred); if (error == 0) { @@ -922,12 +919,11 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) error = EISCONN; goto out; } - if (td && jailed(td->td_ucred)) { + if (td) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; - if (prison_remote_ip6(td->td_ucred, &sin6->sin6_addr) != 0) { - error = EAFNOSUPPORT; + if ((error = prison_remote_ip6(td->td_ucred, + &sin6->sin6_addr)) != 0) goto out; - } } error = in6_pcbconnect(inp, nam, td->td_ucred); if (error == 0) {