lkml.org 
[lkml]   [2013]   [Nov]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 31/87] inet: fix possible memory corruption with UDP_CORK and UFO
    3.2.53-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Hannes Frederic Sowa <hannes@stressinduktion.org>

    [ This is a simplified -stable version of a set of upstream commits. ]

    This is a replacement patch only for stable which does fix the problems
    handled by the following two commits in -net:

    "ip_output: do skb ufo init for peeked non ufo skb as well" (e93b7d748be887cd7639b113ba7d7ef792a7efb9)
    "ip6_output: do skb ufo init for peeked non ufo skb as well" (c547dbf55d5f8cf615ccc0e7265e98db27d3fb8b)

    Three frames are written on a corked udp socket for which the output
    netdevice has UFO enabled. If the first and third frame are smaller than
    the mtu and the second one is bigger, we enqueue the second frame with
    skb_append_datato_frags without initializing the gso fields. This leads
    to the third frame appended regulary and thus constructing an invalid skb.

    This fixes the problem by always using skb_append_datato_frags as soon
    as the first frag got enqueued to the skb without marking the packet
    as SKB_GSO_UDP.

    The problem with only two frames for ipv6 was fixed by "ipv6: udp
    packets following an UFO enqueued packet need also be handled by UFO"
    (2811ebac2521ceac84f2bdae402455baa6a7fb47).

    Cc: Jiri Pirko <jiri@resnulli.us>
    Cc: Eric Dumazet <eric.dumazet@gmail.com>
    Cc: David Miller <davem@davemloft.net>
    Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    include/linux/skbuff.h | 5 +++++
    net/ipv4/ip_output.c | 2 +-
    net/ipv6/ip6_output.c | 2 +-
    3 files changed, 7 insertions(+), 2 deletions(-)

    --- a/include/linux/skbuff.h
    +++ b/include/linux/skbuff.h
    @@ -1167,6 +1167,11 @@ static inline int skb_pagelen(const stru
    return len + skb_headlen(skb);
    }

    +static inline bool skb_has_frags(const struct sk_buff *skb)
    +{
    + return skb_shinfo(skb)->nr_frags;
    +}
    +
    /**
    * __skb_fill_page_desc - initialise a paged fragment in an skb
    * @skb: buffer containing fragment to be initialised
    --- a/net/ipv4/ip_output.c
    +++ b/net/ipv4/ip_output.c
    @@ -833,7 +833,7 @@ static int __ip_append_data(struct sock
    csummode = CHECKSUM_PARTIAL;

    cork->length += length;
    - if (((length > mtu) || (skb && skb_is_gso(skb))) &&
    + if (((length > mtu) || (skb && skb_has_frags(skb))) &&
    (sk->sk_protocol == IPPROTO_UDP) &&
    (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) {
    err = ip_ufo_append_data(sk, queue, getfrag, from, length,
    --- a/net/ipv6/ip6_output.c
    +++ b/net/ipv6/ip6_output.c
    @@ -1342,7 +1342,7 @@ int ip6_append_data(struct sock *sk, int
    skb = skb_peek_tail(&sk->sk_write_queue);
    cork->length += length;
    if (((length > mtu) ||
    - (skb && skb_is_gso(skb))) &&
    + (skb && skb_has_frags(skb))) &&
    (sk->sk_protocol == IPPROTO_UDP) &&
    (rt->dst.dev->features & NETIF_F_UFO)) {
    err = ip6_ufo_append_data(sk, getfrag, from, length,


    \
     
     \ /
      Last update: 2013-11-25 16:41    [W:4.396 / U:0.268 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site