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"

Reply via email to