lkml.org 
[lkml]   [2018]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 253/410] udplite: fix partial checksum initialization
    3.16.57-rc1 review patch.  If anyone has any objections, please let me know.

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

    From: Alexey Kodanev <alexey.kodanev@oracle.com>

    commit 15f35d49c93f4fa9875235e7bf3e3783d2dd7a1b upstream.

    Since UDP-Lite is always using checksum, the following path is
    triggered when calculating pseudo header for it:

    udp4_csum_init() or udp6_csum_init()
    skb_checksum_init_zero_check()
    __skb_checksum_validate_complete()

    The problem can appear if skb->len is less than CHECKSUM_BREAK. In
    this particular case __skb_checksum_validate_complete() also invokes
    __skb_checksum_complete(skb). If UDP-Lite is using partial checksum
    that covers only part of a packet, the function will return bad
    checksum and the packet will be dropped.

    It can be fixed if we skip skb_checksum_init_zero_check() and only
    set the required pseudo header checksum for UDP-Lite with partial
    checksum before udp4_csum_init()/udp6_csum_init() functions return.

    Fixes: ed70fcfcee95 ("net: Call skb_checksum_init in IPv4")
    Fixes: e4f45b7f40bd ("net: Call skb_checksum_init in IPv6")
    Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    include/net/udplite.h | 1 +
    net/ipv4/udp.c | 5 +++++
    net/ipv6/ip6_checksum.c | 5 +++++
    3 files changed, 11 insertions(+)

    --- a/include/net/udplite.h
    +++ b/include/net/udplite.h
    @@ -61,6 +61,7 @@ static inline int udplite_checksum_init(
    UDP_SKB_CB(skb)->cscov = cscov;
    if (skb->ip_summed == CHECKSUM_COMPLETE)
    skb->ip_summed = CHECKSUM_NONE;
    + skb->csum_valid = 0;
    }

    return 0;
    --- a/net/ipv4/udp.c
    +++ b/net/ipv4/udp.c
    @@ -1729,6 +1729,11 @@ static inline int udp4_csum_init(struct
    err = udplite_checksum_init(skb, uh);
    if (err)
    return err;
    +
    + if (UDP_SKB_CB(skb)->partial_cov) {
    + skb->csum = inet_compute_pseudo(skb, proto);
    + return 0;
    + }
    }

    return skb_checksum_init_zero_check(skb, proto, uh->check,
    --- a/net/ipv6/ip6_checksum.c
    +++ b/net/ipv6/ip6_checksum.c
    @@ -73,6 +73,11 @@ int udp6_csum_init(struct sk_buff *skb,
    err = udplite_checksum_init(skb, uh);
    if (err)
    return err;
    +
    + if (UDP_SKB_CB(skb)->partial_cov) {
    + skb->csum = ip6_compute_pseudo(skb, proto);
    + return 0;
    + }
    }

    /* To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels)
    \
     
     \ /
      Last update: 2018-06-07 17:12    [W:4.767 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site