Author: pluknet
Date: Mon Aug 22 23:39:40 2011
New Revision: 225096
URL: http://svn.freebsd.org/changeset/base/225096

Log:
  Fix if_addr_mtx recursion in mld6.
  
  mld_set_version() is called only from mld_v1_input_query() and
  mld_v2_input_query() both holding the if_addr_mtx lock, and then calling
  into mld_v2_cancel_link_timers() acquires it the second time, which results
  in mtx recursion. To avoid that, delay if_addr_mtx acquisition until after
  mld_set_version() is called; while here, further reduce locking scope
  to protect only the needed pieces: if_multiaddrs, in6m_lookup_locked().
  
  PR:           kern/158426
  Reported by:  Thomas <tps vr-web.de>,
                Tom Vijlbrief <tom.vijlbrief xs4all.nl>
  Tested by:    Tom Vijlbrief
  Reviewed by:  bz
  Approved by:  re (kib)

Modified:
  head/sys/netinet6/mld6.c

Modified: head/sys/netinet6/mld6.c
==============================================================================
--- head/sys/netinet6/mld6.c    Mon Aug 22 23:27:23 2011        (r225095)
+++ head/sys/netinet6/mld6.c    Mon Aug 22 23:39:40 2011        (r225096)
@@ -680,7 +680,6 @@ mld_v1_input_query(struct ifnet *ifp, co
 
        IN6_MULTI_LOCK();
        MLD_LOCK();
-       IF_ADDR_LOCK(ifp);
 
        /*
         * Switch to MLDv1 host compatibility mode.
@@ -693,6 +692,7 @@ mld_v1_input_query(struct ifnet *ifp, co
        if (timer == 0)
                timer = 1;
 
+       IF_ADDR_LOCK(ifp);
        if (is_general_query) {
                /*
                 * For each reporting group joined on this
@@ -888,7 +888,6 @@ mld_v2_input_query(struct ifnet *ifp, co
 
        IN6_MULTI_LOCK();
        MLD_LOCK();
-       IF_ADDR_LOCK(ifp);
 
        mli = MLD_IFINFO(ifp);
        KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
@@ -936,14 +935,18 @@ mld_v2_input_query(struct ifnet *ifp, co
                 * Queries for groups we are not a member of on this
                 * link are simply ignored.
                 */
+               IF_ADDR_LOCK(ifp);
                inm = in6m_lookup_locked(ifp, &mld->mld_addr);
-               if (inm == NULL)
+               if (inm == NULL) {
+                       IF_ADDR_UNLOCK(ifp);
                        goto out_locked;
+               }
                if (nsrc > 0) {
                        if (!ratecheck(&inm->in6m_lastgsrtv,
                            &V_mld_gsrdelay)) {
                                CTR1(KTR_MLD, "%s: GS query throttled.",
                                    __func__);
+                               IF_ADDR_UNLOCK(ifp);
                                goto out_locked;
                        }
                }
@@ -961,10 +964,10 @@ mld_v2_input_query(struct ifnet *ifp, co
 
                /* XXX Clear embedded scope ID as userland won't expect it. */
                in6_clearscope(&mld->mld_addr);
+               IF_ADDR_UNLOCK(ifp);
        }
 
 out_locked:
-       IF_ADDR_UNLOCK(ifp);
        MLD_UNLOCK();
        IN6_MULTI_UNLOCK();
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to