From 9abf4945e622652cd155eef261aa0c1fe8916d30 Mon Sep 17 00:00:00 2001 From: markj Date: Thu, 11 Apr 2019 08:00:59 +0000 Subject: [PATCH] Reinitialize multicast source filter structures after invalidation. When leaving a multicast group, a hole may be created in the inpcb's source filter and group membership arrays. To remove the hole, the succeeding array elements are copied over by one entry. The multicast code expects that a newly allocated array element is initialized, but the code which shifts a tail of the array was leaving stale data in the final entry. Fix this by explicitly reinitializing the last entry following such a copy. Reported by: syzbot+f8c3c564ee21d650475e@syzkaller.appspotmail.com Reviewed by: ae MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D19872 --- sys/netinet/in_mcast.c | 8 ++++++-- sys/netinet6/in6_mcast.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index ab48fed348e60c..9707f45d6ebff9 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -2556,10 +2556,14 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt) if (is_final) { /* Remove the gap in the membership and filter array. */ + KASSERT(RB_EMPTY(&imf->imf_sources), + ("%s: imf_sources not empty", __func__)); for (++idx; idx < imo->imo_num_memberships; ++idx) { - imo->imo_membership[idx-1] = imo->imo_membership[idx]; - imo->imo_mfilters[idx-1] = imo->imo_mfilters[idx]; + imo->imo_membership[idx - 1] = imo->imo_membership[idx]; + imo->imo_mfilters[idx - 1] = imo->imo_mfilters[idx]; } + imf_init(&imo->imo_mfilters[idx - 1], MCAST_UNDEFINED, + MCAST_EXCLUDE); imo->imo_num_memberships--; } diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c index 3b60d26c84ee4f..5557a7c7656400 100644 --- a/sys/netinet6/in6_mcast.c +++ b/sys/netinet6/in6_mcast.c @@ -2470,10 +2470,14 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt) if (is_final) { /* Remove the gap in the membership array. */ + KASSERT(RB_EMPTY(&imf->im6f_sources), + ("%s: im6f_sources not empty", __func__)); for (++idx; idx < imo->im6o_num_memberships; ++idx) { - imo->im6o_membership[idx-1] = imo->im6o_membership[idx]; - imo->im6o_mfilters[idx-1] = imo->im6o_mfilters[idx]; + imo->im6o_membership[idx - 1] = imo->im6o_membership[idx]; + imo->im6o_mfilters[idx - 1] = imo->im6o_mfilters[idx]; } + im6f_init(&imo->im6o_mfilters[idx - 1], MCAST_UNDEFINED, + MCAST_EXCLUDE); imo->im6o_num_memberships--; }