Module Name: src
Committed By: ozaki-r
Date: Fri Dec 15 04:03:46 UTC 2017
Modified Files:
src/sys/net: if.c if.h if_vlan.c
src/sys/netinet: in.c in_pcb.c ip_output.c
src/sys/netinet6: in6.c in6_pcb.c ip6_output.c nd6.c nd6_rtr.c
Log Message:
Ensure to call if_mcast_op with holding IFNET_LOCK
Note that CARP doesn't deal with IFNET_LOCK yet.
To generate a diff of this commit:
cvs rdiff -u -r1.414 -r1.415 src/sys/net/if.c
cvs rdiff -u -r1.253 -r1.254 src/sys/net/if.h
cvs rdiff -u -r1.119 -r1.120 src/sys/net/if_vlan.c
cvs rdiff -u -r1.210 -r1.211 src/sys/netinet/in.c
cvs rdiff -u -r1.179 -r1.180 src/sys/netinet/in_pcb.c
cvs rdiff -u -r1.286 -r1.287 src/sys/netinet/ip_output.c
cvs rdiff -u -r1.254 -r1.255 src/sys/netinet6/in6.c
cvs rdiff -u -r1.161 -r1.162 src/sys/netinet6/in6_pcb.c
cvs rdiff -u -r1.195 -r1.196 src/sys/netinet6/ip6_output.c
cvs rdiff -u -r1.239 -r1.240 src/sys/netinet6/nd6.c
cvs rdiff -u -r1.135 -r1.136 src/sys/netinet6/nd6_rtr.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/net/if.c
diff -u src/sys/net/if.c:1.414 src/sys/net/if.c:1.415
--- src/sys/net/if.c:1.414 Thu Dec 14 05:46:54 2017
+++ src/sys/net/if.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.414 2017/12/14 05:46:54 ozaki-r Exp $ */
+/* $NetBSD: if.c,v 1.415 2017/12/15 04:03:46 ozaki-r 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.414 2017/12/14 05:46:54 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.415 2017/12/15 04:03:46 ozaki-r Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -2721,12 +2721,27 @@ if_put(const struct ifnet *ifp, struct p
psref_release(psref, &ifp->if_psref, ifnet_psref_class);
}
+/*
+ * Return ifp having idx. Return NULL if not found. Normally if_byindex
+ * should be used.
+ */
+ifnet_t *
+_if_byindex(u_int idx)
+{
+
+ return (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;
+}
+
+/*
+ * Return ifp having idx. Return NULL if not found or the found ifp is
+ * already deactivated.
+ */
ifnet_t *
if_byindex(u_int idx)
{
ifnet_t *ifp;
- ifp = (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;
+ ifp = _if_byindex(idx);
if (ifp != NULL && if_is_deactivated(ifp))
ifp = NULL;
return ifp;
@@ -3570,6 +3585,10 @@ if_mcast_op(ifnet_t *ifp, const unsigned
int rc;
struct ifreq ifr;
+ /* CARP still doesn't deal with the lock yet */
+#if !defined(NCARP) || (NCARP == 0)
+ KASSERT(IFNET_LOCKED(ifp));
+#endif
if (ifp->if_mcastop != NULL)
rc = (*ifp->if_mcastop)(ifp, cmd, sa);
else {
Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.253 src/sys/net/if.h:1.254
--- src/sys/net/if.h:1.253 Mon Dec 11 03:29:20 2017
+++ src/sys/net/if.h Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.253 2017/12/11 03:29:20 ozaki-r Exp $ */
+/* $NetBSD: if.h,v 1.254 2017/12/15 04:03:46 ozaki-r Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -1026,6 +1026,7 @@ int if_clone_list(int, char *, int *);
struct ifnet *ifunit(const char *);
struct ifnet *if_get(const char *, struct psref *);
ifnet_t *if_byindex(u_int);
+ifnet_t *_if_byindex(u_int);
ifnet_t *if_get_byindex(u_int, struct psref *);
ifnet_t *if_get_bylla(const void *, unsigned char, struct psref *);
void if_put(const struct ifnet *, struct psref *);
Index: src/sys/net/if_vlan.c
diff -u src/sys/net/if_vlan.c:1.119 src/sys/net/if_vlan.c:1.120
--- src/sys/net/if_vlan.c:1.119 Mon Dec 11 03:29:20 2017
+++ src/sys/net/if_vlan.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vlan.c,v 1.119 2017/12/11 03:29:20 ozaki-r Exp $ */
+/* $NetBSD: if_vlan.c,v 1.120 2017/12/15 04:03:46 ozaki-r Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.119 2017/12/11 03:29:20 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.120 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1160,7 +1160,9 @@ vlan_ether_addmulti(struct ifvlan *ifv,
mib = ifv->ifv_mib;
KERNEL_LOCK_UNLESS_IFP_MPSAFE(mib->ifvm_p);
+ IFNET_LOCK(mib->ifvm_p);
error = if_mcast_op(mib->ifvm_p, SIOCADDMULTI, sa);
+ IFNET_UNLOCK(mib->ifvm_p);
KERNEL_UNLOCK_UNLESS_IFP_MPSAFE(mib->ifvm_p);
if (error != 0)
@@ -1201,7 +1203,9 @@ vlan_ether_delmulti(struct ifvlan *ifv,
/* We no longer use this multicast address. Tell parent so. */
mib = ifv->ifv_mib;
+ IFNET_LOCK(mib->ifvm_p);
error = if_mcast_op(mib->ifvm_p, SIOCDELMULTI, sa);
+ IFNET_UNLOCK(mib->ifvm_p);
if (error == 0) {
/* And forget about this address. */
@@ -1236,8 +1240,10 @@ vlan_ether_purgemulti(struct ifvlan *ifv
}
while ((mc = LIST_FIRST(&ifv->ifv_mc_listhead)) != NULL) {
+ IFNET_LOCK(mib->ifvm_p);
(void)if_mcast_op(mib->ifvm_p, SIOCDELMULTI,
(const struct sockaddr *)&mc->mc_addr);
+ IFNET_UNLOCK(mib->ifvm_p);
LIST_REMOVE(mc, mc_entries);
free(mc, M_DEVBUF);
}
Index: src/sys/netinet/in.c
diff -u src/sys/netinet/in.c:1.210 src/sys/netinet/in.c:1.211
--- src/sys/netinet/in.c:1.210 Fri Nov 17 07:37:12 2017
+++ src/sys/netinet/in.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: in.c,v 1.210 2017/11/17 07:37:12 ozaki-r Exp $ */
+/* $NetBSD: in.c,v 1.211 2017/12/15 04:03:46 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.210 2017/11/17 07:37:12 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.211 2017/12/15 04:03:46 ozaki-r Exp $");
#include "arp.h"
@@ -912,11 +912,14 @@ in_addrhash_remove(struct in_ifaddr *ia)
void
in_purgeif(struct ifnet *ifp) /* MUST be called at splsoftnet() */
{
+
+ IFNET_LOCK(ifp);
if_purgeaddrs(ifp, AF_INET, in_purgeaddr);
igmp_purgeif(ifp); /* manipulates pools */
#ifdef MROUTING
ip_mrouter_detach(ifp);
#endif
+ IFNET_UNLOCK(ifp);
}
/*
Index: src/sys/netinet/in_pcb.c
diff -u src/sys/netinet/in_pcb.c:1.179 src/sys/netinet/in_pcb.c:1.180
--- src/sys/netinet/in_pcb.c:1.179 Thu Aug 10 04:31:58 2017
+++ src/sys/netinet/in_pcb.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: in_pcb.c,v 1.179 2017/08/10 04:31:58 ryo Exp $ */
+/* $NetBSD: in_pcb.c,v 1.180 2017/12/15 04:03:46 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -93,7 +93,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.179 2017/08/10 04:31:58 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.180 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -777,7 +777,10 @@ in_pcbpurgeif0(struct inpcbtable *table,
need_unlock = true;
}
+ /* IFNET_LOCK must be taken after solock */
+ IFNET_LOCK(ifp);
in_purgeifmcast(inp->inp_moptions, ifp);
+ IFNET_UNLOCK(ifp);
if (need_unlock)
inp_unlock(inp);
Index: src/sys/netinet/ip_output.c
diff -u src/sys/netinet/ip_output.c:1.286 src/sys/netinet/ip_output.c:1.287
--- src/sys/netinet/ip_output.c:1.286 Mon Dec 11 05:47:18 2017
+++ src/sys/netinet/ip_output.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_output.c,v 1.286 2017/12/11 05:47:18 ryo Exp $ */
+/* $NetBSD: ip_output.c,v 1.287 2017/12/15 04:03:46 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.286 2017/12/11 05:47:18 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.287 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1771,7 +1771,10 @@ ip_add_membership(struct ip_moptions *im
* Everything looks good; add a new record to the multicast
* address list for the given interface.
*/
- if ((imo->imo_membership[i] = in_addmulti(&ia, ifp)) == NULL) {
+ IFNET_LOCK(ifp);
+ imo->imo_membership[i] = in_addmulti(&ia, ifp);
+ IFNET_UNLOCK(ifp);
+ if (imo->imo_membership[i] == NULL) {
error = ENOBUFS;
goto out;
}
@@ -1830,7 +1833,9 @@ ip_drop_membership(struct ip_moptions *i
* Give up the multicast address record to which the
* membership points.
*/
+ IFNET_LOCK(ifp);
in_delmulti(imo->imo_membership[i]);
+ IFNET_UNLOCK(ifp);
/*
* Remove the gap in the membership array.
@@ -2023,8 +2028,15 @@ ip_freemoptions(struct ip_moptions *imo)
/* The owner of imo (inp) should be protected by solock */
if (imo != NULL) {
- for (i = 0; i < imo->imo_num_memberships; ++i)
- in_delmulti(imo->imo_membership[i]);
+ for (i = 0; i < imo->imo_num_memberships; ++i) {
+ struct in_multi *inm = imo->imo_membership[i];
+ struct ifnet *ifp = inm->inm_ifp;
+ IFNET_LOCK(ifp);
+ in_delmulti(inm);
+ /* ifp should not leave thanks to solock */
+ IFNET_UNLOCK(ifp);
+ }
+
kmem_intr_free(imo, sizeof(*imo));
}
}
Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.254 src/sys/netinet6/in6.c:1.255
--- src/sys/netinet6/in6.c:1.254 Thu Nov 23 07:09:20 2017
+++ src/sys/netinet6/in6.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: in6.c,v 1.254 2017/11/23 07:09:20 ozaki-r Exp $ */
+/* $NetBSD: in6.c,v 1.255 2017/12/15 04:03:46 ozaki-r 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.254 2017/11/23 07:09:20 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.255 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1385,6 +1385,7 @@ in6_purgeaddr(struct ifaddr *ifa)
struct in6_multi_mship *imm;
KASSERT(!ifa_held(ifa));
+ KASSERT(IFNET_LOCKED(ifp));
ifa->ifa_flags |= IFA_DESTROYING;
@@ -1400,12 +1401,14 @@ in6_purgeaddr(struct ifaddr *ifa)
/*
* leave from multicast groups we have joined for the interface
*/
+ again:
mutex_enter(&in6_ifaddr_lock);
while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
LIST_REMOVE(imm, i6mm_chain);
mutex_exit(&in6_ifaddr_lock);
+ KASSERT(imm->i6mm_maddr->in6m_ifp == ifp);
in6_leavegroup(imm);
- mutex_enter(&in6_ifaddr_lock);
+ goto again;
}
mutex_exit(&in6_ifaddr_lock);
@@ -1456,7 +1459,9 @@ void
in6_purgeif(struct ifnet *ifp)
{
+ IFNET_LOCK(ifp);
in6_ifdetach(ifp);
+ IFNET_UNLOCK(ifp);
}
void
Index: src/sys/netinet6/in6_pcb.c
diff -u src/sys/netinet6/in6_pcb.c:1.161 src/sys/netinet6/in6_pcb.c:1.162
--- src/sys/netinet6/in6_pcb.c:1.161 Tue Apr 25 05:44:11 2017
+++ src/sys/netinet6/in6_pcb.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: in6_pcb.c,v 1.161 2017/04/25 05:44:11 ozaki-r Exp $ */
+/* $NetBSD: in6_pcb.c,v 1.162 2017/12/15 04:03:46 ozaki-r Exp $ */
/* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.161 2017/04/25 05:44:11 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.162 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -875,11 +875,18 @@ in6_pcbpurgeif0(struct inpcbtable *table
i6mm_chain, nimm) {
if (imm->i6mm_maddr->in6m_ifp == ifp) {
LIST_REMOVE(imm, i6mm_chain);
+ IFNET_LOCK(ifp);
in6_leavegroup(imm);
+ IFNET_UNLOCK(ifp);
}
}
}
+
+ /* IFNET_LOCK must be taken after solock */
+ IFNET_LOCK(ifp);
in_purgeifmcast(in6p->in6p_v4moptions, ifp);
+ IFNET_UNLOCK(ifp);
+
if (need_unlock)
in6p_unlock(in6p);
}
Index: src/sys/netinet6/ip6_output.c
diff -u src/sys/netinet6/ip6_output.c:1.195 src/sys/netinet6/ip6_output.c:1.196
--- src/sys/netinet6/ip6_output.c:1.195 Sat Nov 25 13:18:02 2017
+++ src/sys/netinet6/ip6_output.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_output.c,v 1.195 2017/11/25 13:18:02 kre Exp $ */
+/* $NetBSD: ip6_output.c,v 1.196 2017/12/15 04:03:46 ozaki-r Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.195 2017/11/25 13:18:02 kre Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.196 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -2606,7 +2606,9 @@ ip6_setmoptions(const struct sockopt *so
* Everything looks good; add a new record to the multicast
* address list for the given interface.
*/
+ IFNET_LOCK(ifp);
imm = in6_joingroup(ifp, &ia, &error, 0);
+ IFNET_UNLOCK(ifp);
if (imm == NULL)
goto put_break;
LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
@@ -2616,7 +2618,8 @@ ip6_setmoptions(const struct sockopt *so
break;
}
- case IPV6_LEAVE_GROUP:
+ case IPV6_LEAVE_GROUP: {
+ struct ifnet *in6m_ifp;
/*
* Drop a multicast group membership.
* Group must be a valid IP6 multicast address.
@@ -2698,8 +2701,13 @@ ip6_setmoptions(const struct sockopt *so
* membership points.
*/
LIST_REMOVE(imm, i6mm_chain);
+ in6m_ifp = imm->i6mm_maddr->in6m_ifp;
+ IFNET_LOCK(in6m_ifp);
in6_leavegroup(imm);
+ /* in6m_ifp should not leave thanks to in6p_lock */
+ IFNET_UNLOCK(in6m_ifp);
break;
+ }
default:
error = EOPNOTSUPP;
@@ -2778,8 +2786,15 @@ ip6_freemoptions(struct ip6_moptions *im
/* The owner of im6o (in6p) should be protected by solock */
LIST_FOREACH_SAFE(imm, &im6o->im6o_memberships, i6mm_chain, nimm) {
+ struct ifnet *ifp;
+
LIST_REMOVE(imm, i6mm_chain);
+
+ ifp = imm->i6mm_maddr->in6m_ifp;
+ IFNET_LOCK(ifp);
in6_leavegroup(imm);
+ /* ifp should not leave thanks to solock */
+ IFNET_UNLOCK(ifp);
}
free(im6o, M_IPMOPTS);
}
Index: src/sys/netinet6/nd6.c
diff -u src/sys/netinet6/nd6.c:1.239 src/sys/netinet6/nd6.c:1.240
--- src/sys/netinet6/nd6.c:1.239 Fri Nov 17 07:37:12 2017
+++ src/sys/netinet6/nd6.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6.c,v 1.239 2017/11/17 07:37:12 ozaki-r Exp $ */
+/* $NetBSD: nd6.c,v 1.240 2017/12/15 04:03:46 ozaki-r Exp $ */
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.239 2017/11/17 07:37:12 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.240 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -614,6 +614,7 @@ nd6_timer_work(struct work *wk, void *ar
/* check address lifetime */
if (IFA6_IS_INVALID(ia6)) {
int regen = 0;
+ struct ifnet *ifp;
/*
* If the expiring address is temporary, try
@@ -627,13 +628,30 @@ nd6_timer_work(struct work *wk, void *ar
*/
if (ip6_use_tempaddr &&
(ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
+ IFNET_LOCK(ia6->ia_ifa.ifa_ifp);
if (regen_tmpaddr(ia6) == 0)
regen = 1;
+ IFNET_UNLOCK(ia6->ia_ifa.ifa_ifp);
}
- ia6_release(ia6, &psref);
- in6_purgeaddr(&ia6->ia_ifa);
+ ifp = ia6->ia_ifa.ifa_ifp;
+ IFNET_LOCK(ifp);
+ /*
+ * Need to take the lock first to prevent if_detach
+ * from running in6_purgeaddr concurrently.
+ */
+ if (!if_is_deactivated(ifp)) {
+ ia6_release(ia6, &psref);
+ in6_purgeaddr(&ia6->ia_ifa);
+ } else {
+ /*
+ * ifp is being destroyed, ia6 will be destroyed
+ * by if_detach.
+ */
+ ia6_release(ia6, &psref);
+ }
ia6 = NULL;
+ IFNET_UNLOCK(ifp);
if (regen)
goto addrloop; /* XXX: see below */
@@ -1883,20 +1901,53 @@ nd6_ioctl(u_long cmd, void *data, struct
_s = pserialize_read_enter();
for (ia = IN6_ADDRLIST_READER_FIRST(); ia;
ia = ia_next) {
+ struct ifnet *ifa_ifp;
+ int bound;
+ struct psref psref;
+
/* ia might be removed. keep the next ptr. */
ia_next = IN6_ADDRLIST_READER_NEXT(ia);
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
continue;
- if (ia->ia6_ndpr == pfx) {
- pserialize_read_exit(_s);
- ND6_UNLOCK();
- /* XXX NOMPSAFE? */
- /* in6_purgeaddr may destroy pfx. */
+ if (ia->ia6_ndpr != pfx)
+ continue;
+
+ bound = curlwp_bind();
+ ia6_acquire(ia, &psref);
+ pserialize_read_exit(_s);
+ ND6_UNLOCK();
+
+ ifa_ifp = ia->ia_ifa.ifa_ifp;
+ if (ifa_ifp == ifp) {
+ /* Already have IFNET_LOCK(ifp) */
+ KASSERT(!if_is_deactivated(ifp));
+ ia6_release(ia, &psref);
in6_purgeaddr(&ia->ia_ifa);
+ curlwp_bindx(bound);
goto restart;
}
+ IFNET_LOCK(ifa_ifp);
+ /*
+ * Need to take the lock first to prevent
+ * if_detach from running in6_purgeaddr
+ * concurrently.
+ */
+ if (!if_is_deactivated(ifa_ifp)) {
+ ia6_release(ia, &psref);
+ in6_purgeaddr(&ia->ia_ifa);
+ } else {
+ /*
+ * ifp is being destroyed, ia will be
+ * destroyed by if_detach.
+ */
+ ia6_release(ia, &psref);
+ /* XXX may cause busy loop */
+ }
+ IFNET_UNLOCK(ifa_ifp);
+ curlwp_bindx(bound);
+ goto restart;
}
pserialize_read_exit(_s);
Index: src/sys/netinet6/nd6_rtr.c
diff -u src/sys/netinet6/nd6_rtr.c:1.135 src/sys/netinet6/nd6_rtr.c:1.136
--- src/sys/netinet6/nd6_rtr.c:1.135 Tue Mar 14 04:21:38 2017
+++ src/sys/netinet6/nd6_rtr.c Fri Dec 15 04:03:46 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: nd6_rtr.c,v 1.135 2017/03/14 04:21:38 ozaki-r Exp $ */
+/* $NetBSD: nd6_rtr.c,v 1.136 2017/12/15 04:03:46 ozaki-r Exp $ */
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.135 2017/03/14 04:21:38 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.136 2017/12/15 04:03:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -319,6 +319,7 @@ nd6_ra_input(struct mbuf *m, int off, in
IN6_PRINT(ip6buf, &ip6->ip6_src),
if_name(ifp), ndi->chlim, nd_ra->nd_ra_curhoplimit);
}
+ IFNET_LOCK(ifp);
ND6_WLOCK();
dr = defrtrlist_update(&drtr);
}
@@ -378,6 +379,7 @@ nd6_ra_input(struct mbuf *m, int off, in
}
}
ND6_UNLOCK();
+ IFNET_UNLOCK(ifp);
/*
* MTU