* [PATCH v2] net: netem: fix skb length BUG_ON in __skb_to_sgvec
@ 2019-02-28 10:47 Sheng Lan
2019-02-28 17:03 ` Eric Dumazet
2019-02-28 18:32 ` David Miller
0 siblings, 2 replies; 3+ messages in thread
From: Sheng Lan @ 2019-02-28 10:47 UTC (permalink / raw)
To: eric.dumazet, stephen, davem
Cc: netdev, netem, xuhanbing, zhengshaoyu, jiqin.ji, liuzhiqiang26,
yuehaibing
From: Sheng Lan <lansheng@huawei.com>
It can be reproduced by following steps:
1. virtio_net NIC is configured with gso/tso on
2. configure nginx as http server with an index file bigger than 1M bytes
3. use tc netem to produce duplicate packets and delay:
tc qdisc add dev eth0 root netem delay 100ms 10ms 30% duplicate 90%
4. continually curl the nginx http server to get index file on client
5. BUG_ON is seen quickly
[10258690.371129] kernel BUG at net/core/skbuff.c:4028!
[10258690.371748] invalid opcode: 0000 [#1] SMP PTI
[10258690.372094] CPU: 5 PID: 0 Comm: swapper/5 Tainted: G W 5.0.0-rc6 #2
[10258690.372094] RSP: 0018:ffffa05797b43da0 EFLAGS: 00010202
[10258690.372094] RBP: 00000000000005ea R08: 0000000000000000 R09: 00000000000005ea
[10258690.372094] R10: ffffa0579334d800 R11: 00000000000002c0 R12: 0000000000000002
[10258690.372094] R13: 0000000000000000 R14: ffffa05793122900 R15: ffffa0578f7cb028
[10258690.372094] FS: 0000000000000000(0000) GS:ffffa05797b40000(0000) knlGS:0000000000000000
[10258690.372094] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[10258690.372094] CR2: 00007f1a6dc00868 CR3: 000000001000e000 CR4: 00000000000006e0
[10258690.372094] Call Trace:
[10258690.372094] <IRQ>
[10258690.372094] skb_to_sgvec+0x11/0x40
[10258690.372094] start_xmit+0x38c/0x520 [virtio_net]
[10258690.372094] dev_hard_start_xmit+0x9b/0x200
[10258690.372094] sch_direct_xmit+0xff/0x260
[10258690.372094] __qdisc_run+0x15e/0x4e0
[10258690.372094] net_tx_action+0x137/0x210
[10258690.372094] __do_softirq+0xd6/0x2a9
[10258690.372094] irq_exit+0xde/0xf0
[10258690.372094] smp_apic_timer_interrupt+0x74/0x140
[10258690.372094] apic_timer_interrupt+0xf/0x20
[10258690.372094] </IRQ>
In __skb_to_sgvec(), the skb->len is not equal to the sum of the skb's
linear data size and nonlinear data size, thus BUG_ON triggered.
Because the skb is cloned and a part of nonlinear data is split off.
Duplicate packet is cloned in netem_enqueue() and may be delayed
some time in qdisc. When qdisc len reached the limit and returns
NET_XMIT_DROP, the skb will be retransmit later in write queue.
the skb will be fragmented by tso_fragment(), the limit size
that depends on cwnd and mss decrease, the skb's nonlinear
data will be split off. The length of the skb cloned by netem
will not be updated. When we use virtio_net NIC and invoke skb_to_sgvec(),
the BUG_ON trigger.
To fix it, netem returns NET_XMIT_SUCCESS to upper stack
when it clones a duplicate packet.
Fixes: 35d889d1 ("sch_netem: fix skb leak in netem_enqueue()")
Signed-off-by: Sheng Lan <lansheng@huawei.com>
Reported-by: Qin Ji <jiqin.ji@huawei.com>
Suggested-by: Eric Dumazet <eric.dumazet@gmail.com>
---
Changes v1 to v2:
- Fix it by returning a proper value rather than copy one skb
net/sched/sch_netem.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 75046ec..cc9d813 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -447,6 +447,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
int nb = 0;
int count = 1;
int rc = NET_XMIT_SUCCESS;
+ int rc_drop = NET_XMIT_DROP;
/* Do not fool qdisc_drop_all() */
skb->prev = NULL;
@@ -486,6 +487,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
q->duplicate = 0;
rootq->enqueue(skb2, rootq, to_free);
q->duplicate = dupsave;
+ rc_drop = NET_XMIT_SUCCESS;
}
/*
@@ -498,7 +500,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (skb_is_gso(skb)) {
segs = netem_segment(skb, sch, to_free);
if (!segs)
- return NET_XMIT_DROP;
+ return rc_drop;
} else {
segs = skb;
}
@@ -521,8 +523,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
1<<(prandom_u32() % 8);
}
- if (unlikely(sch->q.qlen >= sch->limit))
- return qdisc_drop_all(skb, sch, to_free);
+ if (unlikely(sch->q.qlen >= sch->limit)) {
+ qdisc_drop_all(skb, sch, to_free);
+ return rc_drop;
+ }
qdisc_qstats_backlog_inc(sch, skb);
--
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH v2] net: netem: fix skb length BUG_ON in __skb_to_sgvec
2019-02-28 10:47 [PATCH v2] net: netem: fix skb length BUG_ON in __skb_to_sgvec Sheng Lan
@ 2019-02-28 17:03 ` Eric Dumazet
2019-02-28 18:32 ` David Miller
1 sibling, 0 replies; 3+ messages in thread
From: Eric Dumazet @ 2019-02-28 17:03 UTC (permalink / raw)
To: Sheng Lan, stephen, davem
Cc: netdev, netem, xuhanbing, zhengshaoyu, jiqin.ji, liuzhiqiang26,
yuehaibing
On 02/28/2019 02:47 AM, Sheng Lan wrote:
> From: Sheng Lan <lansheng@huawei.com>
>
> It can be reproduced by following steps:
> 1. virtio_net NIC is configured with gso/tso on
> 2. configure nginx as http server with an index file bigger than 1M bytes
> 3. use tc netem to produce duplicate packets and delay:
> tc qdisc add dev eth0 root netem delay 100ms 10ms 30% duplicate 90%
> 4. continually curl the nginx http server to get index file on client
> 5. BUG_ON is seen quickly
>
...
> To fix it, netem returns NET_XMIT_SUCCESS to upper stack
> when it clones a duplicate packet.
>
> Fixes: 35d889d1 ("sch_netem: fix skb leak in netem_enqueue()")
> Signed-off-by: Sheng Lan <lansheng@huawei.com>
> Reported-by: Qin Ji <jiqin.ji@huawei.com>
> Suggested-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> ---
Signed-off-by: Eric Dumazet <edumazet@google.com>
Thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH v2] net: netem: fix skb length BUG_ON in __skb_to_sgvec
2019-02-28 10:47 [PATCH v2] net: netem: fix skb length BUG_ON in __skb_to_sgvec Sheng Lan
2019-02-28 17:03 ` Eric Dumazet
@ 2019-02-28 18:32 ` David Miller
1 sibling, 0 replies; 3+ messages in thread
From: David Miller @ 2019-02-28 18:32 UTC (permalink / raw)
To: lansheng
Cc: eric.dumazet, stephen, netdev, netem, xuhanbing, zhengshaoyu,
jiqin.ji, liuzhiqiang26, yuehaibing
From: Sheng Lan <lansheng@huawei.com>
Date: Thu, 28 Feb 2019 18:47:58 +0800
> From: Sheng Lan <lansheng@huawei.com>
>
> It can be reproduced by following steps:
> 1. virtio_net NIC is configured with gso/tso on
> 2. configure nginx as http server with an index file bigger than 1M bytes
> 3. use tc netem to produce duplicate packets and delay:
> tc qdisc add dev eth0 root netem delay 100ms 10ms 30% duplicate 90%
> 4. continually curl the nginx http server to get index file on client
> 5. BUG_ON is seen quickly
...
> In __skb_to_sgvec(), the skb->len is not equal to the sum of the skb's
> linear data size and nonlinear data size, thus BUG_ON triggered.
> Because the skb is cloned and a part of nonlinear data is split off.
>
> Duplicate packet is cloned in netem_enqueue() and may be delayed
> some time in qdisc. When qdisc len reached the limit and returns
> NET_XMIT_DROP, the skb will be retransmit later in write queue.
> the skb will be fragmented by tso_fragment(), the limit size
> that depends on cwnd and mss decrease, the skb's nonlinear
> data will be split off. The length of the skb cloned by netem
> will not be updated. When we use virtio_net NIC and invoke skb_to_sgvec(),
> the BUG_ON trigger.
>
> To fix it, netem returns NET_XMIT_SUCCESS to upper stack
> when it clones a duplicate packet.
>
> Fixes: 35d889d1 ("sch_netem: fix skb leak in netem_enqueue()")
> Signed-off-by: Sheng Lan <lansheng@huawei.com>
> Reported-by: Qin Ji <jiqin.ji@huawei.com>
> Suggested-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-02-28 18:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-02-28 10:47 [PATCH v2] net: netem: fix skb length BUG_ON in __skb_to_sgvec Sheng Lan
2019-02-28 17:03 ` Eric Dumazet
2019-02-28 18:32 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox