Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed876e99 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Greg Kroah-Hartman
Browse files

igmp: Fix data-races around sysctl_igmp_llm_reports.



[ Upstream commit f6da2267e71106474fbc0943dc24928b9cb79119 ]

While reading sysctl_igmp_llm_reports, it can be changed concurrently.
Thus, we need to add READ_ONCE() to its readers.

This test can be packed into a helper, so such changes will be in the
follow-up series after net is merged into net-next.

  if (ipv4_is_local_multicast(pmc->multiaddr) &&
      !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))

Fixes: df2cf4a7 ("IGMP: Inhibit reports for local multicast groups")
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 52d3c2e6
Loading
Loading
Loading
Loading
+13 −8
Original line number Original line Diff line number Diff line
@@ -471,7 +471,8 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,


	if (pmc->multiaddr == IGMP_ALL_HOSTS)
	if (pmc->multiaddr == IGMP_ALL_HOSTS)
		return skb;
		return skb;
	if (ipv4_is_local_multicast(pmc->multiaddr) && !net->ipv4.sysctl_igmp_llm_reports)
	if (ipv4_is_local_multicast(pmc->multiaddr) &&
	    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
		return skb;
		return skb;


	mtu = READ_ONCE(dev->mtu);
	mtu = READ_ONCE(dev->mtu);
@@ -597,7 +598,7 @@ static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc)
			if (pmc->multiaddr == IGMP_ALL_HOSTS)
			if (pmc->multiaddr == IGMP_ALL_HOSTS)
				continue;
				continue;
			if (ipv4_is_local_multicast(pmc->multiaddr) &&
			if (ipv4_is_local_multicast(pmc->multiaddr) &&
			     !net->ipv4.sysctl_igmp_llm_reports)
			    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
				continue;
				continue;
			spin_lock_bh(&pmc->lock);
			spin_lock_bh(&pmc->lock);
			if (pmc->sfcount[MCAST_EXCLUDE])
			if (pmc->sfcount[MCAST_EXCLUDE])
@@ -740,7 +741,8 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
	if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
	if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
		return igmpv3_send_report(in_dev, pmc);
		return igmpv3_send_report(in_dev, pmc);


	if (ipv4_is_local_multicast(group) && !net->ipv4.sysctl_igmp_llm_reports)
	if (ipv4_is_local_multicast(group) &&
	    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
		return 0;
		return 0;


	if (type == IGMP_HOST_LEAVE_MESSAGE)
	if (type == IGMP_HOST_LEAVE_MESSAGE)
@@ -924,7 +926,8 @@ static bool igmp_heard_report(struct in_device *in_dev, __be32 group)


	if (group == IGMP_ALL_HOSTS)
	if (group == IGMP_ALL_HOSTS)
		return false;
		return false;
	if (ipv4_is_local_multicast(group) && !net->ipv4.sysctl_igmp_llm_reports)
	if (ipv4_is_local_multicast(group) &&
	    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
		return false;
		return false;


	rcu_read_lock();
	rcu_read_lock();
@@ -1049,7 +1052,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
		if (im->multiaddr == IGMP_ALL_HOSTS)
		if (im->multiaddr == IGMP_ALL_HOSTS)
			continue;
			continue;
		if (ipv4_is_local_multicast(im->multiaddr) &&
		if (ipv4_is_local_multicast(im->multiaddr) &&
		    !net->ipv4.sysctl_igmp_llm_reports)
		    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
			continue;
			continue;
		spin_lock_bh(&im->lock);
		spin_lock_bh(&im->lock);
		if (im->tm_running)
		if (im->tm_running)
@@ -1299,7 +1302,8 @@ static void igmp_group_dropped(struct ip_mc_list *im)
#ifdef CONFIG_IP_MULTICAST
#ifdef CONFIG_IP_MULTICAST
	if (im->multiaddr == IGMP_ALL_HOSTS)
	if (im->multiaddr == IGMP_ALL_HOSTS)
		return;
		return;
	if (ipv4_is_local_multicast(im->multiaddr) && !net->ipv4.sysctl_igmp_llm_reports)
	if (ipv4_is_local_multicast(im->multiaddr) &&
	    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
		return;
		return;


	reporter = im->reporter;
	reporter = im->reporter;
@@ -1336,7 +1340,8 @@ static void igmp_group_added(struct ip_mc_list *im)
#ifdef CONFIG_IP_MULTICAST
#ifdef CONFIG_IP_MULTICAST
	if (im->multiaddr == IGMP_ALL_HOSTS)
	if (im->multiaddr == IGMP_ALL_HOSTS)
		return;
		return;
	if (ipv4_is_local_multicast(im->multiaddr) && !net->ipv4.sysctl_igmp_llm_reports)
	if (ipv4_is_local_multicast(im->multiaddr) &&
	    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
		return;
		return;


	if (in_dev->dead)
	if (in_dev->dead)
@@ -1657,7 +1662,7 @@ static void ip_mc_rejoin_groups(struct in_device *in_dev)
		if (im->multiaddr == IGMP_ALL_HOSTS)
		if (im->multiaddr == IGMP_ALL_HOSTS)
			continue;
			continue;
		if (ipv4_is_local_multicast(im->multiaddr) &&
		if (ipv4_is_local_multicast(im->multiaddr) &&
		    !net->ipv4.sysctl_igmp_llm_reports)
		    !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports))
			continue;
			continue;


		/* a failover is happening and switches
		/* a failover is happening and switches