aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet6/in6_mcast.c
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2019-05-16 13:04:26 +0000
committerMark Johnston <markj@FreeBSD.org>2019-05-16 13:04:26 +0000
commitf00876fb601ad1bae791830cfa7a7079a4fc0d79 (patch)
tree35b78a6844943532251c5339b1755bdcf362b95f /sys/netinet6/in6_mcast.c
parent0ddfdc60f80c93c8a2df986e246c92cfdd011bf0 (diff)
downloadsrc-f00876fb601ad1bae791830cfa7a7079a4fc0d79.tar.gz
src-f00876fb601ad1bae791830cfa7a7079a4fc0d79.zip
Notes
Diffstat (limited to 'sys/netinet6/in6_mcast.c')
-rw-r--r--sys/netinet6/in6_mcast.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
index c0e6d2dcb650..5557a7c76564 100644
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -2052,7 +2052,6 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
(void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
- IN6_MULTI_LOCK();
imo = in6p_findmoptions(inp);
idx = im6o_match_group(imo, ifp, &gsa->sa);
if (idx == -1) {
@@ -2172,6 +2171,10 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at MLD layer.
*/
+ in_pcbref(inp);
+ INP_WUNLOCK(inp);
+ IN6_MULTI_LOCK();
+
if (is_new) {
error = in6_joingroup_locked(ifp, &gsa->sin6.sin6_addr, imf,
&inm, 0);
@@ -2201,6 +2204,10 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
IN6_MULTI_LIST_UNLOCK();
}
+ IN6_MULTI_UNLOCK();
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp))
+ return (ENXIO);
if (error) {
im6f_rollback(imf);
if (is_new)
@@ -2225,7 +2232,6 @@ out_im6o_free:
out_in6p_locked:
INP_WUNLOCK(inp);
- IN6_MULTI_UNLOCK();
in6m_release_list_deferred(&inmh);
return (error);
}
@@ -2375,7 +2381,6 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Find the membership in the membership array.
*/
- IN6_MULTI_LOCK();
imo = in6p_findmoptions(inp);
idx = im6o_match_group(imo, ifp, &gsa->sa);
if (idx == -1) {
@@ -2424,6 +2429,10 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at MLD layer.
*/
+ in_pcbref(inp);
+ INP_WUNLOCK(inp);
+ IN6_MULTI_LOCK();
+
if (is_final) {
/*
* Give up the multicast address record to which
@@ -2447,6 +2456,11 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
IN6_MULTI_LIST_UNLOCK();
}
+ IN6_MULTI_UNLOCK();
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp))
+ return (ENXIO);
+
if (error)
im6f_rollback(imf);
else
@@ -2469,7 +2483,6 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
out_in6p_locked:
INP_WUNLOCK(inp);
- IN6_MULTI_UNLOCK();
return (error);
}
@@ -2515,6 +2528,8 @@ in6p_set_multicast_if(struct inpcb *inp, struct sockopt *sopt)
/*
* Atomically set source filters on a socket for an IPv6 multicast group.
+ *
+ * SMPng: NOTE: Potentially calls malloc(M_WAITOK) with Giant held.
*/
static int
in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt)