From: Greg Kroah-Hartman Date: Fri, 31 May 2019 23:38:12 +0000 (-0700) Subject: 4.4-stable patches X-Git-Tag: v5.1.7~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=51324e95327f5e4e2d6e7006ee82a171866ab44a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: bnxt_en-fix-aggregation-buffer-leak-under-oom-condition.patch ipv6-consider-sk_bound_dev_if-when-binding-a-raw-socket-to-an-address.patch llc-fix-skb-leak-in-llc_build_and_send_ui_pkt.patch net-gro-fix-use-after-free-read-in-napi_gro_frags.patch net-mvpp2-fix-bad-mvpp2_txq_sched_token_cntr_reg-queue-value.patch net-stmmac-fix-reset-gpio-free-missing.patch tipc-avoid-copying-bytes-beyond-the-supplied-data.patch usbnet-fix-kernel-crash-after-disconnect.patch --- diff --git a/queue-4.4/bnxt_en-fix-aggregation-buffer-leak-under-oom-condition.patch b/queue-4.4/bnxt_en-fix-aggregation-buffer-leak-under-oom-condition.patch new file mode 100644 index 00000000000..3830c1e4ce5 --- /dev/null +++ b/queue-4.4/bnxt_en-fix-aggregation-buffer-leak-under-oom-condition.patch @@ -0,0 +1,37 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Michael Chan +Date: Wed, 22 May 2019 19:12:54 -0400 +Subject: bnxt_en: Fix aggregation buffer leak under OOM condition. + +From: Michael Chan + +[ Upstream commit 296d5b54163964b7ae536b8b57dfbd21d4e868e1 ] + +For every RX packet, the driver replenishes all buffers used for that +packet and puts them back into the RX ring and RX aggregation ring. +In one code path where the RX packet has one RX buffer and one or more +aggregation buffers, we missed recycling the aggregation buffer(s) if +we are unable to allocate a new SKB buffer. This leads to the +aggregation ring slowly running out of buffers over time. Fix it +by properly recycling the aggregation buffers. + +Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") +Reported-by: Rakesh Hemnani +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -1140,6 +1140,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, + skb = bnxt_copy_skb(bnapi, data, len, dma_addr); + bnxt_reuse_rx_data(rxr, cons, data); + if (!skb) { ++ if (agg_bufs) ++ bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs); + rc = -ENOMEM; + goto next_rx; + } diff --git a/queue-4.4/ipv6-consider-sk_bound_dev_if-when-binding-a-raw-socket-to-an-address.patch b/queue-4.4/ipv6-consider-sk_bound_dev_if-when-binding-a-raw-socket-to-an-address.patch new file mode 100644 index 00000000000..c84c6579736 --- /dev/null +++ b/queue-4.4/ipv6-consider-sk_bound_dev_if-when-binding-a-raw-socket-to-an-address.patch @@ -0,0 +1,37 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Mike Manning +Date: Mon, 20 May 2019 19:57:17 +0100 +Subject: ipv6: Consider sk_bound_dev_if when binding a raw socket to an address + +From: Mike Manning + +[ Upstream commit 72f7cfab6f93a8ea825fab8ccfb016d064269f7f ] + +IPv6 does not consider if the socket is bound to a device when binding +to an address. The result is that a socket can be bound to eth0 and +then bound to the address of eth1. If the device is a VRF, the result +is that a socket can only be bound to an address in the default VRF. + +Resolve by considering the device if sk_bound_dev_if is set. + +Signed-off-by: Mike Manning +Reviewed-by: David Ahern +Tested-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/raw.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -283,7 +283,9 @@ static int rawv6_bind(struct sock *sk, s + /* Binding to link-local address requires an interface */ + if (!sk->sk_bound_dev_if) + goto out_unlock; ++ } + ++ if (sk->sk_bound_dev_if) { + err = -ENODEV; + dev = dev_get_by_index_rcu(sock_net(sk), + sk->sk_bound_dev_if); diff --git a/queue-4.4/llc-fix-skb-leak-in-llc_build_and_send_ui_pkt.patch b/queue-4.4/llc-fix-skb-leak-in-llc_build_and_send_ui_pkt.patch new file mode 100644 index 00000000000..f3b5b019d29 --- /dev/null +++ b/queue-4.4/llc-fix-skb-leak-in-llc_build_and_send_ui_pkt.patch @@ -0,0 +1,84 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Eric Dumazet +Date: Mon, 27 May 2019 17:35:52 -0700 +Subject: llc: fix skb leak in llc_build_and_send_ui_pkt() + +From: Eric Dumazet + +[ Upstream commit 8fb44d60d4142cd2a440620cd291d346e23c131e ] + +If llc_mac_hdr_init() returns an error, we must drop the skb +since no llc_build_and_send_ui_pkt() caller will take care of this. + +BUG: memory leak +unreferenced object 0xffff8881202b6800 (size 2048): + comm "syz-executor907", pid 7074, jiffies 4294943781 (age 8.590s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 1a 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace: + [<00000000e25b5abe>] kmemleak_alloc_recursive include/linux/kmemleak.h:55 [inline] + [<00000000e25b5abe>] slab_post_alloc_hook mm/slab.h:439 [inline] + [<00000000e25b5abe>] slab_alloc mm/slab.c:3326 [inline] + [<00000000e25b5abe>] __do_kmalloc mm/slab.c:3658 [inline] + [<00000000e25b5abe>] __kmalloc+0x161/0x2c0 mm/slab.c:3669 + [<00000000a1ae188a>] kmalloc include/linux/slab.h:552 [inline] + [<00000000a1ae188a>] sk_prot_alloc+0xd6/0x170 net/core/sock.c:1608 + [<00000000ded25bbe>] sk_alloc+0x35/0x2f0 net/core/sock.c:1662 + [<000000002ecae075>] llc_sk_alloc+0x35/0x170 net/llc/llc_conn.c:950 + [<00000000551f7c47>] llc_ui_create+0x7b/0x140 net/llc/af_llc.c:173 + [<0000000029027f0e>] __sock_create+0x164/0x250 net/socket.c:1430 + [<000000008bdec225>] sock_create net/socket.c:1481 [inline] + [<000000008bdec225>] __sys_socket+0x69/0x110 net/socket.c:1523 + [<00000000b6439228>] __do_sys_socket net/socket.c:1532 [inline] + [<00000000b6439228>] __se_sys_socket net/socket.c:1530 [inline] + [<00000000b6439228>] __x64_sys_socket+0x1e/0x30 net/socket.c:1530 + [<00000000cec820c1>] do_syscall_64+0x76/0x1a0 arch/x86/entry/common.c:301 + [<000000000c32554f>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +BUG: memory leak +unreferenced object 0xffff88811d750d00 (size 224): + comm "syz-executor907", pid 7074, jiffies 4294943781 (age 8.600s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 f0 0c 24 81 88 ff ff 00 68 2b 20 81 88 ff ff ...$.....h+ .... + backtrace: + [<0000000053026172>] kmemleak_alloc_recursive include/linux/kmemleak.h:55 [inline] + [<0000000053026172>] slab_post_alloc_hook mm/slab.h:439 [inline] + [<0000000053026172>] slab_alloc_node mm/slab.c:3269 [inline] + [<0000000053026172>] kmem_cache_alloc_node+0x153/0x2a0 mm/slab.c:3579 + [<00000000fa8f3c30>] __alloc_skb+0x6e/0x210 net/core/skbuff.c:198 + [<00000000d96fdafb>] alloc_skb include/linux/skbuff.h:1058 [inline] + [<00000000d96fdafb>] alloc_skb_with_frags+0x5f/0x250 net/core/skbuff.c:5327 + [<000000000a34a2e7>] sock_alloc_send_pskb+0x269/0x2a0 net/core/sock.c:2225 + [<00000000ee39999b>] sock_alloc_send_skb+0x32/0x40 net/core/sock.c:2242 + [<00000000e034d810>] llc_ui_sendmsg+0x10a/0x540 net/llc/af_llc.c:933 + [<00000000c0bc8445>] sock_sendmsg_nosec net/socket.c:652 [inline] + [<00000000c0bc8445>] sock_sendmsg+0x54/0x70 net/socket.c:671 + [<000000003b687167>] __sys_sendto+0x148/0x1f0 net/socket.c:1964 + [<00000000922d78d9>] __do_sys_sendto net/socket.c:1976 [inline] + [<00000000922d78d9>] __se_sys_sendto net/socket.c:1972 [inline] + [<00000000922d78d9>] __x64_sys_sendto+0x2a/0x30 net/socket.c:1972 + [<00000000cec820c1>] do_syscall_64+0x76/0x1a0 arch/x86/entry/common.c:301 + [<000000000c32554f>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/llc/llc_output.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/llc/llc_output.c ++++ b/net/llc/llc_output.c +@@ -72,6 +72,8 @@ int llc_build_and_send_ui_pkt(struct llc + rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac); + if (likely(!rc)) + rc = dev_queue_xmit(skb); ++ else ++ kfree_skb(skb); + return rc; + } + diff --git a/queue-4.4/net-gro-fix-use-after-free-read-in-napi_gro_frags.patch b/queue-4.4/net-gro-fix-use-after-free-read-in-napi_gro_frags.patch new file mode 100644 index 00000000000..5d58aa9818e --- /dev/null +++ b/queue-4.4/net-gro-fix-use-after-free-read-in-napi_gro_frags.patch @@ -0,0 +1,69 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Eric Dumazet +Date: Wed, 29 May 2019 15:36:10 -0700 +Subject: net-gro: fix use-after-free read in napi_gro_frags() + +From: Eric Dumazet + +[ Upstream commit a4270d6795b0580287453ea55974d948393e66ef ] + +If a network driver provides to napi_gro_frags() an +skb with a page fragment of exactly 14 bytes, the call +to gro_pull_from_frag0() will 'consume' the fragment +by calling skb_frag_unref(skb, 0), and the page might +be freed and reused. + +Reading eth->h_proto at the end of napi_frags_skb() might +read mangled data, or crash under specific debugging features. + +BUG: KASAN: use-after-free in napi_frags_skb net/core/dev.c:5833 [inline] +BUG: KASAN: use-after-free in napi_gro_frags+0xc6f/0xd10 net/core/dev.c:5841 +Read of size 2 at addr ffff88809366840c by task syz-executor599/8957 + +CPU: 1 PID: 8957 Comm: syz-executor599 Not tainted 5.2.0-rc1+ #32 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x172/0x1f0 lib/dump_stack.c:113 + print_address_description.cold+0x7c/0x20d mm/kasan/report.c:188 + __kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317 + kasan_report+0x12/0x20 mm/kasan/common.c:614 + __asan_report_load_n_noabort+0xf/0x20 mm/kasan/generic_report.c:142 + napi_frags_skb net/core/dev.c:5833 [inline] + napi_gro_frags+0xc6f/0xd10 net/core/dev.c:5841 + tun_get_user+0x2f3c/0x3ff0 drivers/net/tun.c:1991 + tun_chr_write_iter+0xbd/0x156 drivers/net/tun.c:2037 + call_write_iter include/linux/fs.h:1872 [inline] + do_iter_readv_writev+0x5f8/0x8f0 fs/read_write.c:693 + do_iter_write fs/read_write.c:970 [inline] + do_iter_write+0x184/0x610 fs/read_write.c:951 + vfs_writev+0x1b3/0x2f0 fs/read_write.c:1015 + do_writev+0x15b/0x330 fs/read_write.c:1058 + +Fixes: a50e233c50db ("net-gro: restore frag0 optimization") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4550,7 +4550,6 @@ static struct sk_buff *napi_frags_skb(st + skb_reset_mac_header(skb); + skb_gro_reset_offset(skb); + +- eth = skb_gro_header_fast(skb, 0); + if (unlikely(skb_gro_header_hard(skb, hlen))) { + eth = skb_gro_header_slow(skb, hlen, 0); + if (unlikely(!eth)) { +@@ -4558,6 +4557,7 @@ static struct sk_buff *napi_frags_skb(st + return NULL; + } + } else { ++ eth = (const struct ethhdr *)skb->data; + gro_pull_from_frag0(skb, hlen); + NAPI_GRO_CB(skb)->frag0 += hlen; + NAPI_GRO_CB(skb)->frag0_len -= hlen; diff --git a/queue-4.4/net-mvpp2-fix-bad-mvpp2_txq_sched_token_cntr_reg-queue-value.patch b/queue-4.4/net-mvpp2-fix-bad-mvpp2_txq_sched_token_cntr_reg-queue-value.patch new file mode 100644 index 00000000000..73ab09844e9 --- /dev/null +++ b/queue-4.4/net-mvpp2-fix-bad-mvpp2_txq_sched_token_cntr_reg-queue-value.patch @@ -0,0 +1,57 @@ +From foo@baz Fri 31 May 2019 03:24:14 PM PDT +From: Antoine Tenart +Date: Wed, 29 May 2019 15:59:48 +0200 +Subject: net: mvpp2: fix bad MVPP2_TXQ_SCHED_TOKEN_CNTR_REG queue value + +From: Antoine Tenart + +[ Upstream commit 21808437214637952b61beaba6034d97880fbeb3 ] + +MVPP2_TXQ_SCHED_TOKEN_CNTR_REG() expects the logical queue id but +the current code is passing the global tx queue offset, so it ends +up writing to unknown registers (between 0x8280 and 0x82fc, which +seemed to be unused by the hardware). This fixes the issue by using +the logical queue id instead. + +Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit") +Signed-off-by: Antoine Tenart +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/marvell/mvpp2.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvpp2.c ++++ b/drivers/net/ethernet/marvell/mvpp2.c +@@ -3940,7 +3940,7 @@ static inline void mvpp2_gmac_max_rx_siz + /* Set defaults to the MVPP2 port */ + static void mvpp2_defaults_set(struct mvpp2_port *port) + { +- int tx_port_num, val, queue, ptxq, lrxq; ++ int tx_port_num, val, queue, lrxq; + + /* Configure port to loopback if needed */ + if (port->flags & MVPP2_F_LOOPBACK) +@@ -3960,11 +3960,9 @@ static void mvpp2_defaults_set(struct mv + mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0); + + /* Close bandwidth for all queues */ +- for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) { +- ptxq = mvpp2_txq_phys(port->id, queue); ++ for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) + mvpp2_write(port->priv, +- MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(ptxq), 0); +- } ++ MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(queue), 0); + + /* Set refill period to 1 usec, refill tokens + * and bucket size to maximum +@@ -4722,7 +4720,7 @@ static void mvpp2_txq_deinit(struct mvpp + txq->descs_phys = 0; + + /* Set minimum bandwidth for disabled TXQs */ +- mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0); ++ mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->log_id), 0); + + /* Set Tx descriptors queue starting address and size */ + mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id); diff --git a/queue-4.4/net-stmmac-fix-reset-gpio-free-missing.patch b/queue-4.4/net-stmmac-fix-reset-gpio-free-missing.patch new file mode 100644 index 00000000000..5674a03fa6d --- /dev/null +++ b/queue-4.4/net-stmmac-fix-reset-gpio-free-missing.patch @@ -0,0 +1,36 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Jisheng Zhang +Date: Wed, 22 May 2019 10:05:09 +0000 +Subject: net: stmmac: fix reset gpio free missing + +From: Jisheng Zhang + +[ Upstream commit 49ce881c0d4c4a7a35358d9dccd5f26d0e56fc61 ] + +Commit 984203ceff27 ("net: stmmac: mdio: remove reset gpio free") +removed the reset gpio free, when the driver is unbinded or rmmod, +we miss the gpio free. + +This patch uses managed API to request the reset gpio, so that the +gpio could be freed properly. + +Fixes: 984203ceff27 ("net: stmmac: mdio: remove reset gpio free") +Signed-off-by: Jisheng Zhang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +@@ -154,7 +154,8 @@ int stmmac_mdio_reset(struct mii_bus *bu + of_property_read_u32_array(np, + "snps,reset-delays-us", data->delays, 3); + +- if (gpio_request(data->reset_gpio, "mdio-reset")) ++ if (devm_gpio_request(priv->device, data->reset_gpio, ++ "mdio-reset")) + return 0; + } + diff --git a/queue-4.4/series b/queue-4.4/series index f392caebed9..39bb5b2eb0d 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -177,3 +177,11 @@ spi-spi-topcliff-pch-fix-to-handle-empty-dma-buffers.patch spi-rspi-fix-sequencer-reset-during-initialization.patch spi-fix-zero-length-xfer-bug.patch asoc-davinci-mcasp-fix-clang-warning-without-config_.patch +ipv6-consider-sk_bound_dev_if-when-binding-a-raw-socket-to-an-address.patch +llc-fix-skb-leak-in-llc_build_and_send_ui_pkt.patch +net-gro-fix-use-after-free-read-in-napi_gro_frags.patch +net-stmmac-fix-reset-gpio-free-missing.patch +usbnet-fix-kernel-crash-after-disconnect.patch +tipc-avoid-copying-bytes-beyond-the-supplied-data.patch +bnxt_en-fix-aggregation-buffer-leak-under-oom-condition.patch +net-mvpp2-fix-bad-mvpp2_txq_sched_token_cntr_reg-queue-value.patch diff --git a/queue-4.4/tipc-avoid-copying-bytes-beyond-the-supplied-data.patch b/queue-4.4/tipc-avoid-copying-bytes-beyond-the-supplied-data.patch new file mode 100644 index 00000000000..cf993e3de65 --- /dev/null +++ b/queue-4.4/tipc-avoid-copying-bytes-beyond-the-supplied-data.patch @@ -0,0 +1,67 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Chris Packham +Date: Mon, 20 May 2019 15:45:36 +1200 +Subject: tipc: Avoid copying bytes beyond the supplied data + +From: Chris Packham + +TLV_SET is called with a data pointer and a len parameter that tells us +how many bytes are pointed to by data. When invoking memcpy() we need +to careful to only copy len bytes. + +Previously we would copy TLV_LENGTH(len) bytes which would copy an extra +4 bytes past the end of the data pointer which newer GCC versions +complain about. + + In file included from test.c:17: + In function 'TLV_SET', + inlined from 'test' at test.c:186:5: + /usr/include/linux/tipc_config.h:317:3: + warning: 'memcpy' forming offset [33, 36] is out of the bounds [0, 32] + of object 'bearer_name' with type 'char[32]' [-Warray-bounds] + memcpy(TLV_DATA(tlv_ptr), data, tlv_len); + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + test.c: In function 'test': + test.c::161:10: note: + 'bearer_name' declared here + char bearer_name[TIPC_MAX_BEARER_NAME]; + ^~~~~~~~~~~ + +We still want to ensure any padding bytes at the end are initialised, do +this with a explicit memset() rather than copy bytes past the end of +data. Apply the same logic to TCM_SET. + +Signed-off-by: Chris Packham +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/uapi/linux/tipc_config.h | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/include/uapi/linux/tipc_config.h ++++ b/include/uapi/linux/tipc_config.h +@@ -301,8 +301,10 @@ static inline int TLV_SET(void *tlv, __u + tlv_ptr = (struct tlv_desc *)tlv; + tlv_ptr->tlv_type = htons(type); + tlv_ptr->tlv_len = htons(tlv_len); +- if (len && data) +- memcpy(TLV_DATA(tlv_ptr), data, tlv_len); ++ if (len && data) { ++ memcpy(TLV_DATA(tlv_ptr), data, len); ++ memset(TLV_DATA(tlv_ptr) + len, 0, TLV_SPACE(len) - tlv_len); ++ } + return TLV_SPACE(len); + } + +@@ -399,8 +401,10 @@ static inline int TCM_SET(void *msg, __u + tcm_hdr->tcm_len = htonl(msg_len); + tcm_hdr->tcm_type = htons(cmd); + tcm_hdr->tcm_flags = htons(flags); +- if (data_len && data) ++ if (data_len && data) { + memcpy(TCM_DATA(msg), data, data_len); ++ memset(TCM_DATA(msg) + data_len, 0, TCM_SPACE(data_len) - msg_len); ++ } + return TCM_SPACE(data_len); + } + diff --git a/queue-4.4/usbnet-fix-kernel-crash-after-disconnect.patch b/queue-4.4/usbnet-fix-kernel-crash-after-disconnect.patch new file mode 100644 index 00000000000..09a295bc7bb --- /dev/null +++ b/queue-4.4/usbnet-fix-kernel-crash-after-disconnect.patch @@ -0,0 +1,90 @@ +From foo@baz Fri 31 May 2019 03:55:52 PM PDT +From: Kloetzke Jan +Date: Tue, 21 May 2019 13:18:40 +0000 +Subject: usbnet: fix kernel crash after disconnect + +From: Kloetzke Jan + +[ Upstream commit ad70411a978d1e6e97b1e341a7bde9a79af0c93d ] + +When disconnecting cdc_ncm the kernel sporadically crashes shortly +after the disconnect: + + [ 57.868812] Unable to handle kernel NULL pointer dereference at virtual address 00000000 + ... + [ 58.006653] PC is at 0x0 + [ 58.009202] LR is at call_timer_fn+0xec/0x1b4 + [ 58.013567] pc : [<0000000000000000>] lr : [] pstate: 00000145 + [ 58.020976] sp : ffffff8008003da0 + [ 58.024295] x29: ffffff8008003da0 x28: 0000000000000001 + [ 58.029618] x27: 000000000000000a x26: 0000000000000100 + [ 58.034941] x25: 0000000000000000 x24: ffffff8008003e68 + [ 58.040263] x23: 0000000000000000 x22: 0000000000000000 + [ 58.045587] x21: 0000000000000000 x20: ffffffc68fac1808 + [ 58.050910] x19: 0000000000000100 x18: 0000000000000000 + [ 58.056232] x17: 0000007f885aff8c x16: 0000007f883a9f10 + [ 58.061556] x15: 0000000000000001 x14: 000000000000006e + [ 58.066878] x13: 0000000000000000 x12: 00000000000000ba + [ 58.072201] x11: ffffffc69ff1db30 x10: 0000000000000020 + [ 58.077524] x9 : 8000100008001000 x8 : 0000000000000001 + [ 58.082847] x7 : 0000000000000800 x6 : ffffff8008003e70 + [ 58.088169] x5 : ffffffc69ff17a28 x4 : 00000000ffff138b + [ 58.093492] x3 : 0000000000000000 x2 : 0000000000000000 + [ 58.098814] x1 : 0000000000000000 x0 : 0000000000000000 + ... + [ 58.205800] [< (null)>] (null) + [ 58.210521] [] expire_timers+0xa0/0x14c + [ 58.215937] [] run_timer_softirq+0xe8/0x128 + [ 58.221702] [] __do_softirq+0x298/0x348 + [ 58.227118] [] irq_exit+0x74/0xbc + [ 58.232009] [] __handle_domain_irq+0x78/0xac + [ 58.237857] [] gic_handle_irq+0x80/0xac + ... + +The crash happens roughly 125..130ms after the disconnect. This +correlates with the 'delay' timer that is started on certain USB tx/rx +errors in the URB completion handler. + +The problem is a race of usbnet_stop() with usbnet_start_xmit(). In +usbnet_stop() we call usbnet_terminate_urbs() to cancel all URBs in +flight. This only makes sense if no new URBs are submitted +concurrently, though. But the usbnet_start_xmit() can run at the same +time on another CPU which almost unconditionally submits an URB. The +error callback of the new URB will then schedule the timer after it was +already stopped. + +The fix adds a check if the tx queue is stopped after the tx list lock +has been taken. This should reliably prevent the submission of new URBs +while usbnet_terminate_urbs() does its job. The same thing is done on +the rx side even though it might be safe due to other flags that are +checked there. + +Signed-off-by: Jan Klötzke +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/usbnet.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -499,6 +499,7 @@ static int rx_submit (struct usbnet *dev + + if (netif_running (dev->net) && + netif_device_present (dev->net) && ++ test_bit(EVENT_DEV_OPEN, &dev->flags) && + !test_bit (EVENT_RX_HALT, &dev->flags) && + !test_bit (EVENT_DEV_ASLEEP, &dev->flags)) { + switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { +@@ -1385,6 +1386,11 @@ netdev_tx_t usbnet_start_xmit (struct sk + spin_unlock_irqrestore(&dev->txq.lock, flags); + goto drop; + } ++ if (netif_queue_stopped(net)) { ++ usb_autopm_put_interface_async(dev->intf); ++ spin_unlock_irqrestore(&dev->txq.lock, flags); ++ goto drop; ++ } + + #ifdef CONFIG_PM + /* if this triggers the device is still a sleep */