lkml.org 
[lkml]   [2020]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 327/343] net: netem: fix error path for corrupted GSO frames
    Date
    From: Jakub Kicinski <jakub.kicinski@netronome.com>

    [ Upstream commit a7fa12d15855904aff1716e1fc723c03ba38c5cc ]

    To corrupt a GSO frame we first perform segmentation. We then
    proceed using the first segment instead of the full GSO skb and
    requeue the rest of the segments as separate packets.

    If there are any issues with processing the first segment we
    still want to process the rest, therefore we jump to the
    finish_segs label.

    Commit 177b8007463c ("net: netem: fix backlog accounting for
    corrupted GSO frames") started using the pointer to the first
    segment in the "rest of segments processing", but as mentioned
    above the first segment may had already been freed at this point.

    Backlog corrections for parent qdiscs have to be adjusted.

    Fixes: 177b8007463c ("net: netem: fix backlog accounting for corrupted GSO frames")
    Reported-by: kbuild test robot <lkp@intel.com>
    Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
    Reported-by: Ben Hutchings <ben@decadent.org.uk>
    Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
    Reviewed-by: Simon Horman <simon.horman@netronome.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/sched/sch_netem.c | 9 ++++++---
    1 file changed, 6 insertions(+), 3 deletions(-)

    diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
    index ede0a24e67eb8..64c3cfa357363 100644
    --- a/net/sched/sch_netem.c
    +++ b/net/sched/sch_netem.c
    @@ -504,6 +504,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
    if (skb->ip_summed == CHECKSUM_PARTIAL &&
    skb_checksum_help(skb)) {
    qdisc_drop(skb, sch, to_free);
    + skb = NULL;
    goto finish_segs;
    }

    @@ -580,9 +581,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
    finish_segs:
    if (segs) {
    unsigned int len, last_len;
    - int nb = 0;
    + int nb;

    - len = skb->len;
    + len = skb ? skb->len : 0;
    + nb = skb ? 1 : 0;

    while (segs) {
    skb2 = segs->next;
    @@ -599,7 +601,8 @@ finish_segs:
    }
    segs = skb2;
    }
    - qdisc_tree_reduce_backlog(sch, -nb, prev_len - len);
    + /* Parent qdiscs accounted for 1 skb of size @prev_len */
    + qdisc_tree_reduce_backlog(sch, -(nb - 1), -(len - prev_len));
    }
    return NET_XMIT_SUCCESS;
    }
    --
    2.20.1


    \
     
     \ /
      Last update: 2020-01-24 11:07    [W:2.215 / U:0.100 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site