diff options
author | Mark Johnston <markj@FreeBSD.org> | 2019-05-16 13:04:26 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2019-05-16 13:04:26 +0000 |
commit | f00876fb601ad1bae791830cfa7a7079a4fc0d79 (patch) | |
tree | 35b78a6844943532251c5339b1755bdcf362b95f /sys/netinet6/in6_mcast.c | |
parent | 0ddfdc60f80c93c8a2df986e246c92cfdd011bf0 (diff) | |
download | src-f00876fb601ad1bae791830cfa7a7079a4fc0d79.tar.gz src-f00876fb601ad1bae791830cfa7a7079a4fc0d79.zip |
Notes
Diffstat (limited to 'sys/netinet6/in6_mcast.c')
-rw-r--r-- | sys/netinet6/in6_mcast.c | 23 |
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) |