Skip to content

Commit a7fa12d

Browse files
Jakub Kicinskidavem330
authored andcommitted
net: netem: fix error path for corrupted GSO frames
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 <[email protected]> Reported-by: Dan Carpenter <[email protected]> Reported-by: Ben Hutchings <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bd310ac commit a7fa12d

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

net/sched/sch_netem.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
509509
if (skb->ip_summed == CHECKSUM_PARTIAL &&
510510
skb_checksum_help(skb)) {
511511
qdisc_drop(skb, sch, to_free);
512+
skb = NULL;
512513
goto finish_segs;
513514
}
514515

@@ -593,9 +594,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
593594
finish_segs:
594595
if (segs) {
595596
unsigned int len, last_len;
596-
int nb = 0;
597+
int nb;
597598

598-
len = skb->len;
599+
len = skb ? skb->len : 0;
600+
nb = skb ? 1 : 0;
599601

600602
while (segs) {
601603
skb2 = segs->next;
@@ -612,7 +614,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
612614
}
613615
segs = skb2;
614616
}
615-
qdisc_tree_reduce_backlog(sch, -nb, prev_len - len);
617+
/* Parent qdiscs accounted for 1 skb of size @prev_len */
618+
qdisc_tree_reduce_backlog(sch, -(nb - 1), -(len - prev_len));
616619
}
617620
return NET_XMIT_SUCCESS;
618621
}

0 commit comments

Comments
 (0)