netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
@ 2014-05-12 16:38 Yurij M. Plotnikov
  2014-05-12 17:18 ` Eric Dumazet
  0 siblings, 1 reply; 12+ messages in thread
From: Yurij M. Plotnikov @ 2014-05-12 16:38 UTC (permalink / raw)
  To: netdev; +Cc: Alexandra N. Kossovsky

[-- Attachment #1: Type: text/plain, Size: 810 bytes --]

On kernel 3.13.10-1 I see that socket joined to one multicast group 
receives packets to another multicast address. That can be reproduced by 
the following example:

1. socket(DGRAM) -> 3
2. bind(3, 0.0.0.0:12345) -> 0
3. setsockopt(3, IP_MULTICAST_IF, {224.168.2.9, 7}) -> 0
// "7" is correct interface index

4. Send packet from peer host to 224.168.2.9:12345
5. poll({3, POLLIN}) -> 1
6. recv(3) -> <data_length>

5. Send packet from peer host to 225.168.2.9:12345
// Note that the address is not the same!
6. poll({3, POLLIN}) -> 1
7. recv(3) -> <data_length>

I checked kernel 3.12.6-2, there is no such problem. I have placed 
simple C-program in attachment to reproduce the behaviour. It should be 
called:
./mult_recv <mcast_address> <interface index> i.e. in example above:
./mult_recv 224.168.2.9 7

[-- Attachment #2: mult_recv.c --]
[-- Type: text/x-csrc, Size: 1785 bytes --]

#include <stdio.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <poll.h>

int
main(int argc, char *argv[])
{
    int sock;
    int rc;
    struct sockaddr_in addr;
    struct ip_mreqn req;
    char buf[256];
    struct pollfd fds;

    if (argc < 2)
    {
        printf("\nToo few arguments\n");
        return 1;
    }

    sock = socket(PF_INET, SOCK_DGRAM, 0);
    printf("socket() -> %d(%d)\n", sock, errno);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.s_addr = INADDR_ANY;
    rc = bind(sock, (struct sockaddr*)&addr, sizeof(addr));
    printf("bind() -> %d(%d)\n", rc, errno);

    memset((void *)&req, 0, sizeof(req));
    rc = inet_aton(argv[1], &req.imr_multiaddr);
    printf("inet_aton() -> %d(%d)\n", rc, errno);
    req.imr_ifindex = atoi(argv[2]);

    rc = setsockopt(sock, SOL_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req));
    printf("setsockopt() -> %d(%d)\n", rc, errno);

    printf("Send packet to %s:12345 address...", argv[1]);
    getchar();

    fds.fd = sock;
    fds.events = POLLIN;
    rc = poll(&fds, 1, 1000);
    printf("poll() -> %d(%d)\n", rc, errno);

    if (rc != 1)
    {
        printf("The packet was not received.\n");
        return 1;
    }

    rc = recv(sock, buf, sizeof(buf), 0);
    printf("recv() -> %d(%d)\n", rc, errno);

    printf("Send packet to different multicast address(with 12345 port)...");
    getchar();

    rc = poll(&fds, 1, 1000);
    printf("poll() -> %d(%d)\n", rc, errno);

    if (rc != 0)
    {
        printf("The packet to different multicast address was received.\n");
        rc = recv(sock, buf, sizeof(buf), 0);
        printf("recv() -> %d(%d)\n", rc, errno);
        return 1;
    }
    printf("The behaviour is correct\n");

    return 0;
}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2014-05-12 16:38 Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1 Yurij M. Plotnikov
@ 2014-05-12 17:18 ` Eric Dumazet
  2014-05-13  6:25   ` Yurij M. Plotnikov
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Dumazet @ 2014-05-12 17:18 UTC (permalink / raw)
  To: Yurij M. Plotnikov; +Cc: netdev, Alexandra N. Kossovsky, Shawn Bohrer

On Mon, 2014-05-12 at 20:38 +0400, Yurij M. Plotnikov wrote:
> On kernel 3.13.10-1 I see that socket joined to one multicast group 
> receives packets to another multicast address. That can be reproduced by 
> the following example:
> 
> 1. socket(DGRAM) -> 3
> 2. bind(3, 0.0.0.0:12345) -> 0
> 3. setsockopt(3, IP_MULTICAST_IF, {224.168.2.9, 7}) -> 0
> // "7" is correct interface index
> 
> 4. Send packet from peer host to 224.168.2.9:12345
> 5. poll({3, POLLIN}) -> 1
> 6. recv(3) -> <data_length>
> 
> 5. Send packet from peer host to 225.168.2.9:12345
> // Note that the address is not the same!
> 6. poll({3, POLLIN}) -> 1
> 7. recv(3) -> <data_length>
> 
> I checked kernel 3.12.6-2, there is no such problem. I have placed 
> simple C-program in attachment to reproduce the behaviour. It should be 
> called:
> ./mult_recv <mcast_address> <interface index> i.e. in example above:
> ./mult_recv 224.168.2.9 7

I suspect problem came with commit
421b3885bf6d56391297844f43fb7154a6396e12
("udp: ipv4: Add udp early demux")

Is that better if you try :

echo 0 >/proc/sys/net/ipv4/ip_early_demux

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2014-05-12 17:18 ` Eric Dumazet
@ 2014-05-13  6:25   ` Yurij M. Plotnikov
  2014-05-13 21:36     ` Shawn Bohrer
  0 siblings, 1 reply; 12+ messages in thread
From: Yurij M. Plotnikov @ 2014-05-13  6:25 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, Alexandra N. Kossovsky, Shawn Bohrer

On 12/05/14 21:18, Eric Dumazet wrote:
> On Mon, 2014-05-12 at 20:38 +0400, Yurij M. Plotnikov wrote:
>> On kernel 3.13.10-1 I see that socket joined to one multicast group
>> receives packets to another multicast address. That can be reproduced by
>> the following example:
>>
>> 1. socket(DGRAM) -> 3
>> 2. bind(3, 0.0.0.0:12345) -> 0
>> 3. setsockopt(3, IP_MULTICAST_IF, {224.168.2.9, 7}) -> 0
>> // "7" is correct interface index
>>
>> 4. Send packet from peer host to 224.168.2.9:12345
>> 5. poll({3, POLLIN}) -> 1
>> 6. recv(3) -> <data_length>
>>
>> 5. Send packet from peer host to 225.168.2.9:12345
>> // Note that the address is not the same!
>> 6. poll({3, POLLIN}) -> 1
>> 7. recv(3) -> <data_length>
>>
>> I checked kernel 3.12.6-2, there is no such problem. I have placed
>> simple C-program in attachment to reproduce the behaviour. It should be
>> called:
>> ./mult_recv <mcast_address> <interface index> i.e. in example above:
>> ./mult_recv 224.168.2.9 7
>
> I suspect problem came with commit
> 421b3885bf6d56391297844f43fb7154a6396e12
> ("udp: ipv4: Add udp early demux")
>
> Is that better if you try :
>
> echo 0 >/proc/sys/net/ipv4/ip_early_demux
>
Yes, this fixes the problem.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2014-05-13  6:25   ` Yurij M. Plotnikov
@ 2014-05-13 21:36     ` Shawn Bohrer
  2014-05-14 20:40       ` Shawn Bohrer
  0 siblings, 1 reply; 12+ messages in thread
From: Shawn Bohrer @ 2014-05-13 21:36 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Yurij M. Plotnikov, netdev, Alexandra N. Kossovsky, Shawn Bohrer

On Tue, May 13, 2014 at 10:25:37AM +0400, Yurij M. Plotnikov wrote:
> On 12/05/14 21:18, Eric Dumazet wrote:
> >On Mon, 2014-05-12 at 20:38 +0400, Yurij M. Plotnikov wrote:
> >>On kernel 3.13.10-1 I see that socket joined to one multicast group
> >>receives packets to another multicast address. That can be reproduced by
> >>the following example:
> >>
> >>1. socket(DGRAM) -> 3
> >>2. bind(3, 0.0.0.0:12345) -> 0
> >>3. setsockopt(3, IP_MULTICAST_IF, {224.168.2.9, 7}) -> 0
> >>// "7" is correct interface index
> >>
> >>4. Send packet from peer host to 224.168.2.9:12345
> >>5. poll({3, POLLIN}) -> 1
> >>6. recv(3) -> <data_length>
> >>
> >>5. Send packet from peer host to 225.168.2.9:12345
> >>// Note that the address is not the same!
> >>6. poll({3, POLLIN}) -> 1
> >>7. recv(3) -> <data_length>
> >>
> >>I checked kernel 3.12.6-2, there is no such problem. I have placed
> >>simple C-program in attachment to reproduce the behaviour. It should be
> >>called:
> >>./mult_recv <mcast_address> <interface index> i.e. in example above:
> >>./mult_recv 224.168.2.9 7
> >
> >I suspect problem came with commit
> >421b3885bf6d56391297844f43fb7154a6396e12
> >("udp: ipv4: Add udp early demux")
> >
> >Is that better if you try :
> >
> >echo 0 >/proc/sys/net/ipv4/ip_early_demux
> >
> Yes, this fixes the problem.

Eric can you (or someone) comment on if I actually broke something
here?  The example Yurij provided binds to INADDR_ANY and thus will
receive any packets destined to port 12345.  So for example even with
ip_early_demux disabled simply running a second instance of the
mult_recv example on the same host results in the same behavior, e.g.

./mult_recv 225.168.2.9 7 >/dev/null 2>&1 &
./mult_recv 224.168.2.9 7

Both programs will receive packets destined to 224.168.2.9 and
225.168.2.9.  Specifically this works because of the IP_ADD_MEMBERSHIP
for 225.168.2.9, which leads to my next question.  When we _don't_ do
the IP_ADD_MEMBERSHIP for 225.168.2.9 why are they getting delivered
to the interface in the first place?  Shouldn't igmp be preventing
this?

If I did "break" something here it appears to be because with
ip_early_demux we only call ip_check_mc_rcu() once on the initial
packet, and subsequent packets destined for that socket simply need to
pass the __udp_is_mcast_sock() test.  With ip_early_demux disaled we
call ip_check_mc_rcu() for every packet.

--
Shawn

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2014-05-13 21:36     ` Shawn Bohrer
@ 2014-05-14 20:40       ` Shawn Bohrer
  2015-05-24  4:55         ` Oliver Graff
  0 siblings, 1 reply; 12+ messages in thread
From: Shawn Bohrer @ 2014-05-14 20:40 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Yurij M. Plotnikov, netdev, Alexandra N. Kossovsky, Shawn Bohrer

On Tue, May 13, 2014 at 04:36:41PM -0500, Shawn Bohrer wrote:
> Eric can you (or someone) comment on if I actually broke something
> here?  The example Yurij provided binds to INADDR_ANY and thus will
> receive any packets destined to port 12345.  So for example even with
> ip_early_demux disabled simply running a second instance of the
> mult_recv example on the same host results in the same behavior, e.g.
> 
> ./mult_recv 225.168.2.9 7 >/dev/null 2>&1 &
> ./mult_recv 224.168.2.9 7
> 
> Both programs will receive packets destined to 224.168.2.9 and
> 225.168.2.9.  Specifically this works because of the IP_ADD_MEMBERSHIP
> for 225.168.2.9, which leads to my next question.  When we _don't_ do
> the IP_ADD_MEMBERSHIP for 225.168.2.9 why are they getting delivered
> to the interface in the first place?  Shouldn't igmp be preventing
> this?

Partially answering my own question here about why the 225.168.2.9
packets arrive at the host in the first place without doing an
IP_ADD_MEMBERSHIP.  Essentially the first 9 bits of the IP address do
not map to the MAC-layer multicast address.  Thus only incrementing
the first octect of the IP means they both have the same MAC-layer
multicast address and are both delivered to the interface.  Here is a
fine microsoft article explaining the mapping of IP multicast address
to MAC-layer Multicast.

http://technet.microsoft.com/en-us/library/cc957928.aspx

The Microsoft article mentions that the host may receive these packets
for groups to which it does not belong, but they will be dropped once
the destination IP is determined.  So it seems that I likely did
indeed break things.

> If I did "break" something here it appears to be because with
> ip_early_demux we only call ip_check_mc_rcu() once on the initial
> packet, and subsequent packets destined for that socket simply need to
> pass the __udp_is_mcast_sock() test.  With ip_early_demux disaled we
> call ip_check_mc_rcu() for every packet.

So is the solution to effectively call ip_check_mc_rcu() inside
udp_v4_early_demux()?

--
Shawn

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2014-05-14 20:40       ` Shawn Bohrer
@ 2015-05-24  4:55         ` Oliver Graff
  2015-05-26 17:41           ` Shawn Bohrer
  0 siblings, 1 reply; 12+ messages in thread
From: Oliver Graff @ 2015-05-24  4:55 UTC (permalink / raw)
  To: netdev

Shawn Bohrer <shawn.bohrer <at> gmail.com> writes:

> 
> On Tue, May 13, 2014 at 04:36:41PM -0500, Shawn Bohrer wrote:

> > If I did "break" something here it appears to be because with
> > ip_early_demux we only call ip_check_mc_rcu() once on the initial
> > packet, and subsequent packets destined for that socket simply need to
> > pass the __udp_is_mcast_sock() test.  With ip_early_demux disaled we
> > call ip_check_mc_rcu() for every packet.
> 
> So is the solution to effectively call ip_check_mc_rcu() inside
> udp_v4_early_demux()?
> 
> --
> Shawn
> 
(See earlier parts of thread here: 
http://netdev.vger.kernel.narkive.com/mwurLsMT/socket-receives-packet-to-multicast-
group-to-which-it-was-not-joined-since-kernel-3-13-10-1)

Was a bug report filed for this / was this fixed? 
I looked at the diffs from the referenced commit and the current version of 
udp_v4_early_demux and the changes appear to be 
minimal,
it doesn't look like ip_check_mc_rcu was added. Is that all that's needed?

- Oliver

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2015-05-24  4:55         ` Oliver Graff
@ 2015-05-26 17:41           ` Shawn Bohrer
  2015-05-26 17:59             ` Eric Dumazet
  0 siblings, 1 reply; 12+ messages in thread
From: Shawn Bohrer @ 2015-05-26 17:41 UTC (permalink / raw)
  To: Oliver Graff; +Cc: netdev

On Sun, May 24, 2015 at 04:55:40AM +0000, Oliver Graff wrote:
> Shawn Bohrer <shawn.bohrer <at> gmail.com> writes:
> 
> > 
> > On Tue, May 13, 2014 at 04:36:41PM -0500, Shawn Bohrer wrote:
> 
> > > If I did "break" something here it appears to be because with
> > > ip_early_demux we only call ip_check_mc_rcu() once on the initial
> > > packet, and subsequent packets destined for that socket simply need to
> > > pass the __udp_is_mcast_sock() test.  With ip_early_demux disaled we
> > > call ip_check_mc_rcu() for every packet.
> > 
> > So is the solution to effectively call ip_check_mc_rcu() inside
> > udp_v4_early_demux()?
> > 
> > --
> > Shawn
> > 
> (See earlier parts of thread here: 
> http://netdev.vger.kernel.narkive.com/mwurLsMT/socket-receives-packet-to-multicast-
> group-to-which-it-was-not-joined-since-kernel-3-13-10-1)
> 
> Was a bug report filed for this / was this fixed? 
> I looked at the diffs from the referenced commit and the current version of 
> udp_v4_early_demux and the changes appear to be 
> minimal,
> it doesn't look like ip_check_mc_rcu was added. Is that all that's needed?

Hi Oliver,

I haven't tested but looking over the code I would say that this has
not been fixed.  Is this issue impacting you?

I think calling ip_check_mc_rcu (you might need some of the code from
ip_route_input_noref too) might "fix" the issue, though I have not
tried.  My concern is that early demux is a performance optimization
and I don't know how much this would impact multicast receive
performance.

As Eric mentioned in the earlier email if you don't care about
performance you can simply disable early demux:

echo 0 >/proc/sys/net/ipv4/ip_early_demux

--
Shawn

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1
  2015-05-26 17:41           ` Shawn Bohrer
@ 2015-05-26 17:59             ` Eric Dumazet
  2015-06-01 16:34               ` [PATCH] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux() Shawn Bohrer
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Dumazet @ 2015-05-26 17:59 UTC (permalink / raw)
  To: Shawn Bohrer; +Cc: Oliver Graff, netdev

On Tue, 2015-05-26 at 12:41 -0500, Shawn Bohrer wrote:
> On Sun, May 24, 2015 at 04:55:40AM +0000, Oliver Graff wrote:
> > Shawn Bohrer <shawn.bohrer <at> gmail.com> writes:
> > 
> > > 
> > > On Tue, May 13, 2014 at 04:36:41PM -0500, Shawn Bohrer wrote:
> > 
> > > > If I did "break" something here it appears to be because with
> > > > ip_early_demux we only call ip_check_mc_rcu() once on the initial
> > > > packet, and subsequent packets destined for that socket simply need to
> > > > pass the __udp_is_mcast_sock() test.  With ip_early_demux disaled we
> > > > call ip_check_mc_rcu() for every packet.
> > > 
> > > So is the solution to effectively call ip_check_mc_rcu() inside
> > > udp_v4_early_demux()?
> > > 
> > > --
> > > Shawn
> > > 
> > (See earlier parts of thread here: 
> > http://netdev.vger.kernel.narkive.com/mwurLsMT/socket-receives-packet-to-multicast-
> > group-to-which-it-was-not-joined-since-kernel-3-13-10-1)
> > 
> > Was a bug report filed for this / was this fixed? 
> > I looked at the diffs from the referenced commit and the current version of 
> > udp_v4_early_demux and the changes appear to be 
> > minimal,
> > it doesn't look like ip_check_mc_rcu was added. Is that all that's needed?
> 
> Hi Oliver,
> 
> I haven't tested but looking over the code I would say that this has
> not been fixed.  Is this issue impacting you?
> 
> I think calling ip_check_mc_rcu (you might need some of the code from
> ip_route_input_noref too) might "fix" the issue, though I have not
> tried.  My concern is that early demux is a performance optimization
> and I don't know how much this would impact multicast receive
> performance.
> 
> As Eric mentioned in the earlier email if you don't care about
> performance you can simply disable early demux:
> 
> echo 0 >/proc/sys/net/ipv4/ip_early_demux

Well, we should fix the bug, whatever this sysctl value is ;)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux()
  2015-05-26 17:59             ` Eric Dumazet
@ 2015-06-01 16:34               ` Shawn Bohrer
  2015-06-01 20:11                 ` Sergei Shtylyov
  0 siblings, 1 reply; 12+ messages in thread
From: Shawn Bohrer @ 2015-06-01 16:34 UTC (permalink / raw)
  To: netdev
  Cc: Yurij M. Plotnikov, Alexandra.Kossovsky, Eric Dumazet,
	Oliver Graff, davem, Shawn Bohrer

From: Shawn Bohrer <sbohrer@rgmadvisors.com>

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>
---
 net/ipv4/udp.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d10b7e0..17d31f5 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -90,6 +90,7 @@
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/igmp.h>
+#include <linux/inetdevice.h>
 #include <linux/in.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
@@ -1959,7 +1960,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
 	struct net *net = dev_net(skb->dev);
 	const struct iphdr *iph;
 	const struct udphdr *uh;
-	struct sock *sk;
+	struct sock *sk = NULL;
 	struct dst_entry *dst;
 	int dif = skb->dev->ifindex;
 
@@ -1971,10 +1972,17 @@ void udp_v4_early_demux(struct sk_buff *skb)
 	uh = udp_hdr(skb);
 
 	if (skb->pkt_type == PACKET_BROADCAST ||
-	    skb->pkt_type == PACKET_MULTICAST)
-		sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
-						   uh->source, iph->saddr, dif);
-	else if (skb->pkt_type == PACKET_HOST)
+	    skb->pkt_type == PACKET_MULTICAST) {
+		struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
+
+		if (in_dev) {
+			int our = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
+						  iph->protocol);
+			if (our)
+				sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
+								   uh->source, iph->saddr, dif);
+		}
+	} else if (skb->pkt_type == PACKET_HOST)
 		sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,
 					     uh->source, iph->saddr, dif);
 	else
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux()
  2015-06-01 16:34               ` [PATCH] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux() Shawn Bohrer
@ 2015-06-01 20:11                 ` Sergei Shtylyov
  2015-06-03 21:27                   ` [PATCH v2] " Shawn Bohrer
  0 siblings, 1 reply; 12+ messages in thread
From: Sergei Shtylyov @ 2015-06-01 20:11 UTC (permalink / raw)
  To: Shawn Bohrer, netdev
  Cc: Yurij M. Plotnikov, Alexandra.Kossovsky, Eric Dumazet,
	Oliver Graff, davem, Shawn Bohrer

Hello.

On 06/01/2015 07:34 PM, Shawn Bohrer wrote:

> From: Shawn Bohrer <sbohrer@rgmadvisors.com>

> 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>
> ---
>   net/ipv4/udp.c | 18 +++++++++++++-----
>   1 file changed, 13 insertions(+), 5 deletions(-)

> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> index d10b7e0..17d31f5 100644
> --- a/net/ipv4/udp.c
> +++ b/net/ipv4/udp.c
[...]
> @@ -1971,10 +1972,17 @@ void udp_v4_early_demux(struct sk_buff *skb)
>   	uh = udp_hdr(skb);
>
>   	if (skb->pkt_type == PACKET_BROADCAST ||
> -	    skb->pkt_type == PACKET_MULTICAST)
> -		sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
> -						   uh->source, iph->saddr, dif);
> -	else if (skb->pkt_type == PACKET_HOST)
> +	    skb->pkt_type == PACKET_MULTICAST) {
> +		struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
> +
> +		if (in_dev) {
> +			int our = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
> +						  iph->protocol);
> +			if (our)
> +				sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
> +								   uh->source, iph->saddr, dif);
> +		}
> +	} else if (skb->pkt_type == PACKET_HOST)
>   		sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,
>   					     uh->source, iph->saddr, dif);
>   	else

    Must add {} around all branches of the *if* statement if you're adding 
them around just one; see Documentation/CodingStyle.

WBR, Sergei

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux()
  2015-06-01 20:11                 ` Sergei Shtylyov
@ 2015-06-03 21:27                   ` Shawn Bohrer
  2015-06-04  7:46                     ` David Miller
  0 siblings, 1 reply; 12+ messages in thread
From: Shawn Bohrer @ 2015-06-03 21:27 UTC (permalink / raw)
  To: netdev
  Cc: Yurij M. Plotnikov, Alexandra.Kossovsky, Eric Dumazet,
	Oliver Graff, davem, sergei.shtylyov, Shawn Bohrer

From: Shawn Bohrer <sbohrer@rgmadvisors.com>

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>
---

Coding style fixes.  Added braces around if branches, and inverted logic
to avoid long lines.

 net/ipv4/udp.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d10b7e0..df1b285 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -90,6 +90,7 @@
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/igmp.h>
+#include <linux/inetdevice.h>
 #include <linux/in.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
@@ -1962,6 +1963,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
 	struct sock *sk;
 	struct dst_entry *dst;
 	int dif = skb->dev->ifindex;
+	int ours;
 
 	/* validate the packet */
 	if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
@@ -1971,14 +1973,24 @@ void udp_v4_early_demux(struct sk_buff *skb)
 	uh = udp_hdr(skb);
 
 	if (skb->pkt_type == PACKET_BROADCAST ||
-	    skb->pkt_type == PACKET_MULTICAST)
+	    skb->pkt_type == PACKET_MULTICAST) {
+		struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
+
+		if (!in_dev)
+			return;
+
+		ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
+				       iph->protocol);
+		if (!ours)
+			return;
 		sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
 						   uh->source, iph->saddr, dif);
-	else if (skb->pkt_type == PACKET_HOST)
+	} else if (skb->pkt_type == PACKET_HOST) {
 		sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,
 					     uh->source, iph->saddr, dif);
-	else
+	} else {
 		return;
+	}
 
 	if (!sk)
 		return;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v2] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux()
  2015-06-03 21:27                   ` [PATCH v2] " Shawn Bohrer
@ 2015-06-04  7:46                     ` David Miller
  0 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2015-06-04  7:46 UTC (permalink / raw)
  To: shawn.bohrer
  Cc: netdev, Yurij.Plotnikov, Alexandra.Kossovsky, eric.dumazet,
	oliver.e.graff, sergei.shtylyov, sbohrer

From: Shawn Bohrer <shawn.bohrer@gmail.com>
Date: Wed,  3 Jun 2015 16:27:38 -0500

> From: Shawn Bohrer <sbohrer@rgmadvisors.com>
> 
> 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>

Applied and queued up for -stable, thanks.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-06-04  7:56 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-12 16:38 Socket receives packet to multicast group to which it was not joined since kernel 3.13.10-1 Yurij M. Plotnikov
2014-05-12 17:18 ` Eric Dumazet
2014-05-13  6:25   ` Yurij M. Plotnikov
2014-05-13 21:36     ` Shawn Bohrer
2014-05-14 20:40       ` Shawn Bohrer
2015-05-24  4:55         ` Oliver Graff
2015-05-26 17:41           ` Shawn Bohrer
2015-05-26 17:59             ` Eric Dumazet
2015-06-01 16:34               ` [PATCH] ipv4/udp: Verify multicast group is ours in upd_v4_early_demux() Shawn Bohrer
2015-06-01 20:11                 ` Sergei Shtylyov
2015-06-03 21:27                   ` [PATCH v2] " Shawn Bohrer
2015-06-04  7:46                     ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).