Author: rwatson
Date: Sun Apr 19 22:25:09 2009
New Revision: 191286
URL: http://svn.freebsd.org/changeset/base/191286

Log:
  Lock interface address lists in in_pcbladdr() when searching for a
  source address for a connection and there's no route or now interface
  for the route.
  
  MFC after:    2 weeks

Modified:
  head/sys/netinet/in_pcb.c

Modified: head/sys/netinet/in_pcb.c
==============================================================================
--- head/sys/netinet/in_pcb.c   Sun Apr 19 22:16:19 2009        (r191285)
+++ head/sys/netinet/in_pcb.c   Sun Apr 19 22:25:09 2009        (r191286)
@@ -605,6 +605,7 @@ in_pcbladdr(struct inpcb *inp, struct in
 
                ifp = ia->ia_ifp;
                ia = NULL;
+               IF_ADDR_LOCK(ifp);
                TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 
                        sa = ifa->ifa_addr;
@@ -618,8 +619,10 @@ in_pcbladdr(struct inpcb *inp, struct in
                }
                if (ia != NULL) {
                        laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
+                       IF_ADDR_UNLOCK(ifp);
                        goto done;
                }
+               IF_ADDR_UNLOCK(ifp);
 
                /* 3. As a last resort return the 'default' jail address. */
                error = prison_get_ip4(cred, laddr);
@@ -636,6 +639,7 @@ in_pcbladdr(struct inpcb *inp, struct in
         * 3. as a last resort return the 'default' jail address.
         */
        if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) {
+               struct ifnet *ifp;
 
                /* If not jailed, use the default returned. */
                if (cred == NULL || !jailed(cred)) {
@@ -657,7 +661,9 @@ in_pcbladdr(struct inpcb *inp, struct in
                 * 2. Check if we have any address on the outgoing interface
                 *    belonging to this jail.
                 */
-               TAILQ_FOREACH(ifa, &sro.ro_rt->rt_ifp->if_addrhead, ifa_link) {
+               ifp = sro.ro_rt->rt_ifp;
+               IF_ADDR_LOCK(ifp);
+               TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 
                        sa = ifa->ifa_addr;
                        if (sa->sa_family != AF_INET)
@@ -670,8 +676,10 @@ in_pcbladdr(struct inpcb *inp, struct in
                }
                if (ia != NULL) {
                        laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
+                       IF_ADDR_UNLOCK(ifp);
                        goto done;
                }
+               IF_ADDR_UNLOCK(ifp);
 
                /* 3. As a last resort return the 'default' jail address. */
                error = prison_get_ip4(cred, laddr);
@@ -718,6 +726,7 @@ in_pcbladdr(struct inpcb *inp, struct in
 
                        ifp = ia->ia_ifp;
                        ia = NULL;
+                       IF_ADDR_LOCK(ifp);
                        TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 
                                sa = ifa->ifa_addr;
@@ -732,8 +741,10 @@ in_pcbladdr(struct inpcb *inp, struct in
                        }
                        if (ia != NULL) {
                                laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
+                               IF_ADDR_UNLOCK(ifp);
                                goto done;
                        }
+                       IF_ADDR_UNLOCK(ifp);
                }
 
                /* 3. As a last resort return the 'default' jail address. */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to