aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorShawn Bohrer <sbohrer@rgmadvisors.com>2015-06-03 17:27:38 -0400
committerDavid S. Miller <davem@davemloft.net>2015-06-04 03:46:26 -0400
commit6e540309326188f769e03bb4c6dd8ff6752930c2 (patch)
tree5e024fab9cf5bd0affa537c2c04389daa551d022 /net
parent640b2b107cec23c754214b62a811465fa8f9257f (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.c18
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;