linux/net/sched
Sheng Lan a550a01b8a net: netem: fix skb length BUG_ON in __skb_to_sgvec
commit 5845f70638 upstream.

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>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: netem_enqueue() may call qdisc_reshape_fail();
 keep returning NET_XMIT_SUCCESS if that succeeds]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
History 2019-05-02 21:42:02 +01:00
..
act_api.c net sched actions: decrement module reference count after table flush. 2017-06-05 21:17:17 +01:00
act_csum.c bpf: try harder on clones when writing into skb 2017-07-18 18:40:20 +01:00
act_gact.c net_sched: act: move tcf_hashinfo_init() into tcf_register_action() 2014-02-12 19:23:32 -05:00
act_ipt.c net: sched: act_ipt: check for underflow in __tcf_ipt_init() 2018-12-16 22:09:32 +00:00
act_mirred.c net_sched: act: move tcf_hashinfo_init() into tcf_register_action() 2014-02-12 19:23:32 -05:00
act_nat.c bpf: try harder on clones when writing into skb 2017-07-18 18:40:20 +01:00
act_pedit.c net/sched: pedit: make sure that offset is valid 2017-03-16 02:27:21 +00:00
act_police.c net_sched: act: move tcf_hashinfo_init() into tcf_register_action() 2014-02-12 19:23:32 -05:00
act_simple.c net/sched: act_simple: fix parsing of TCA_DEF_DATA 2018-11-20 18:05:12 +00:00
act_skbedit.c net_sched: act: move tcf_hashinfo_init() into tcf_register_action() 2014-02-12 19:23:32 -05:00
cls_api.c net sched filters: fix notification of filter delete with proper handle 2017-10-12 15:28:14 +01:00
cls_basic.c sched, cls: check if we could overwrite actions when changing a filter 2014-04-27 23:42:39 -04:00
cls_bpf.c net: cls_bpf: fix auto generation of per list handles 2015-03-20 09:36:24 +00:00
cls_cgroup.c sched, cls: check if we could overwrite actions when changing a filter 2014-04-27 23:42:39 -04:00
cls_flow.c sched, cls: check if we could overwrite actions when changing a filter 2014-04-27 23:42:39 -04:00
cls_fw.c sched, cls: check if we could overwrite actions when changing a filter 2014-04-27 23:42:39 -04:00
cls_route.c sched, cls: check if we could overwrite actions when changing a filter 2014-04-27 23:42:39 -04:00
cls_rsvp.c [NET_SCHED]: Remove unnecessary includes 2007-07-10 22:16:41 -07:00
cls_rsvp.h sched, cls: check if we could overwrite actions when changing a filter 2014-04-27 23:42:39 -04:00
cls_rsvp6.c [NET_SCHED]: Remove unnecessary includes 2007-07-10 22:16:41 -07:00
cls_tcindex.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2014-05-24 00:32:30 -04:00
cls_u32.c net_sched: avoid generating same handle for u32 filters 2014-07-20 20:49:17 -07:00
em_canid.c net: em_canid: Ematch rule to match CAN frames according to their identifiers 2012-07-04 13:07:05 +02:00
em_cmp.c net_sched: cleanups 2011-01-19 23:31:12 -08:00
em_ipset.c em_ipset: use dev_net() accessor 2013-10-18 16:23:06 -04:00
em_meta.c net/sched: em_meta: Fix 'meta vlan' to correctly recognize zero VID frames 2017-03-16 02:26:16 +00:00
em_nbyte.c net_sched: cleanups 2011-01-19 23:31:12 -08:00
em_text.c net_sched: cleanups 2011-01-19 23:31:12 -08:00
em_u32.c net_sched: cleanups 2011-01-19 23:31:12 -08:00
ematch.c ematch: Fix auto-loading of ematch modules. 2015-03-12 16:27:28 +00:00
Kconfig net: pkt_sched: PIE AQM scheme 2014-01-06 15:13:01 -05:00
Makefile net: pkt_sched: PIE AQM scheme 2014-01-06 15:13:01 -05:00
sch_api.c net_sched: fix error recovery at qdisc creation 2017-11-11 13:33:34 +00:00
sch_atm.c net_sched: return nla_nest_end() instead of skb->len 2014-03-13 15:39:20 -04:00
sch_blackhole.c pkt_sched: Add qdisc->ops->peek() implementation. 2008-10-31 00:45:55 -07:00
sch_cbq.c sch_cbq: fix null pointer dereferences on init failure 2017-11-11 13:33:35 +00:00
sch_choke.c net_sched: red: Avoid illegal values 2018-03-03 15:51:45 +00:00
sch_codel.c net_sched: update hierarchical backlog too 2016-08-22 22:38:15 +01:00
sch_drr.c net_sched: update hierarchical backlog too 2016-08-22 22:38:15 +01:00
sch_dsmark.c sch_dsmark: fix invalid skb_cow() usage 2017-07-18 18:40:20 +01:00
sch_fifo.c net_sched: fix pfifo_head_drop behavior vs backlog 2016-08-22 22:38:15 +01:00
sch_fq.c net_sched: fq: take care of throttled flows before reuse 2018-10-21 08:45:52 +01:00
sch_fq_codel.c sch_fq_codel: avoid double free on init failure 2017-11-11 13:33:35 +00:00
sch_generic.c net_sched: always reset qdisc backlog in qdisc_reset() 2018-01-01 20:51:36 +00:00
sch_gred.c net: sched: gred: pass the right attribute to gred_change_table_def() 2019-02-11 17:53:42 +00:00
sch_hfsc.c sch_hfsc: fix null pointer deref and double free on init failure 2017-11-11 13:33:35 +00:00
sch_hhf.c sch_hhf: fix null pointer dereference on init failure 2017-11-11 13:33:35 +00:00
sch_htb.c sch_htb: fix crash on init failure 2017-11-11 13:33:34 +00:00
sch_ingress.c net_sched: return nla_nest_end() instead of skb->len 2014-03-13 15:39:20 -04:00
sch_mq.c net_sched: fix error recovery at qdisc creation 2017-11-11 13:33:34 +00:00
sch_mqprio.c net_sched: fix error recovery at qdisc creation 2017-11-11 13:33:34 +00:00
sch_multiq.c sch_multiq: fix double free on init failure 2017-11-11 13:33:34 +00:00
sch_netem.c net: netem: fix skb length BUG_ON in __skb_to_sgvec 2019-05-02 21:42:02 +01:00
sch_pie.c net_sched: update hierarchical backlog too 2016-08-22 22:38:15 +01:00
sch_plug.c net_sched: sch_plug: plug_qdisc_ops is static 2012-02-13 16:04:40 -05:00
sch_prio.c net_sched: update hierarchical backlog too 2016-08-22 22:38:15 +01:00
sch_qfq.c net_sched: update hierarchical backlog too 2016-08-22 22:38:15 +01:00
sch_red.c net_sched: red: Avoid illegal values 2018-03-03 15:51:45 +00:00
sch_sfb.c net_sched: update hierarchical backlog too 2016-08-22 22:38:15 +01:00
sch_sfq.c net_sched: red: Avoid illegal values 2018-03-03 15:51:45 +00:00
sch_tbf.c sch_tbf: fix two null pointer dereferences on init failure 2017-11-11 13:33:36 +00:00
sch_teql.c sch_teql: Convert over to dev_neigh_lookup_skb(). 2012-07-05 01:09:06 -07:00