diff options
author | Shawn Bohrer <sbohrer@rgmadvisors.com> | 2015-06-03 17:27:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-06-04 03:46:26 -0400 |
commit | 6e540309326188f769e03bb4c6dd8ff6752930c2 (patch) | |
tree | 5e024fab9cf5bd0affa537c2c04389daa551d022 /net | |
parent | 640b2b107cec23c754214b62a811465fa8f9257f (diff) |
ipv4/udp: Verify multicast group is ours in upd_v4_early_demux()
421b3885bf6d56391297844f43fb7154a6396e12 "udp: ipv4: Add udp early
demux" introduced a regression that allowed sockets bound to INADDR_ANY
to receive packets from multicast groups that the socket had not joined.
For example a socket that had joined 224.168.2.9 could also receive
packets from 225.168.2.9 despite not having joined that group if
ip_early_demux is enabled.
Fix this by calling ip_check_mc_rcu() in udp_v4_early_demux() to verify
that the multicast packet is indeed ours.
Signed-off-by: Shawn Bohrer <sbohrer@rgmadvisors.com>
Reported-by: Yurij M. Plotnikov <Yurij.Plotnikov@oktetlabs.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/udp.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1c92ea67baef..83aa604f9273 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <linux/socket.h> | 90 | #include <linux/socket.h> |
91 | #include <linux/sockios.h> | 91 | #include <linux/sockios.h> |
92 | #include <linux/igmp.h> | 92 | #include <linux/igmp.h> |
93 | #include <linux/inetdevice.h> | ||
93 | #include <linux/in.h> | 94 | #include <linux/in.h> |
94 | #include <linux/errno.h> | 95 | #include <linux/errno.h> |
95 | #include <linux/timer.h> | 96 | #include <linux/timer.h> |
@@ -1960,6 +1961,7 @@ void udp_v4_early_demux(struct sk_buff *skb) | |||
1960 | struct sock *sk; | 1961 | struct sock *sk; |
1961 | struct dst_entry *dst; | 1962 | struct dst_entry *dst; |
1962 | int dif = skb->dev->ifindex; | 1963 | int dif = skb->dev->ifindex; |
1964 | int ours; | ||
1963 | 1965 | ||
1964 | /* validate the packet */ | 1966 | /* validate the packet */ |
1965 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) | 1967 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) |
@@ -1969,14 +1971,24 @@ void udp_v4_early_demux(struct sk_buff *skb) | |||
1969 | uh = udp_hdr(skb); | 1971 | uh = udp_hdr(skb); |
1970 | 1972 | ||
1971 | if (skb->pkt_type == PACKET_BROADCAST || | 1973 | if (skb->pkt_type == PACKET_BROADCAST || |
1972 | skb->pkt_type == PACKET_MULTICAST) | 1974 | skb->pkt_type == PACKET_MULTICAST) { |
1975 | struct in_device *in_dev = __in_dev_get_rcu(skb->dev); | ||
1976 | |||
1977 | if (!in_dev) | ||
1978 | return; | ||
1979 | |||
1980 | ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, | ||
1981 | iph->protocol); | ||
1982 | if (!ours) | ||
1983 | return; | ||
1973 | sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, | 1984 | sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, |
1974 | uh->source, iph->saddr, dif); | 1985 | uh->source, iph->saddr, dif); |
1975 | else if (skb->pkt_type == PACKET_HOST) | 1986 | } else if (skb->pkt_type == PACKET_HOST) { |
1976 | sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, | 1987 | sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, |
1977 | uh->source, iph->saddr, dif); | 1988 | uh->source, iph->saddr, dif); |
1978 | else | 1989 | } else { |
1979 | return; | 1990 | return; |
1991 | } | ||
1980 | 1992 | ||
1981 | if (!sk) | 1993 | if (!sk) |
1982 | return; | 1994 | return; |