Commit fd4a0bf3 authored by Andrew Lunn's avatar Andrew Lunn Committed by Luis Henriques

ipv4: igmp: Allow removing groups from a removed interface

commit 4eba7bb1 upstream.

When a multicast group is joined on a socket, a struct ip_mc_socklist
is appended to the sockets mc_list containing information about the
joined group.

If the interface is hot unplugged, this entry becomes stale. Prior to
commit 52ad353a ("igmp: fix the problem when mc leave group") it
was possible to remove the stale entry by performing a
IP_DROP_MEMBERSHIP, passing either the old ifindex or ip address on
the interface. However, this fix enforces that the interface must
still exist. Thus with time, the number of stale entries grows, until
sysctl_igmp_max_memberships is reached and then it is not possible to
join and more groups.

The previous patch fixes an issue where a IP_DROP_MEMBERSHIP is
performed without specifying the interface, either by ifindex or ip
address. However here we do supply one of these. So loosen the
restriction on device existence to only apply when the interface has
not been specified. This then restores the ability to clean up the
stale entries.
Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Fixes: 52ad353a "(igmp: fix the problem when mc leave group")
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
[ luis: backported to 3.16: adjusted context ]
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 49b4d2ca
...@@ -1943,7 +1943,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) ...@@ -1943,7 +1943,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
rtnl_lock(); rtnl_lock();
in_dev = ip_mc_find_dev(net, imr); in_dev = ip_mc_find_dev(net, imr);
if (!in_dev) { if (!imr->imr_ifindex && !imr->imr_address.s_addr && !in_dev) {
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
...@@ -1964,7 +1964,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) ...@@ -1964,7 +1964,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
*imlp = iml->next_rcu; *imlp = iml->next_rcu;
ip_mc_dec_group(in_dev, group); if (in_dev)
ip_mc_dec_group(in_dev, group);
rtnl_unlock(); rtnl_unlock();
/* decrease mem now to avoid the memleak warning */ /* decrease mem now to avoid the memleak warning */
atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment