diff options
author | jamie <jamie@FreeBSD.org> | 2009-02-05 14:06:09 +0000 |
---|---|---|
committer | jamie <jamie@FreeBSD.org> | 2009-02-05 14:06:09 +0000 |
commit | 12bbe1869f5926ca7e3457f5424afdca31a1189b (patch) | |
tree | 71fe0b10296684e7094a545ca78ed6f72789d82d /sys/kern/kern_jail.c | |
parent | 2926f8fa435de3f0b595eb5309b2a0c364703371 (diff) | |
download | FreeBSD-src-12bbe1869f5926ca7e3457f5424afdca31a1189b.zip FreeBSD-src-12bbe1869f5926ca7e3457f5424afdca31a1189b.tar.gz |
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.
Approved by: bz (mentor)
Diffstat (limited to 'sys/kern/kern_jail.c')
-rw-r--r-- | sys/kern/kern_jail.c | 144 |
1 files changed, 74 insertions, 70 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index b87de0b..9b2f6d8 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); } /* |