Author: bz Date: Tue Apr 27 15:05:03 2010 New Revision: 207276 URL: http://svn.freebsd.org/changeset/base/207276
Log: Make sure IPv6 source address selection does not change interface addresses while walking the IPv6 address list if in the jail case something is connecting to ::1. Reported by: Pieter de Boer (pieter thedarkside.nl) Tested by: Pieter de Boer (pieter thedarkside.nl) MFC after: 4 days Modified: head/sys/netinet6/in6_src.c Modified: head/sys/netinet6/in6_src.c ============================================================================== --- head/sys/netinet6/in6_src.c Tue Apr 27 14:14:21 2010 (r207275) +++ head/sys/netinet6/in6_src.c Tue Apr 27 15:05:03 2010 (r207276) @@ -182,7 +182,7 @@ in6_selectsrc(struct sockaddr_in6 *dstso struct inpcb *inp, struct route_in6 *ro, struct ucred *cred, struct ifnet **ifpp, struct in6_addr *srcp) { - struct in6_addr dst; + struct in6_addr dst, tmp; struct ifnet *ifp = NULL; struct in6_ifaddr *ia = NULL, *ia_best = NULL; struct in6_pktinfo *pi = NULL; @@ -326,10 +326,9 @@ in6_selectsrc(struct sockaddr_in6 *dstso if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia)) continue; + /* If jailed only take addresses of the jail into account. */ if (cred != NULL && - prison_local_ip6(cred, &ia->ia_addr.sin6_addr, - (inp != NULL && - (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) + prison_check_ip6(cred, &ia->ia_addr.sin6_addr) != 0) continue; /* Rule 1: Prefer same address */ @@ -476,10 +475,26 @@ in6_selectsrc(struct sockaddr_in6 *dstso return (EADDRNOTAVAIL); } + /* + * At this point at least one of the addresses belonged to the jail + * but it could still be, that we want to further restrict it, e.g. + * theoratically IN6_IS_ADDR_LOOPBACK. + * It must not be IN6_IS_ADDR_UNSPECIFIED anymore. + * prison_local_ip6() will fix an IN6_IS_ADDR_LOOPBACK but should + * let all others previously selected pass. + * Use tmp to not change ::1 on lo0 to the primary jail address. + */ + tmp = ia->ia_addr.sin6_addr; + if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL && + (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { + IN6_IFADDR_RUNLOCK(); + return (EADDRNOTAVAIL); + } + if (ifpp) *ifpp = ifp; - bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp)); + bcopy(&tmp, srcp, sizeof(*srcp)); IN6_IFADDR_RUNLOCK(); return (0); } _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"