[PATCH net-next v3 4/5] net/sched: netem: handle multi-segment skb in corruption
From: Stephen Hemminger
Date: Tue May 05 2026 - 13:42:19 EST
The packet corruption code only flipped bits in the linear
header portion of the skb, skipping corruption when
skb_headlen() was zero.
Linearize the whole skb if necessary before corruption.
That step also makes calling skb_unshare() unnecessary.
Extends d64cb81dcbd5 ("net/sched: sch_netem: fix out-of-bounds access
in packet corruption") with a more general solution.
Signed-off-by: Stephen Hemminger <stephen@xxxxxxxxxxxxxxxxxx>
---
net/sched/sch_netem.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 53bdfa77ee2d..020dbfb6e4a7 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -508,21 +508,17 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
qdisc_skb_cb(skb)->pkt_len = skb->len;
}
- skb = skb_unshare(skb, GFP_ATOMIC);
- if (unlikely(!skb)) {
- qdisc_qstats_drop(sch);
- goto finish_segs;
- }
- if (skb->ip_summed == CHECKSUM_PARTIAL &&
- skb_checksum_help(skb)) {
+ if (skb_linearize(skb) ||
+ (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))) {
qdisc_drop(skb, sch, to_free);
skb = NULL;
goto finish_segs;
}
- if (skb_headlen(skb))
- skb->data[get_random_u32_below(skb_headlen(skb))] ^=
- 1 << get_random_u32_below(8);
+ if (skb->len) {
+ u32 offset = get_random_u32_below(skb->len);
+ skb->data[offset] ^= 1 << get_random_u32_below(8);
+ }
}
if (unlikely(sch->q.qlen >= sch->limit)) {
--
2.53.0