[lkml]   [2022]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    Subject[PATCH 5.15 159/262] net: fix up skbs delta_truesize in UDP GRO frag_list
    From: lena wang <>

    commit 224102de2ff105a2c05695e66a08f4b5b6b2d19c upstream.

    The truesize for a UDP GRO packet is added by main skb and skbs in main
    skb's frag_list:
    p->truesize += skb->truesize;

    The commit 53475c5dd856 ("net: fix use-after-free when UDP GRO with
    shared fraglist") introduced a truesize increase for frag_list skbs.
    When uncloning skb, it will call pskb_expand_head and trusesize for
    frag_list skbs may increase. This can occur when allocators uses
    __netdev_alloc_skb and not jump into __alloc_skb. This flow does not
    use ksize(len) to calculate truesize while pskb_expand_head uses.
    err = skb_unclone(nskb, GFP_ATOMIC);
    if (!skb->sk || skb->destructor == sock_edemux)
    skb->truesize += size - osize;

    If we uses increased truesize adding as delta_truesize, it will be
    larger than before and even larger than previous total truesize value
    if skbs in frag_list are abundant. The main skb truesize will become
    smaller and even a minus value or a huge value for an unsigned int
    parameter. Then the following memory check will drop this abnormal skb.

    To avoid this error we should use the original truesize to segment the
    main skb.

    Fixes: 53475c5dd856 ("net: fix use-after-free when UDP GRO with shared fraglist")
    Signed-off-by: lena wang <>
    Acked-by: Paolo Abeni <>
    Reviewed-by: Eric Dumazet <>
    Signed-off-by: Jakub Kicinski <>
    Signed-off-by: Greg Kroah-Hartman <>
    net/core/skbuff.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    --- a/net/core/skbuff.c
    +++ b/net/core/skbuff.c
    @@ -3853,6 +3853,7 @@ struct sk_buff *skb_segment_list(struct
    list_skb = list_skb->next;

    err = 0;
    + delta_truesize += nskb->truesize;
    if (skb_shared(nskb)) {
    tmp = skb_clone(nskb, GFP_ATOMIC);
    if (tmp) {
    @@ -3877,7 +3878,6 @@ struct sk_buff *skb_segment_list(struct
    tail = nskb;

    delta_len += nskb->len;
    - delta_truesize += nskb->truesize;

    skb_push(nskb, -skb_network_offset(nskb) + offset);

     \ /
      Last update: 2022-03-07 11:08    [W:2.233 / U:1.840 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site