From owner-svn-src-head@FreeBSD.ORG Tue Apr 21 19:06:47 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BA6971065672; Tue, 21 Apr 2009 19:06:47 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A80FA8FC15; Tue, 21 Apr 2009 19:06:47 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n3LJ6ljA019221; Tue, 21 Apr 2009 19:06:47 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n3LJ6l16019220; Tue, 21 Apr 2009 19:06:47 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200904211906.n3LJ6l16019220@svn.freebsd.org> From: Robert Watson Date: Tue, 21 Apr 2009 19:06:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r191365 - head/sys/net X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Apr 2009 19:06:48 -0000 Author: rwatson Date: Tue Apr 21 19:06:47 2009 New Revision: 191365 URL: http://svn.freebsd.org/changeset/base/191365 Log: Acquire the interface address list lock over some iterations over if_addrhead. This closes some reader-writer races associated with the address list. MFC after: 2 weeks Modified: head/sys/net/if.c Modified: head/sys/net/if.c ============================================================================== --- head/sys/net/if.c Tue Apr 21 17:44:46 2009 (r191364) +++ head/sys/net/if.c Tue Apr 21 19:06:47 2009 (r191365) @@ -1249,19 +1249,26 @@ ifa_ifwithaddr(struct sockaddr *addr) struct ifaddr *ifa; IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) + TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; - if (sa_equal(addr, ifa->ifa_addr)) + if (sa_equal(addr, ifa->ifa_addr)) { + IF_ADDR_UNLOCK(ifp); goto done; + } /* IP6 doesn't have broadcast */ if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && ifa->ifa_broadaddr->sa_len != 0 && - sa_equal(ifa->ifa_broadaddr, addr)) + sa_equal(ifa->ifa_broadaddr, addr)) { + IF_ADDR_UNLOCK(ifp); goto done; + } } + IF_ADDR_UNLOCK(ifp); + } ifa = NULL; done: IFNET_RUNLOCK(); @@ -1280,16 +1287,21 @@ ifa_ifwithbroadaddr(struct sockaddr *add struct ifaddr *ifa; IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) + TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && ifa->ifa_broadaddr->sa_len != 0 && - sa_equal(ifa->ifa_broadaddr, addr)) + sa_equal(ifa->ifa_broadaddr, addr)) { + IF_ADDR_UNLOCK(ifp); goto done; + } } + IF_ADDR_UNLOCK(ifp); + } ifa = NULL; done: IFNET_RUNLOCK(); @@ -1311,13 +1323,17 @@ ifa_ifwithdstaddr(struct sockaddr *addr) TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((ifp->if_flags & IFF_POINTOPOINT) == 0) continue; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (ifa->ifa_dstaddr != NULL && - sa_equal(addr, ifa->ifa_dstaddr)) + sa_equal(addr, ifa->ifa_dstaddr)) { + IF_ADDR_UNLOCK(ifp); goto done; + } } + IF_ADDR_UNLOCK(ifp); } ifa = NULL; done: @@ -1355,6 +1371,7 @@ ifa_ifwithnet(struct sockaddr *addr) */ IFNET_RLOCK(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { char *cp, *cp2, *cp3; @@ -1370,16 +1387,20 @@ next: continue; * netmask for the remote end. */ if (ifa->ifa_dstaddr != NULL && - sa_equal(addr, ifa->ifa_dstaddr)) + sa_equal(addr, ifa->ifa_dstaddr)) { + IF_ADDR_UNLOCK(ifp); goto done; + } } else { /* * if we have a special address handler, * then use it instead of the generic one. */ if (ifa->ifa_claim_addr) { - if ((*ifa->ifa_claim_addr)(ifa, addr)) + if ((*ifa->ifa_claim_addr)(ifa, addr)) { + IF_ADDR_UNLOCK(ifp); goto done; + } continue; } @@ -1413,6 +1434,7 @@ next: continue; ifa_maybe = ifa; } } + IF_ADDR_UNLOCK(ifp); } ifa = ifa_maybe; done: @@ -1435,6 +1457,7 @@ ifaof_ifpforaddr(struct sockaddr *addr, if (af >= AF_MAX) return (0); + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != af) continue; @@ -1464,6 +1487,7 @@ ifaof_ifpforaddr(struct sockaddr *addr, } ifa = ifa_maybe; done: + IF_ADDR_UNLOCK(ifp); return (ifa); } @@ -2326,6 +2350,7 @@ again: } addrs = 0; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct sockaddr *sa = ifa->ifa_addr; @@ -2357,6 +2382,7 @@ again: if (!sbuf_overflowed(sb)) valid_len = sbuf_len(sb); } + IF_ADDR_UNLOCK(ifp); if (addrs == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); sbuf_bcat(sb, &ifr, sizeof(ifr));