Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Ensure to call if_mcast_op with holding IFNET_LOCK



details:   https://anonhg.NetBSD.org/src/rev/fa2f1b06c2ec
branches:  trunk
changeset: 828460:fa2f1b06c2ec
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Fri Dec 15 04:03:46 2017 +0000

description:
Ensure to call if_mcast_op with holding IFNET_LOCK

Note that CARP doesn't deal with IFNET_LOCK yet.

diffstat:

 sys/net/if.c              |  25 ++++++++++++++--
 sys/net/if.h              |   3 +-
 sys/net/if_vlan.c         |  10 +++++-
 sys/netinet/in.c          |   7 +++-
 sys/netinet/in_pcb.c      |   7 +++-
 sys/netinet/ip_output.c   |  22 +++++++++++---
 sys/netinet6/in6.c        |  11 +++++--
 sys/netinet6/in6_pcb.c    |  11 ++++++-
 sys/netinet6/ip6_output.c |  21 ++++++++++++--
 sys/netinet6/nd6.c        |  69 ++++++++++++++++++++++++++++++++++++++++------
 sys/netinet6/nd6_rtr.c    |   6 ++-
 11 files changed, 158 insertions(+), 34 deletions(-)

diffs (truncated from 553 to 300 lines):

diff -r deae1207f6dc -r fa2f1b06c2ec sys/net/if.c
--- a/sys/net/if.c      Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/net/if.c      Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
        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 @@
        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 {
diff -r deae1207f6dc -r fa2f1b06c2ec sys/net/if.h
--- a/sys/net/if.h      Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/net/if.h      Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
 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 *);
diff -r deae1207f6dc -r fa2f1b06c2ec sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/net/if_vlan.c Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
        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 @@
 
        /* 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 @@
        }
 
        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);
        }
diff -r deae1207f6dc -r fa2f1b06c2ec sys/netinet/in.c
--- a/sys/netinet/in.c  Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/netinet/in.c  Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
 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);
 }
 
 /*
diff -r deae1207f6dc -r fa2f1b06c2ec sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c      Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/netinet/in_pcb.c      Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
                        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);
diff -r deae1207f6dc -r fa2f1b06c2ec sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c   Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/netinet/ip_output.c   Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
         * 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 @@
         * 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 @@
        /* 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));
        }
 }
diff -r deae1207f6dc -r fa2f1b06c2ec sys/netinet6/in6.c
--- a/sys/netinet6/in6.c        Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/netinet6/in6.c        Fri Dec 15 04:03:46 2017 +0000
@@ -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 @@
        struct in6_multi_mship *imm;
 
        KASSERT(!ifa_held(ifa));
+       KASSERT(IFNET_LOCKED(ifp));
 
        ifa->ifa_flags |= IFA_DESTROYING;
 
@@ -1400,12 +1401,14 @@
        /*
         * 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 @@
 in6_purgeif(struct ifnet *ifp)
 {
 
+       IFNET_LOCK(ifp);
        in6_ifdetach(ifp);
+       IFNET_UNLOCK(ifp);
 }
 
 void
diff -r deae1207f6dc -r fa2f1b06c2ec sys/netinet6/in6_pcb.c
--- a/sys/netinet6/in6_pcb.c    Fri Dec 15 02:24:22 2017 +0000
+++ b/sys/netinet6/in6_pcb.c    Fri Dec 15 04:03:46 2017 +0000
@@ -1,4 +1,4 @@



Home | Main Index | Thread Index | Old Index