Module Name: src Committed By: martin Date: Thu Nov 30 15:57:37 UTC 2017
Modified Files: src/sys/compat/common [netbsd-8]: uipc_syscalls_40.c src/sys/compat/linux/common [netbsd-8]: linux_socket.c src/sys/compat/linux32/common [netbsd-8]: linux32_socket.c src/sys/net [netbsd-8]: if.c if_spppsubr.c src/sys/netinet [netbsd-8]: ip_carp.c src/sys/netinet6 [netbsd-8]: in6.c src/sys/netipsec [netbsd-8]: key.c Log Message: Pull up following revision(s) (requested by ozaki-r in ticket #407): sys/compat/linux32/common/linux32_socket.c: revision 1.28 sys/net/if.c: revision 1.400 sys/netipsec/key.c: revision 1.243 sys/compat/linux/common/linux_socket.c: revision 1.139 sys/netinet/ip_carp.c: revision 1.93 sys/netinet6/in6.c: revision 1.252 sys/netinet6/in6.c: revision 1.253 sys/netinet6/in6.c: revision 1.254 sys/net/if_spppsubr.c: revision 1.173 sys/net/if_spppsubr.c: revision 1.174 sys/compat/common/uipc_syscalls_40.c: revision 1.14 Protect IFADDR_READER_FOREACH and obtained ifa with psz/psref Fix usage of FOREACH macro key_sad.lock is held there so SAVLIST_WRITER_FOREACH is enough. Protect IFADDR_READER_FOREACH and obtained ifa with psz/psref Protect IFADDR_READER_FOREACH and obtained ifa with psz/psref (more) Fix and make consistent of usages of psz/psref in ifconf variants Remove unnecessary goto because there is no cleanup code to share (NFC) Tweak a condition; we don't need to care ifacount to be negative Fix a race condition of in6_ifinit in6_ifinit checks the number of IPv6 addresses on a given interface and if it's zero (i.e., an IPv6 address being assigned to the interface is the first one), call if_addr_init. However, the actual assignment of the address (ifa_insert) is out of in6_ifinit. The check and the assignment must be done atomically. Fix it by holding in6_ifaddr_lock during in6_ifinit and ifa_insert. And also add missing pserialize to IFADDR_READER_FOREACH. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.13.6.1 src/sys/compat/common/uipc_syscalls_40.c cvs rdiff -u -r1.138 -r1.138.6.1 src/sys/compat/linux/common/linux_socket.c cvs rdiff -u -r1.27 -r1.27.6.1 src/sys/compat/linux32/common/linux32_socket.c cvs rdiff -u -r1.394.2.1 -r1.394.2.2 src/sys/net/if.c cvs rdiff -u -r1.169.6.1 -r1.169.6.2 src/sys/net/if_spppsubr.c cvs rdiff -u -r1.90 -r1.90.2.1 src/sys/netinet/ip_carp.c cvs rdiff -u -r1.245.2.2 -r1.245.2.3 src/sys/netinet6/in6.c cvs rdiff -u -r1.163.2.3 -r1.163.2.4 src/sys/netipsec/key.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/common/uipc_syscalls_40.c diff -u src/sys/compat/common/uipc_syscalls_40.c:1.13 src/sys/compat/common/uipc_syscalls_40.c:1.13.6.1 --- src/sys/compat/common/uipc_syscalls_40.c:1.13 Tue Mar 14 09:03:08 2017 +++ src/sys/compat/common/uipc_syscalls_40.c Thu Nov 30 15:57:37 2017 @@ -1,9 +1,9 @@ -/* $NetBSD: uipc_syscalls_40.c,v 1.13 2017/03/14 09:03:08 ozaki-r Exp $ */ +/* $NetBSD: uipc_syscalls_40.c,v 1.13.6.1 2017/11/30 15:57:37 martin Exp $ */ /* written by Pavel Cahyna, 2006. Public domain. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.13 2017/03/14 09:03:08 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.13.6.1 2017/11/30 15:57:37 martin Exp $"); /* * System call interface to the socket abstraction. @@ -53,6 +53,7 @@ compat_ifconf(u_long cmd, void *data) struct ifaddr *ifa; if_acquire(ifp, &psref); + pserialize_read_exit(s); (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); @@ -69,9 +70,10 @@ compat_ifconf(u_long cmd, void *data) ifrp++; } space -= sizeof(ifr); - continue; + goto next; } + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { struct sockaddr *sa = ifa->ifa_addr; struct psref psref_ifa; @@ -85,11 +87,8 @@ compat_ifconf(u_long cmd, void *data) /* * If it does not fit, we don't bother with it */ - if (sa->sa_len > sizeof(*osa)) { - s = pserialize_read_enter(); - ifa_release(ifa, &psref_ifa); - continue; - } + if (sa->sa_len > sizeof(*osa)) + goto next_ifa; memcpy(&ifr.ifr_addr, sa, sa->sa_len); osa->sa_family = sa->sa_family; if (space >= sz) { @@ -119,13 +118,20 @@ compat_ifconf(u_long cmd, void *data) (char *)&ifrp->ifr_addr); } } - s = pserialize_read_enter(); - ifa_release(ifa, &psref_ifa); - if (error != 0) + if (error != 0) { + ifa_release(ifa, &psref_ifa); goto release_exit; + } space -= sz; + + next_ifa: + s = pserialize_read_enter(); + ifa_release(ifa, &psref_ifa); } + pserialize_read_exit(s); + next: + s = pserialize_read_enter(); if_release(ifp, &psref); } pserialize_read_exit(s); @@ -138,7 +144,6 @@ compat_ifconf(u_long cmd, void *data) return (0); release_exit: - pserialize_read_exit(s); if_release(ifp, &psref); curlwp_bindx(bound); return error; Index: src/sys/compat/linux/common/linux_socket.c diff -u src/sys/compat/linux/common/linux_socket.c:1.138 src/sys/compat/linux/common/linux_socket.c:1.138.6.1 --- src/sys/compat/linux/common/linux_socket.c:1.138 Tue Mar 14 09:03:08 2017 +++ src/sys/compat/linux/common/linux_socket.c Thu Nov 30 15:57:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socket.c,v 1.138 2017/03/14 09:03:08 ozaki-r Exp $ */ +/* $NetBSD: linux_socket.c,v 1.138.6.1 2017/11/30 15:57:37 martin Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.138 2017/03/14 09:03:08 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.138.6.1 2017/11/30 15:57:37 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -1144,6 +1144,7 @@ linux_getifconf(struct lwp *l, register_ IFNET_READER_FOREACH(ifp) { struct ifaddr *ifa; if_acquire(ifp, &psref); + pserialize_read_exit(s); (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); @@ -1152,6 +1153,7 @@ linux_getifconf(struct lwp *l, register_ goto release_exit; } + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { struct psref psref_ifa; ifa_acquire(ifa, &psref_ifa); @@ -1167,7 +1169,6 @@ linux_getifconf(struct lwp *l, register_ if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) { - s = pserialize_read_enter(); ifa_release(ifa, &psref_ifa); goto release_exit; } @@ -1179,6 +1180,7 @@ linux_getifconf(struct lwp *l, register_ ifa_release(ifa, &psref_ifa); } + s = pserialize_read_enter(); if_release(ifp, &psref); } pserialize_read_exit(s); @@ -1192,7 +1194,6 @@ linux_getifconf(struct lwp *l, register_ return copyout(&ifc, data, sizeof(ifc)); release_exit: - pserialize_read_exit(s); if_release(ifp, &psref); curlwp_bindx(bound); return error; Index: src/sys/compat/linux32/common/linux32_socket.c diff -u src/sys/compat/linux32/common/linux32_socket.c:1.27 src/sys/compat/linux32/common/linux32_socket.c:1.27.6.1 --- src/sys/compat/linux32/common/linux32_socket.c:1.27 Tue Mar 14 09:03:08 2017 +++ src/sys/compat/linux32/common/linux32_socket.c Thu Nov 30 15:57:36 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_socket.c,v 1.27 2017/03/14 09:03:08 ozaki-r Exp $ */ +/* $NetBSD: linux32_socket.c,v 1.27.6.1 2017/11/30 15:57:36 martin Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.27 2017/03/14 09:03:08 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.27.6.1 2017/11/30 15:57:36 martin Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -442,6 +442,7 @@ linux32_getifconf(struct lwp *l, registe IFNET_READER_FOREACH(ifp) { struct ifaddr *ifa; if_acquire(ifp, &psref); + pserialize_read_exit(s); (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); @@ -450,6 +451,7 @@ linux32_getifconf(struct lwp *l, registe goto release_exit; } + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { struct psref psref_ifa; ifa_acquire(ifa, &psref_ifa); @@ -465,7 +467,6 @@ linux32_getifconf(struct lwp *l, registe if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) { - s = pserialize_read_enter(); ifa_release(ifa, &psref_ifa); goto release_exit; } @@ -477,6 +478,7 @@ linux32_getifconf(struct lwp *l, registe ifa_release(ifa, &psref_ifa); } + s = pserialize_read_enter(); if_release(ifp, &psref); } pserialize_read_exit(s); @@ -490,7 +492,6 @@ linux32_getifconf(struct lwp *l, registe return copyout(&ifc, data, sizeof(ifc)); release_exit: - pserialize_read_exit(s); if_release(ifp, &psref); curlwp_bindx(bound); return error; Index: src/sys/net/if.c diff -u src/sys/net/if.c:1.394.2.1 src/sys/net/if.c:1.394.2.2 --- src/sys/net/if.c:1.394.2.1 Sat Jul 1 08:56:06 2017 +++ src/sys/net/if.c Thu Nov 30 15:57:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if.c,v 1.394.2.1 2017/07/01 08:56:06 snj Exp $ */ +/* $NetBSD: if.c,v 1.394.2.2 2017/11/30 15:57:37 martin Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.394.2.1 2017/07/01 08:56:06 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.394.2.2 2017/11/30 15:57:37 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -3138,7 +3138,7 @@ ifconf(u_long cmd, void *data) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); if (!docopy) { space += sz; - continue; + goto next; } if (space >= sz) { error = copyout(&ifr, ifrp, sz); @@ -3149,6 +3149,7 @@ ifconf(u_long cmd, void *data) } } + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { struct sockaddr *sa = ifa->ifa_addr; /* all sockaddrs must fit in sockaddr_storage */ @@ -3159,14 +3160,19 @@ ifconf(u_long cmd, void *data) continue; } memcpy(&ifr.ifr_space, sa, sa->sa_len); + pserialize_read_exit(s); + if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) goto release_exit; ifrp++; space -= sz; } + s = pserialize_read_enter(); } + pserialize_read_exit(s); + next: s = pserialize_read_enter(); psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } Index: src/sys/net/if_spppsubr.c diff -u src/sys/net/if_spppsubr.c:1.169.6.1 src/sys/net/if_spppsubr.c:1.169.6.2 --- src/sys/net/if_spppsubr.c:1.169.6.1 Thu Nov 2 20:28:24 2017 +++ src/sys/net/if_spppsubr.c Thu Nov 30 15:57:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_spppsubr.c,v 1.169.6.1 2017/11/02 20:28:24 snj Exp $ */ +/* $NetBSD: if_spppsubr.c,v 1.169.6.2 2017/11/30 15:57:37 martin Exp $ */ /* * Synchronous PPP/Cisco link level subroutines. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.169.6.1 2017/11/02 20:28:24 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.169.6.2 2017/11/30 15:57:37 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -5219,6 +5219,8 @@ sppp_get_ip_addrs(struct sppp *sp, uint3 struct ifaddr *ifa; struct sockaddr_in *si, *sm; uint32_t ssrc, ddst; + int s; + struct psref psref; sm = NULL; ssrc = ddst = 0; @@ -5227,14 +5229,18 @@ sppp_get_ip_addrs(struct sppp *sp, uint3 * aliases don't make any sense on a p2p link anyway. */ si = 0; + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family == AF_INET) { si = (struct sockaddr_in *)ifa->ifa_addr; sm = (struct sockaddr_in *)ifa->ifa_netmask; - if (si) + if (si) { + ifa_acquire(ifa, &psref); break; + } } } + pserialize_read_exit(s); if (ifa) { if (si && si->sin_addr.s_addr) { ssrc = si->sin_addr.s_addr; @@ -5245,6 +5251,7 @@ sppp_get_ip_addrs(struct sppp *sp, uint3 si = (struct sockaddr_in *)ifa->ifa_dstaddr; if (si && si->sin_addr.s_addr) ddst = si->sin_addr.s_addr; + ifa_release(ifa, &psref); } if (dst) *dst = ntohl(ddst); @@ -5457,6 +5464,8 @@ sppp_get_ip6_addrs(struct sppp *sp, stru struct ifaddr *ifa; struct sockaddr_in6 *si, *sm; struct in6_addr ssrc, ddst; + int s; + struct psref psref; sm = NULL; memset(&ssrc, 0, sizeof(ssrc)); @@ -5466,13 +5475,19 @@ sppp_get_ip6_addrs(struct sppp *sp, stru * aliases don't make any sense on a p2p link anyway. */ si = 0; - IFADDR_READER_FOREACH(ifa, ifp) + s = pserialize_read_enter(); + IFADDR_READER_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family == AF_INET6) { si = (struct sockaddr_in6 *)ifa->ifa_addr; sm = (struct sockaddr_in6 *)ifa->ifa_netmask; - if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) + if (si && IN6_IS_ADDR_LINKLOCAL(&si->sin6_addr)) { + ifa_acquire(ifa, &psref); break; + } } + } + pserialize_read_exit(s); + if (ifa) { if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) { memcpy(&ssrc, &si->sin6_addr, sizeof(ssrc)); @@ -5485,6 +5500,7 @@ sppp_get_ip6_addrs(struct sppp *sp, stru si = (struct sockaddr_in6 *)ifa->ifa_dstaddr; if (si && !IN6_IS_ADDR_UNSPECIFIED(&si->sin6_addr)) memcpy(&ddst, &si->sin6_addr, sizeof(ddst)); + ifa_release(ifa, &psref); } if (dst) @@ -5512,6 +5528,8 @@ sppp_set_ip6_addr(struct sppp *sp, const STDDCL; struct ifaddr *ifa; struct sockaddr_in6 *sin6; + int s; + struct psref psref; /* * Pick the first link-local AF_INET6 address from the list, @@ -5519,15 +5537,19 @@ sppp_set_ip6_addr(struct sppp *sp, const */ sin6 = NULL; + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; - if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + ifa_acquire(ifa, &psref); break; + } } } + pserialize_read_exit(s); if (ifa && sin6) { @@ -5544,6 +5566,7 @@ sppp_set_ip6_addr(struct sppp *sp, const if (!error) { pfil_run_addrhooks(if_pfil, SIOCAIFADDR_IN6, ifa); } + ifa_release(ifa, &psref); } } #endif Index: src/sys/netinet/ip_carp.c diff -u src/sys/netinet/ip_carp.c:1.90 src/sys/netinet/ip_carp.c:1.90.2.1 --- src/sys/netinet/ip_carp.c:1.90 Fri May 19 08:53:51 2017 +++ src/sys/netinet/ip_carp.c Thu Nov 30 15:57:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_carp.c,v 1.90 2017/05/19 08:53:51 ozaki-r Exp $ */ +/* $NetBSD: ip_carp.c,v 1.90.2.1 2017/11/30 15:57:37 martin Exp $ */ /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ /* @@ -33,7 +33,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.90 2017/05/19 08:53:51 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.90.2.1 2017/11/30 15:57:37 martin Exp $"); /* * TODO: @@ -59,8 +59,9 @@ __KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v #include <sys/syslog.h> #include <sys/acct.h> #include <sys/cprng.h> - #include <sys/cpu.h> +#include <sys/pserialize.h> +#include <sys/psref.h> #include <net/if.h> #include <net/pfil.h> @@ -297,9 +298,11 @@ carp_hmac_prepare(struct carp_softc *sc) #ifdef INET cur.s_addr = 0; do { + int s; found = 0; last = cur; cur.s_addr = 0xffffffff; + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &sc->sc_if) { in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; if (ifa->ifa_addr->sa_family == AF_INET && @@ -309,6 +312,7 @@ carp_hmac_prepare(struct carp_softc *sc) found++; } } + pserialize_read_exit(s); if (found) SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur)); } while (found); @@ -317,9 +321,11 @@ carp_hmac_prepare(struct carp_softc *sc) #ifdef INET6 memset(&cur6, 0x00, sizeof(cur6)); do { + int s; found = 0; last6 = cur6; memset(&cur6, 0xff, sizeof(cur6)); + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &sc->sc_if) { in6 = ifatoia6(ifa)->ia_addr.sin6_addr; if (IN6_IS_ADDR_LINKLOCAL(&in6)) @@ -331,6 +337,7 @@ carp_hmac_prepare(struct carp_softc *sc) found++; } } + pserialize_read_exit(s); if (found) SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6)); } while (found); @@ -375,11 +382,16 @@ static void carp_setroute(struct carp_softc *sc, int cmd) { struct ifaddr *ifa; - int s; + int s, bound; KERNEL_LOCK(1, NULL); - s = splsoftnet(); + bound = curlwp_bind(); + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &sc->sc_if) { + struct psref psref; + ifa_acquire(ifa, &psref); + pserialize_read_exit(s); + switch (ifa->ifa_addr->sa_family) { case AF_INET: { int count = 0; @@ -473,8 +485,11 @@ carp_setroute(struct carp_softc *sc, int default: break; } + s = pserialize_read_enter(); + ifa_release(ifa, &psref); } - splx(s); + pserialize_read_exit(s); + curlwp_bindx(bound); KERNEL_UNLOCK_ONE(NULL); } @@ -1232,18 +1247,27 @@ static void carp_send_arp(struct carp_softc *sc) { struct ifaddr *ifa; - int s; + int s, bound; KERNEL_LOCK(1, NULL); - s = splsoftnet(); + bound = curlwp_bind(); + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &sc->sc_if) { + struct psref psref; if (ifa->ifa_addr->sa_family != AF_INET) continue; + ifa_acquire(ifa, &psref); + pserialize_read_exit(s); + arpannounce(sc->sc_carpdev, ifa, CLLADDR(sc->sc_if.if_sadl)); + + s = pserialize_read_enter(); + ifa_release(ifa, &psref); } - splx(s); + pserialize_read_exit(s); + curlwp_bindx(bound); KERNEL_UNLOCK_ONE(NULL); } @@ -1254,21 +1278,29 @@ carp_send_na(struct carp_softc *sc) struct ifaddr *ifa; struct in6_addr *in6; static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; - int s; + int s, bound; KERNEL_LOCK(1, NULL); - s = splsoftnet(); - + bound = curlwp_bind(); + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &sc->sc_if) { + struct psref psref; if (ifa->ifa_addr->sa_family != AF_INET6) continue; + ifa_acquire(ifa, &psref); + pserialize_read_exit(s); + in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; nd6_na_output(sc->sc_carpdev, &mcast, in6, ND_NA_FLAG_OVERRIDE, 1, NULL); + + s = pserialize_read_enter(); + ifa_release(ifa, &psref); } - splx(s); + pserialize_read_exit(s); + curlwp_bindx(bound); KERNEL_UNLOCK_ONE(NULL); } #endif /* INET6 */ @@ -1321,12 +1353,14 @@ carp_addrcount(struct carp_if *cif, stru (vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) || (type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) { + int s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &vh->sc_if) { if (ifa->ifa_addr->sa_family == AF_INET && ia->ia_addr.sin_addr.s_addr == ifatoia(ifa)->ia_addr.sin_addr.s_addr) count++; } + pserialize_read_exit(s); } } return (count); @@ -1377,6 +1411,7 @@ carp_iamatch6(void *v, struct in6_addr * struct ifaddr *ifa; TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { + int s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, &vh->sc_if) { if (IN6_ARE_ADDR_EQUAL(taddr, &ifatoia6(ifa)->ia_addr.sin6_addr) && @@ -1384,6 +1419,7 @@ carp_iamatch6(void *v, struct in6_addr * (IFF_UP|IFF_RUNNING)) && vh->sc_state == MASTER) return (ifa); } + pserialize_read_exit(s); } return (NULL); Index: src/sys/netinet6/in6.c diff -u src/sys/netinet6/in6.c:1.245.2.2 src/sys/netinet6/in6.c:1.245.2.3 --- src/sys/netinet6/in6.c:1.245.2.2 Fri Nov 17 20:24:05 2017 +++ src/sys/netinet6/in6.c Thu Nov 30 15:57:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in6.c,v 1.245.2.2 2017/11/17 20:24:05 snj Exp $ */ +/* $NetBSD: in6.c,v 1.245.2.3 2017/11/30 15:57:37 martin Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.2 2017/11/17 20:24:05 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.3 2017/11/30 15:57:37 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1191,7 +1191,7 @@ in6_update_ifa1(struct ifnet *ifp, struc error = EINVAL; if (hostIsNew) free(ia, M_IFADDR); - goto exit; + return error; } if (!IN6_ARE_ADDR_EQUAL(&ia->ia_prefixmask.sin6_addr, @@ -1262,30 +1262,36 @@ in6_update_ifa1(struct ifnet *ifp, struc */ ifaref(&ia->ia_ifa); } + + /* Must execute in6_ifinit and ifa_insert atomically */ + mutex_enter(&in6_ifaddr_lock); + /* reset the interface and routing table appropriately. */ error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew); if (error != 0) { if (hostIsNew) free(ia, M_IFADDR); - goto exit; + mutex_exit(&in6_ifaddr_lock); + return error; } /* * We are done if we have simply modified an existing address. */ - if (!hostIsNew) + if (!hostIsNew) { + mutex_exit(&in6_ifaddr_lock); return error; + } /* * Insert ia to the global list and ifa to the interface's list. * A reference to it is already gained above. */ - mutex_enter(&in6_ifaddr_lock); IN6_ADDRLIST_WRITER_INSERT_TAIL(ia); - mutex_exit(&in6_ifaddr_lock); - ifa_insert(ifp, &ia->ia_ifa); + mutex_exit(&in6_ifaddr_lock); + /* * Beyond this point, we should call in6_purgeaddr upon an error, * not just go to unlink. @@ -1361,7 +1367,6 @@ in6_update_ifa1(struct ifnet *ifp, struc cleanup: in6_purgeaddr(&ia->ia_ifa); - exit: return error; } @@ -1760,28 +1765,30 @@ in6_ifinit(struct ifnet *ifp, struct in6 const struct sockaddr_in6 *sin6, int newhost) { int error = 0, ifacount = 0; - int s = splsoftnet(); + int s; struct ifaddr *ifa; + KASSERT(mutex_owned(&in6_ifaddr_lock)); + /* * Give the interface a chance to initialize * if this is its first address, * and to validate the address if necessary. */ + s = pserialize_read_enter(); IFADDR_READER_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ifacount++; } + pserialize_read_exit(s); ia->ia_addr = *sin6; - if (ifacount <= 0 && + if (ifacount == 0 && (error = if_addr_init(ifp, &ia->ia_ifa, true)) != 0) { - splx(s); return error; } - splx(s); ia->ia_ifa.ifa_metric = ifp->if_metric; Index: src/sys/netipsec/key.c diff -u src/sys/netipsec/key.c:1.163.2.3 src/sys/netipsec/key.c:1.163.2.4 --- src/sys/netipsec/key.c:1.163.2.3 Thu Nov 30 14:57:34 2017 +++ src/sys/netipsec/key.c Thu Nov 30 15:57:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.163.2.3 2017/11/30 14:57:34 martin Exp $ */ +/* $NetBSD: key.c,v 1.163.2.4 2017/11/30 15:57:37 martin Exp $ */ /* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $ */ /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.163.2.3 2017/11/30 14:57:34 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.163.2.4 2017/11/30 15:57:37 martin Exp $"); /* * This code is referred to RFC 2367 @@ -8139,7 +8139,7 @@ key_sa_chgstate(struct secasvar *sav, u_ * Sort the list by lft_c->sadb_lifetime_addtime * in ascending order. */ - SAVLIST_READER_FOREACH(_sav, sav->sah, state) { + SAVLIST_WRITER_FOREACH(_sav, sav->sah, state) { if (_sav->lft_c->sadb_lifetime_addtime > sav->lft_c->sadb_lifetime_addtime) { SAVLIST_WRITER_INSERT_BEFORE(_sav, sav);