]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.9.146/net-8139cp-fix-a-bug-triggered-by-changing-mtu-with-network-traffic.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.9.146 / net-8139cp-fix-a-bug-triggered-by-changing-mtu-with-network-traffic.patch
1 From foo@baz Thu Dec 13 12:16:38 CET 2018
2 From: Su Yanjun <suyj.fnst@cn.fujitsu.com>
3 Date: Mon, 3 Dec 2018 15:33:07 +0800
4 Subject: net: 8139cp: fix a BUG triggered by changing mtu with network traffic
5
6 From: Su Yanjun <suyj.fnst@cn.fujitsu.com>
7
8 [ Upstream commit a5d4a89245ead1f37ed135213653c5beebea4237 ]
9
10 When changing mtu many times with traffic, a bug is triggered:
11
12 [ 1035.684037] kernel BUG at lib/dynamic_queue_limits.c:26!
13 [ 1035.684042] invalid opcode: 0000 [#1] SMP
14 [ 1035.684049] Modules linked in: loop binfmt_misc 8139cp(OE) macsec
15 tcp_diag udp_diag inet_diag unix_diag af_packet_diag netlink_diag tcp_lp
16 fuse uinput xt_CHECKSUM iptable_mangle ipt_MASQUERADE
17 nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4
18 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT nf_reject_ipv4 tun
19 bridge stp llc ebtable_filter ebtables ip6table_filter devlink
20 ip6_tables iptable_filter sunrpc snd_hda_codec_generic snd_hda_intel
21 snd_hda_codec snd_hda_core snd_hwdep ppdev snd_seq iosf_mbi crc32_pclmul
22 parport_pc snd_seq_device ghash_clmulni_intel parport snd_pcm
23 aesni_intel joydev lrw snd_timer virtio_balloon sg gf128mul glue_helper
24 ablk_helper cryptd snd soundcore i2c_piix4 pcspkr ip_tables xfs
25 libcrc32c sr_mod sd_mod cdrom crc_t10dif crct10dif_generic ata_generic
26 [ 1035.684102] pata_acpi virtio_console qxl drm_kms_helper syscopyarea
27 sysfillrect sysimgblt floppy fb_sys_fops crct10dif_pclmul
28 crct10dif_common ttm crc32c_intel serio_raw ata_piix drm libata 8139too
29 virtio_pci drm_panel_orientation_quirks virtio_ring virtio mii dm_mirror
30 dm_region_hash dm_log dm_mod [last unloaded: 8139cp]
31 [ 1035.684132] CPU: 9 PID: 25140 Comm: if-mtu-change Kdump: loaded
32 Tainted: G OE ------------ T 3.10.0-957.el7.x86_64 #1
33 [ 1035.684134] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
34 [ 1035.684136] task: ffff8f59b1f5a080 ti: ffff8f5a2e32c000 task.ti:
35 ffff8f5a2e32c000
36 [ 1035.684149] RIP: 0010:[<ffffffffba3a40d0>] [<ffffffffba3a40d0>]
37 dql_completed+0x180/0x190
38 [ 1035.684162] RSP: 0000:ffff8f5a75483e50 EFLAGS: 00010093
39 [ 1035.684162] RAX: 00000000000000c2 RBX: ffff8f5a6f91c000 RCX:
40 0000000000000000
41 [ 1035.684162] RDX: 0000000000000000 RSI: 0000000000000184 RDI:
42 ffff8f599fea3ec0
43 [ 1035.684162] RBP: ffff8f5a75483ea8 R08: 00000000000000c2 R09:
44 0000000000000000
45 [ 1035.684162] R10: 00000000000616ef R11: ffff8f5a75483b56 R12:
46 ffff8f599fea3e00
47 [ 1035.684162] R13: 0000000000000001 R14: 0000000000000000 R15:
48 0000000000000184
49 [ 1035.684162] FS: 00007fa8434de740(0000) GS:ffff8f5a75480000(0000)
50 knlGS:0000000000000000
51 [ 1035.684162] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
52 [ 1035.684162] CR2: 00000000004305d0 CR3: 000000024eb66000 CR4:
53 00000000001406e0
54 [ 1035.684162] Call Trace:
55 [ 1035.684162] <IRQ>
56 [ 1035.684162] [<ffffffffc08cbaf8>] ? cp_interrupt+0x478/0x580 [8139cp]
57 [ 1035.684162] [<ffffffffba14a294>]
58 __handle_irq_event_percpu+0x44/0x1c0
59 [ 1035.684162] [<ffffffffba14a442>] handle_irq_event_percpu+0x32/0x80
60 [ 1035.684162] [<ffffffffba14a4cc>] handle_irq_event+0x3c/0x60
61 [ 1035.684162] [<ffffffffba14db29>] handle_fasteoi_irq+0x59/0x110
62 [ 1035.684162] [<ffffffffba02e554>] handle_irq+0xe4/0x1a0
63 [ 1035.684162] [<ffffffffba7795dd>] do_IRQ+0x4d/0xf0
64 [ 1035.684162] [<ffffffffba76b362>] common_interrupt+0x162/0x162
65 [ 1035.684162] <EOI>
66 [ 1035.684162] [<ffffffffba0c2ae4>] ? __wake_up_bit+0x24/0x70
67 [ 1035.684162] [<ffffffffba1e46f5>] ? do_set_pte+0xd5/0x120
68 [ 1035.684162] [<ffffffffba1b64fb>] unlock_page+0x2b/0x30
69 [ 1035.684162] [<ffffffffba1e4879>] do_read_fault.isra.61+0x139/0x1b0
70 [ 1035.684162] [<ffffffffba1e9134>] handle_pte_fault+0x2f4/0xd10
71 [ 1035.684162] [<ffffffffba1ebc6d>] handle_mm_fault+0x39d/0x9b0
72 [ 1035.684162] [<ffffffffba76f5e3>] __do_page_fault+0x203/0x500
73 [ 1035.684162] [<ffffffffba76f9c6>] trace_do_page_fault+0x56/0x150
74 [ 1035.684162] [<ffffffffba76ef42>] do_async_page_fault+0x22/0xf0
75 [ 1035.684162] [<ffffffffba76b788>] async_page_fault+0x28/0x30
76 [ 1035.684162] Code: 54 c7 47 54 ff ff ff ff 44 0f 49 ce 48 8b 35 48 2f
77 9c 00 48 89 77 58 e9 fe fe ff ff 0f 1f 80 00 00 00 00 41 89 d1 e9 ef fe
78 ff ff <0f> 0b 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 55 8d 42 ff 48
79 [ 1035.684162] RIP [<ffffffffba3a40d0>] dql_completed+0x180/0x190
80 [ 1035.684162] RSP <ffff8f5a75483e50>
81
82 It's not the same as in 7fe0ee09 patch described.
83 As 8139cp uses shared irq mode, other device irq will trigger
84 cp_interrupt to execute.
85
86 cp_change_mtu
87 -> cp_close
88 -> cp_open
89
90 In cp_close routine just before free_irq(), some interrupt may occur.
91 In my environment, cp_interrupt exectutes and IntrStatus is 0x4,
92 exactly TxOk. That will cause cp_tx to wake device queue.
93
94 As device queue is started, cp_start_xmit and cp_open will run at same
95 time which will cause kernel BUG.
96
97 For example:
98 [#] for tx descriptor
99
100 At start:
101
102 [#][#][#]
103 num_queued=3
104
105 After cp_init_hw->cp_start_hw->netdev_reset_queue:
106
107 [#][#][#]
108 num_queued=0
109
110 When 8139cp starts to work then cp_tx will check
111 num_queued mismatchs the complete_bytes.
112
113 The patch will check IntrMask before check IntrStatus in cp_interrupt.
114 When 8139cp interrupt is disabled, just return.
115
116 Signed-off-by: Su Yanjun <suyj.fnst@cn.fujitsu.com>
117 Signed-off-by: David S. Miller <davem@davemloft.net>
118 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
119 ---
120 drivers/net/ethernet/realtek/8139cp.c | 5 +++++
121 1 file changed, 5 insertions(+)
122
123 --- a/drivers/net/ethernet/realtek/8139cp.c
124 +++ b/drivers/net/ethernet/realtek/8139cp.c
125 @@ -578,6 +578,7 @@ static irqreturn_t cp_interrupt (int irq
126 struct cp_private *cp;
127 int handled = 0;
128 u16 status;
129 + u16 mask;
130
131 if (unlikely(dev == NULL))
132 return IRQ_NONE;
133 @@ -585,6 +586,10 @@ static irqreturn_t cp_interrupt (int irq
134
135 spin_lock(&cp->lock);
136
137 + mask = cpr16(IntrMask);
138 + if (!mask)
139 + goto out_unlock;
140 +
141 status = cpr16(IntrStatus);
142 if (!status || (status == 0xFFFF))
143 goto out_unlock;