diff mbox

Kernel crash - Large UDP packet over IPv6 over UFO-enabled device with TBF qdisc (No corking needed)

Message ID 20131103033207.GF30284@order.stressinduktion.org
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Hannes Frederic Sowa Nov. 3, 2013, 3:32 a.m. UTC
Hi Pravin,

Could you have a look at this bug?

On Tue, Oct 29, 2013 at 10:30:34AM -0400, Saran Neti wrote:
> Sending a UDP packet of size larger than MTU over IPv6 over a device that has UFO enabled, and that uses the TBF qdisc causes the kernel to crash. Unlike CVE-2013-4387, this does not require a corked socket and can be remotely triggered by a tftp request. 

It seems it got introduced with this commit:

commit 1e2bd517c108816220f262d7954b697af03b5f9c
Author: Pravin B Shelar <pshelar@nicira.com>
Date:   Thu May 30 06:45:27 2013 +0000

    udp6: Fix udp fragmentation for tunnel traffic.
    
    udp6 over GRE tunnel does not work after to GRE tso changes. GRE
    tso handler passes inner packet but keeps track of outer header
    start in SKB_GSO_CB(skb)->mac_offset.  udp6 fragment need to
    take care of outer header, which start at the mac_offset, while
    adding fragment header.
    This bug is introduced by commit 68c3316311 (GRE: Add TCP
    segmentation offload for GRE).

It seems we don't check for the correct headroom. ->data currently points
to transport_header, so use of skb_headlen seems wrong.

Following diff fixes the problem:



Greetings,

  Hannes

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -90,7 +90,7 @@  static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 
                /* Check if there is enough headroom to insert fragment header. */
                tnl_hlen = skb_tnl_header_len(skb);
-               if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) {
+               if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) {
                        if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
                                goto out;
                }