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

Commit 55b80503 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

net: Fix IP_MULTICAST_IF



ipv4/ipv6 setsockopt(IP_MULTICAST_IF) have dubious __dev_get_by_index() calls.

This function should be called only with RTNL or dev_base_lock held, or reader
could see a corrupt hash chain and eventually enter an endless loop.

Fix is to call dev_get_by_index()/dev_put().

If this happens to be performance critical, we could define a new dev_exist_by_index()
function to avoid touching dev refcount.

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 45054dc1
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -634,17 +634,16 @@ static int do_ip_setsockopt(struct sock *sk, int level,
				break;
			}
			dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr);
			if (dev) {
			if (dev)
				mreq.imr_ifindex = dev->ifindex;
				dev_put(dev);
			}
		} else
			dev = __dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
			dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex);


		err = -EADDRNOTAVAIL;
		if (!dev)
			break;
		dev_put(dev);

		err = -EINVAL;
		if (sk->sk_bound_dev_if &&
+5 −1
Original line number Diff line number Diff line
@@ -496,13 +496,17 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
			goto e_inval;

		if (val) {
			struct net_device *dev;

			if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
				goto e_inval;

			if (__dev_get_by_index(net, val) == NULL) {
			dev = dev_get_by_index(net, val);
			if (!dev) {
				retv = -ENODEV;
				break;
			}
			dev_put(dev);
		}
		np->mcast_oif = val;
		retv = 0;