summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorpluknet <pluknet@FreeBSD.org>2011-08-22 23:39:40 +0000
committerpluknet <pluknet@FreeBSD.org>2011-08-22 23:39:40 +0000
commit081544b729b53a21469898ef85a4f838148d1e71 (patch)
treed5427dd27753b8ee18fb0c63679269db8626ac90 /sys/netinet6
parent4145a19caa34892593779c20f0b391fb661462ed (diff)
downloadFreeBSD-src-081544b729b53a21469898ef85a4f838148d1e71.zip
FreeBSD-src-081544b729b53a21469898ef85a4f838148d1e71.tar.gz
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)
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/mld6.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 21d9eab..a56f83d 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -680,7 +680,6 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
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, const struct ip6_hdr *ip6,
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, const struct ip6_hdr *ip6,
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, const struct ip6_hdr *ip6,
* 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, const struct ip6_hdr *ip6,
/* 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();
OpenPOWER on IntegriCloud