Skip to content

Commit

Permalink
net: netem: fix error path for corrupted GSO frames
Browse files Browse the repository at this point in the history
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 177b800 ("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: 177b800 ("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>
  • Loading branch information
Jakub Kicinski authored and David S. Miller committed Oct 19, 2019
1 parent bd310ac commit a7fa12d
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions net/sched/sch_netem.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,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;
}

Expand Down Expand Up @@ -593,9 +594,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;
Expand All @@ -612,7 +614,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
}
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;
}
Expand Down

0 comments on commit a7fa12d

Please sign in to comment.