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

Log:
  Protect against some writer-writer races in in_control() by acquiring
  the interface address list lock around interface address list
  modifications.  More to do here.
  
  MFC after:    2 weeks

Modified:
  head/sys/netinet/in.c

Modified: head/sys/netinet/in.c
==============================================================================
--- head/sys/netinet/in.c       Sun Apr 19 22:05:39 2009        (r191284)
+++ head/sys/netinet/in.c       Sun Apr 19 22:16:19 2009        (r191285)
@@ -330,14 +330,12 @@ in_control(struct socket *so, u_long cmd
                         * Protect from ipintr() traversing address list
                         * while we're modifying it.
                         */
-                       s = splnet();
                        ifa = &ia->ia_ifa;
                        IFA_LOCK_INIT(ifa);
                        ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
                        ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
                        ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
                        ifa->ifa_refcnt = 1;
-                       TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
 
                        ia->ia_sockmask.sin_len = 8;
                        ia->ia_sockmask.sin_family = AF_INET;
@@ -347,6 +345,10 @@ in_control(struct socket *so, u_long cmd
                        }
                        ia->ia_ifp = ifp;
 
+                       IF_ADDR_LOCK(ifp);
+                       TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
+                       IF_ADDR_UNLOCK(ifp);
+                       s = splnet();
                        TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
                        splx(s);
                        iaIsNew = 1;
@@ -512,8 +514,10 @@ in_control(struct socket *so, u_long cmd
         * Protect from ipintr() traversing address list while we're modifying
         * it.
         */
-       s = splnet();
+       IF_ADDR_LOCK(ifp);
        TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
+       IF_ADDR_UNLOCK(ifp);
+       s = splnet();
        TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
        if (ia->ia_addr.sin_family == AF_INET) {
                LIST_REMOVE(ia, ia_hash);
_______________________________________________
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