netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] net: Handle negative checksum offset in skb-checksum-help
@ 2015-09-21  6:53 Pravin B Shelar
  2015-09-21 15:47 ` Alexander Duyck
  2015-09-22  0:14 ` David Miller
  0 siblings, 2 replies; 9+ messages in thread
From: Pravin B Shelar @ 2015-09-21  6:53 UTC (permalink / raw)
  To: netdev; +Cc: Pravin B Shelar

VXLAN device can receive skb with checksum partial. But the checksum
offset could be in outer header which is pulled on receive. This results
in negative checksum offset for the skb. Such skb can cause the assert
failure in skb_checksum_help(). The patch fixes the bug by checking for
negative offset in skb_checksum_help().

Following is the kernel panic msg from old kernel hitting the bug.

------------[ cut here ]------------
kernel BUG at net/core/dev.c:1906!
RIP: 0010:[<ffffffff81518034>] skb_checksum_help+0x144/0x150
Call Trace:
<IRQ>
[<ffffffffa0164c28>] queue_userspace_packet+0x408/0x470 [openvswitch]
[<ffffffffa016614d>] ovs_dp_upcall+0x5d/0x60 [openvswitch]
[<ffffffffa0166236>] ovs_dp_process_packet_with_key+0xe6/0x100 [openvswitch]
[<ffffffffa016629b>] ovs_dp_process_received_packet+0x4b/0x80 [openvswitch]
[<ffffffffa016c51a>] ovs_vport_receive+0x2a/0x30 [openvswitch]
[<ffffffffa0171383>] vxlan_rcv+0x53/0x60 [openvswitch]
[<ffffffffa01734cb>] vxlan_udp_encap_recv+0x8b/0xf0 [openvswitch]
[<ffffffff8157addc>] udp_queue_rcv_skb+0x2dc/0x3b0
[<ffffffff8157b56f>] __udp4_lib_rcv+0x1cf/0x6c0
[<ffffffff8157ba7a>] udp_rcv+0x1a/0x20
[<ffffffff8154fdbd>] ip_local_deliver_finish+0xdd/0x280
[<ffffffff81550128>] ip_local_deliver+0x88/0x90
[<ffffffff8154fa7d>] ip_rcv_finish+0x10d/0x370
[<ffffffff81550365>] ip_rcv+0x235/0x300
[<ffffffff8151ba1d>] __netif_receive_skb+0x55d/0x620
[<ffffffff8151c360>] netif_receive_skb+0x80/0x90
[<ffffffff81459935>] virtnet_poll+0x555/0x6f0
[<ffffffff8151cd04>] net_rx_action+0x134/0x290
[<ffffffff810683d8>] __do_softirq+0xa8/0x210
[<ffffffff8162fe6c>] call_softirq+0x1c/0x30
[<ffffffff810161a5>] do_softirq+0x65/0xa0
[<ffffffff810687be>] irq_exit+0x8e/0xb0
[<ffffffff81630733>] do_IRQ+0x63/0xe0
[<ffffffff81625f2e>] common_interrupt+0x6e/0x6e

Reported-by: Anupam Chanda <achanda@vmware.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
 net/core/dev.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index ee0d628..008f1ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2408,6 +2408,9 @@ int skb_checksum_help(struct sk_buff *skb)
 		skb_warn_bad_offload(skb);
 		return -EINVAL;
 	}
+	offset = skb_checksum_start_offset(skb);
+	if (offset < 0)
+		goto out_set_summed;
 
 	/* Before computing a checksum, we should make sure no frag could
 	 * be modified by an external entity : checksum could be wrong.
@@ -2418,7 +2421,6 @@ int skb_checksum_help(struct sk_buff *skb)
 			goto out;
 	}
 
-	offset = skb_checksum_start_offset(skb);
 	BUG_ON(offset >= skb_headlen(skb));
 	csum = skb_checksum(skb, offset, skb->len - offset, 0);
 
-- 
1.7.1

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-21  6:53 [PATCH net] net: Handle negative checksum offset in skb-checksum-help Pravin B Shelar
@ 2015-09-21 15:47 ` Alexander Duyck
  2015-09-21 17:45   ` Pravin Shelar
  2015-09-22  0:14 ` David Miller
  1 sibling, 1 reply; 9+ messages in thread
From: Alexander Duyck @ 2015-09-21 15:47 UTC (permalink / raw)
  To: Pravin B Shelar, netdev

On 09/20/2015 11:53 PM, Pravin B Shelar wrote:
> VXLAN device can receive skb with checksum partial. But the checksum
> offset could be in outer header which is pulled on receive. This results
> in negative checksum offset for the skb. Such skb can cause the assert
> failure in skb_checksum_help(). The patch fixes the bug by checking for
> negative offset in skb_checksum_help().
>
> Following is the kernel panic msg from old kernel hitting the bug.
>
> ------------[ cut here ]------------
> kernel BUG at net/core/dev.c:1906!
> RIP: 0010:[<ffffffff81518034>] skb_checksum_help+0x144/0x150
> Call Trace:
> <IRQ>
> [<ffffffffa0164c28>] queue_userspace_packet+0x408/0x470 [openvswitch]
> [<ffffffffa016614d>] ovs_dp_upcall+0x5d/0x60 [openvswitch]
> [<ffffffffa0166236>] ovs_dp_process_packet_with_key+0xe6/0x100 [openvswitch]
> [<ffffffffa016629b>] ovs_dp_process_received_packet+0x4b/0x80 [openvswitch]
> [<ffffffffa016c51a>] ovs_vport_receive+0x2a/0x30 [openvswitch]
> [<ffffffffa0171383>] vxlan_rcv+0x53/0x60 [openvswitch]
> [<ffffffffa01734cb>] vxlan_udp_encap_recv+0x8b/0xf0 [openvswitch]
> [<ffffffff8157addc>] udp_queue_rcv_skb+0x2dc/0x3b0
> [<ffffffff8157b56f>] __udp4_lib_rcv+0x1cf/0x6c0
> [<ffffffff8157ba7a>] udp_rcv+0x1a/0x20
> [<ffffffff8154fdbd>] ip_local_deliver_finish+0xdd/0x280
> [<ffffffff81550128>] ip_local_deliver+0x88/0x90
> [<ffffffff8154fa7d>] ip_rcv_finish+0x10d/0x370
> [<ffffffff81550365>] ip_rcv+0x235/0x300
> [<ffffffff8151ba1d>] __netif_receive_skb+0x55d/0x620
> [<ffffffff8151c360>] netif_receive_skb+0x80/0x90
> [<ffffffff81459935>] virtnet_poll+0x555/0x6f0
> [<ffffffff8151cd04>] net_rx_action+0x134/0x290
> [<ffffffff810683d8>] __do_softirq+0xa8/0x210
> [<ffffffff8162fe6c>] call_softirq+0x1c/0x30
> [<ffffffff810161a5>] do_softirq+0x65/0xa0
> [<ffffffff810687be>] irq_exit+0x8e/0xb0
> [<ffffffff81630733>] do_IRQ+0x63/0xe0
> [<ffffffff81625f2e>] common_interrupt+0x6e/0x6e
>
> Reported-by: Anupam Chanda <achanda@vmware.com>
> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
> ---
>   net/core/dev.c |    4 +++-
>   1 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index ee0d628..008f1ae 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2408,6 +2408,9 @@ int skb_checksum_help(struct sk_buff *skb)
>   		skb_warn_bad_offload(skb);
>   		return -EINVAL;
>   	}
> +	offset = skb_checksum_start_offset(skb);
> +	if (offset < 0)
> +		goto out_set_summed;
>   
>   	/* Before computing a checksum, we should make sure no frag could
>   	 * be modified by an external entity : checksum could be wrong.
> @@ -2418,7 +2421,6 @@ int skb_checksum_help(struct sk_buff *skb)
>   			goto out;
>   	}
>   
> -	offset = skb_checksum_start_offset(skb);
>   	BUG_ON(offset >= skb_headlen(skb));
>   	csum = skb_checksum(skb, offset, skb->len - offset, 0);

It seems like this is just masking an error instead of fixing it. If the 
offload is bad when you are calling this maybe you should be looking at 
instead clearing the flag that is getting you into the state where you 
are triggering a call to this function.

- Alex

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-21 15:47 ` Alexander Duyck
@ 2015-09-21 17:45   ` Pravin Shelar
  0 siblings, 0 replies; 9+ messages in thread
From: Pravin Shelar @ 2015-09-21 17:45 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: netdev

On Mon, Sep 21, 2015 at 8:47 AM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On 09/20/2015 11:53 PM, Pravin B Shelar wrote:
>>
>> VXLAN device can receive skb with checksum partial. But the checksum
>> offset could be in outer header which is pulled on receive. This results
>> in negative checksum offset for the skb. Such skb can cause the assert
>> failure in skb_checksum_help(). The patch fixes the bug by checking for
>> negative offset in skb_checksum_help().
>>
>> Following is the kernel panic msg from old kernel hitting the bug.
>>
>> ------------[ cut here ]------------
>> kernel BUG at net/core/dev.c:1906!
>> RIP: 0010:[<ffffffff81518034>] skb_checksum_help+0x144/0x150
>> Call Trace:
>> <IRQ>
>> [<ffffffffa0164c28>] queue_userspace_packet+0x408/0x470 [openvswitch]
>> [<ffffffffa016614d>] ovs_dp_upcall+0x5d/0x60 [openvswitch]
>> [<ffffffffa0166236>] ovs_dp_process_packet_with_key+0xe6/0x100
>> [openvswitch]
>> [<ffffffffa016629b>] ovs_dp_process_received_packet+0x4b/0x80
>> [openvswitch]
>> [<ffffffffa016c51a>] ovs_vport_receive+0x2a/0x30 [openvswitch]
>> [<ffffffffa0171383>] vxlan_rcv+0x53/0x60 [openvswitch]
>> [<ffffffffa01734cb>] vxlan_udp_encap_recv+0x8b/0xf0 [openvswitch]
>> [<ffffffff8157addc>] udp_queue_rcv_skb+0x2dc/0x3b0
>> [<ffffffff8157b56f>] __udp4_lib_rcv+0x1cf/0x6c0
>> [<ffffffff8157ba7a>] udp_rcv+0x1a/0x20
>> [<ffffffff8154fdbd>] ip_local_deliver_finish+0xdd/0x280
>> [<ffffffff81550128>] ip_local_deliver+0x88/0x90
>> [<ffffffff8154fa7d>] ip_rcv_finish+0x10d/0x370
>> [<ffffffff81550365>] ip_rcv+0x235/0x300
>> [<ffffffff8151ba1d>] __netif_receive_skb+0x55d/0x620
>> [<ffffffff8151c360>] netif_receive_skb+0x80/0x90
>> [<ffffffff81459935>] virtnet_poll+0x555/0x6f0
>> [<ffffffff8151cd04>] net_rx_action+0x134/0x290
>> [<ffffffff810683d8>] __do_softirq+0xa8/0x210
>> [<ffffffff8162fe6c>] call_softirq+0x1c/0x30
>> [<ffffffff810161a5>] do_softirq+0x65/0xa0
>> [<ffffffff810687be>] irq_exit+0x8e/0xb0
>> [<ffffffff81630733>] do_IRQ+0x63/0xe0
>> [<ffffffff81625f2e>] common_interrupt+0x6e/0x6e
>>
>> Reported-by: Anupam Chanda <achanda@vmware.com>
>> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
>> ---
>>   net/core/dev.c |    4 +++-
>>   1 files changed, 3 insertions(+), 1 deletions(-)
>>
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index ee0d628..008f1ae 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -2408,6 +2408,9 @@ int skb_checksum_help(struct sk_buff *skb)
>>                 skb_warn_bad_offload(skb);
>>                 return -EINVAL;
>>         }
>> +       offset = skb_checksum_start_offset(skb);
>> +       if (offset < 0)
>> +               goto out_set_summed;
>>         /* Before computing a checksum, we should make sure no frag could
>>          * be modified by an external entity : checksum could be wrong.
>> @@ -2418,7 +2421,6 @@ int skb_checksum_help(struct sk_buff *skb)
>>                         goto out;
>>         }
>>   -     offset = skb_checksum_start_offset(skb);
>>         BUG_ON(offset >= skb_headlen(skb));
>>         csum = skb_checksum(skb, offset, skb->len - offset, 0);
>
>
> It seems like this is just masking an error instead of fixing it. If the
> offload is bad when you are calling this maybe you should be looking at
> instead clearing the flag that is getting you into the state where you are
> triggering a call to this function.
>

This is not error case. This is packet with checksum offset set for
outer tunnel header. After  the outer header is pulled on tunnel decap
the checksum offset becomes negative. Therefore is does not make sense
to calculate checksum again.

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-21  6:53 [PATCH net] net: Handle negative checksum offset in skb-checksum-help Pravin B Shelar
  2015-09-21 15:47 ` Alexander Duyck
@ 2015-09-22  0:14 ` David Miller
  2015-09-22  1:04   ` Pravin Shelar
  1 sibling, 1 reply; 9+ messages in thread
From: David Miller @ 2015-09-22  0:14 UTC (permalink / raw)
  To: pshelar; +Cc: netdev

From: Pravin B Shelar <pshelar@nicira.com>
Date: Sun, 20 Sep 2015 23:53:17 -0700

> VXLAN device can receive skb with checksum partial. But the checksum
> offset could be in outer header which is pulled on receive.

Such a scenerio is a bug.

Anything that pulls off a header should use a utility function such
as skb_pull_rcsum() or skb_postpull_rcsum() to make sure this gets
fixed up properly.

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-22  0:14 ` David Miller
@ 2015-09-22  1:04   ` Pravin Shelar
  2015-09-22  2:14     ` Eric Dumazet
  0 siblings, 1 reply; 9+ messages in thread
From: Pravin Shelar @ 2015-09-22  1:04 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On Mon, Sep 21, 2015 at 5:14 PM, David Miller <davem@davemloft.net> wrote:
> From: Pravin B Shelar <pshelar@nicira.com>
> Date: Sun, 20 Sep 2015 23:53:17 -0700
>
>> VXLAN device can receive skb with checksum partial. But the checksum
>> offset could be in outer header which is pulled on receive.
>
> Such a scenerio is a bug.
>
> Anything that pulls off a header should use a utility function such
> as skb_pull_rcsum() or skb_postpull_rcsum() to make sure this gets
> fixed up properly.

skb_postpull_rcsum() does not change checksum-offset. vxlan receive
already calls this function.

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-22  1:04   ` Pravin Shelar
@ 2015-09-22  2:14     ` Eric Dumazet
  2015-09-22  2:49       ` Pravin Shelar
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2015-09-22  2:14 UTC (permalink / raw)
  To: Pravin Shelar; +Cc: David Miller, netdev

On Mon, 2015-09-21 at 18:04 -0700, Pravin Shelar wrote:
> On Mon, Sep 21, 2015 at 5:14 PM, David Miller <davem@davemloft.net> wrote:
> > From: Pravin B Shelar <pshelar@nicira.com>
> > Date: Sun, 20 Sep 2015 23:53:17 -0700
> >
> >> VXLAN device can receive skb with checksum partial. But the checksum
> >> offset could be in outer header which is pulled on receive.
> >
> > Such a scenerio is a bug.
> >
> > Anything that pulls off a header should use a utility function such
> > as skb_pull_rcsum() or skb_postpull_rcsum() to make sure this gets
> > fixed up properly.
> 
> skb_postpull_rcsum() does not change checksum-offset. vxlan receive
> already calls this function.

Then the bug is here.

Otherwise we might have to 'fix' other places.

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-22  2:14     ` Eric Dumazet
@ 2015-09-22  2:49       ` Pravin Shelar
  2015-09-22  3:21         ` Eric Dumazet
  0 siblings, 1 reply; 9+ messages in thread
From: Pravin Shelar @ 2015-09-22  2:49 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Tom Herbert

On Mon, Sep 21, 2015 at 7:14 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2015-09-21 at 18:04 -0700, Pravin Shelar wrote:
>> On Mon, Sep 21, 2015 at 5:14 PM, David Miller <davem@davemloft.net> wrote:
>> > From: Pravin B Shelar <pshelar@nicira.com>
>> > Date: Sun, 20 Sep 2015 23:53:17 -0700
>> >
>> >> VXLAN device can receive skb with checksum partial. But the checksum
>> >> offset could be in outer header which is pulled on receive.
>> >
>> > Such a scenerio is a bug.
>> >
>> > Anything that pulls off a header should use a utility function such
>> > as skb_pull_rcsum() or skb_postpull_rcsum() to make sure this gets
>> > fixed up properly.
>>
>> skb_postpull_rcsum() does not change checksum-offset. vxlan receive
>> already calls this function.
>
> Then the bug is here.
>
> Otherwise we might have to 'fix' other places.
>
I posted a patch to fix skb_postpull_rcsum() to handle this case. But
that was not accepted.
https://patchwork.ozlabs.org/patch/512625/

And specific solution for skb_checksum_help() was suggested.

http://marc.info/?l=linux-netdev&m=144108078931774&w=2

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-22  2:49       ` Pravin Shelar
@ 2015-09-22  3:21         ` Eric Dumazet
  2015-09-22  4:44           ` Pravin Shelar
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2015-09-22  3:21 UTC (permalink / raw)
  To: Pravin Shelar; +Cc: David Miller, netdev, Tom Herbert

On Mon, 2015-09-21 at 19:49 -0700, Pravin Shelar wrote:
> On Mon, Sep 21, 2015 at 7:14 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > On Mon, 2015-09-21 at 18:04 -0700, Pravin Shelar wrote:
> >> On Mon, Sep 21, 2015 at 5:14 PM, David Miller <davem@davemloft.net> wrote:
> >> > From: Pravin B Shelar <pshelar@nicira.com>
> >> > Date: Sun, 20 Sep 2015 23:53:17 -0700
> >> >
> >> >> VXLAN device can receive skb with checksum partial. But the checksum
> >> >> offset could be in outer header which is pulled on receive.
> >> >
> >> > Such a scenerio is a bug.
> >> >
> >> > Anything that pulls off a header should use a utility function such
> >> > as skb_pull_rcsum() or skb_postpull_rcsum() to make sure this gets
> >> > fixed up properly.
> >>
> >> skb_postpull_rcsum() does not change checksum-offset. vxlan receive
> >> already calls this function.
> >
> > Then the bug is here.
> >
> > Otherwise we might have to 'fix' other places.
> >
> I posted a patch to fix skb_postpull_rcsum() to handle this case. But
> that was not accepted.
> https://patchwork.ozlabs.org/patch/512625/
> 
> And specific solution for skb_checksum_help() was suggested.
> 
> http://marc.info/?l=linux-netdev&m=144108078931774&w=2

If we pull a header where the csum is, then for sure CHECKSUM_PARTIAL
becomes buggy and void.

Tom was not advocating doing an operation (skb_postpull_rcsum()) leaving
skb in a wrong state.

We should fix callers that are pulling header in such a way.

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

* Re: [PATCH net] net: Handle negative checksum offset in skb-checksum-help
  2015-09-22  3:21         ` Eric Dumazet
@ 2015-09-22  4:44           ` Pravin Shelar
  0 siblings, 0 replies; 9+ messages in thread
From: Pravin Shelar @ 2015-09-22  4:44 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Tom Herbert

On Mon, Sep 21, 2015 at 8:21 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2015-09-21 at 19:49 -0700, Pravin Shelar wrote:
>> On Mon, Sep 21, 2015 at 7:14 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> > On Mon, 2015-09-21 at 18:04 -0700, Pravin Shelar wrote:
>> >> On Mon, Sep 21, 2015 at 5:14 PM, David Miller <davem@davemloft.net> wrote:
>> >> > From: Pravin B Shelar <pshelar@nicira.com>
>> >> > Date: Sun, 20 Sep 2015 23:53:17 -0700
>> >> >
>> >> >> VXLAN device can receive skb with checksum partial. But the checksum
>> >> >> offset could be in outer header which is pulled on receive.
>> >> >
>> >> > Such a scenerio is a bug.
>> >> >
>> >> > Anything that pulls off a header should use a utility function such
>> >> > as skb_pull_rcsum() or skb_postpull_rcsum() to make sure this gets
>> >> > fixed up properly.
>> >>
>> >> skb_postpull_rcsum() does not change checksum-offset. vxlan receive
>> >> already calls this function.
>> >
>> > Then the bug is here.
>> >
>> > Otherwise we might have to 'fix' other places.
>> >
>> I posted a patch to fix skb_postpull_rcsum() to handle this case. But
>> that was not accepted.
>> https://patchwork.ozlabs.org/patch/512625/
>>
>> And specific solution for skb_checksum_help() was suggested.
>>
>> http://marc.info/?l=linux-netdev&m=144108078931774&w=2
>
> If we pull a header where the csum is, then for sure CHECKSUM_PARTIAL
> becomes buggy and void.
>
> Tom was not advocating doing an operation (skb_postpull_rcsum()) leaving
> skb in a wrong state.
>
> We should fix callers that are pulling header in such a way.
>

So same as first patch but set skb checksum flag to CHECKSUM_NONE?

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

end of thread, other threads:[~2015-09-22  4:44 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-21  6:53 [PATCH net] net: Handle negative checksum offset in skb-checksum-help Pravin B Shelar
2015-09-21 15:47 ` Alexander Duyck
2015-09-21 17:45   ` Pravin Shelar
2015-09-22  0:14 ` David Miller
2015-09-22  1:04   ` Pravin Shelar
2015-09-22  2:14     ` Eric Dumazet
2015-09-22  2:49       ` Pravin Shelar
2015-09-22  3:21         ` Eric Dumazet
2015-09-22  4:44           ` Pravin Shelar

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