From: Greg Kroah-Hartman Date: Fri, 11 Sep 2020 07:57:14 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.236~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6d9561e5c909d27250e55b70861d61b8ba6310e0;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: bnxt-don-t-enable-napi-until-rings-are-ready.patch net-disable-netpoll-on-fresh-napis.patch net-usb-dm9601-add-usb-id-of-keenetic-plus-dsl.patch netlabel-fix-problems-with-mapping-removal.patch sctp-not-disable-bh-in-the-whole-sctp_get_port_local.patch tipc-fix-shutdown-of-connectionless-socket.patch --- diff --git a/queue-4.14/bnxt-don-t-enable-napi-until-rings-are-ready.patch b/queue-4.14/bnxt-don-t-enable-napi-until-rings-are-ready.patch new file mode 100644 index 00000000000..64bd81b48a9 --- /dev/null +++ b/queue-4.14/bnxt-don-t-enable-napi-until-rings-are-ready.patch @@ -0,0 +1,79 @@ +From 96ecdcc992eb7f468b2cf829b0f5408a1fad4668 Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Wed, 26 Aug 2020 12:40:07 -0700 +Subject: bnxt: don't enable NAPI until rings are ready + +From: Jakub Kicinski + +commit 96ecdcc992eb7f468b2cf829b0f5408a1fad4668 upstream. + +Netpoll can try to poll napi as soon as napi_enable() is called. +It crashes trying to access a doorbell which is still NULL: + + BUG: kernel NULL pointer dereference, address: 0000000000000000 + CPU: 59 PID: 6039 Comm: ethtool Kdump: loaded Tainted: G S 5.9.0-rc1-00469-g5fd99b5d9950-dirty #26 + RIP: 0010:bnxt_poll+0x121/0x1c0 + Code: c4 20 44 89 e0 5b 5d 41 5c 41 5d 41 5e 41 5f c3 41 8b 86 a0 01 00 00 41 23 85 18 01 00 00 49 8b 96 a8 01 00 00 0d 00 00 00 24 <89> 02 +41 f6 45 77 02 74 cb 49 8b ae d8 01 00 00 31 c0 c7 44 24 1a + netpoll_poll_dev+0xbd/0x1a0 + __netpoll_send_skb+0x1b2/0x210 + netpoll_send_udp+0x2c9/0x406 + write_ext_msg+0x1d7/0x1f0 + console_unlock+0x23c/0x520 + vprintk_emit+0xe0/0x1d0 + printk+0x58/0x6f + x86_vector_activate.cold+0xf/0x46 + __irq_domain_activate_irq+0x50/0x80 + __irq_domain_activate_irq+0x32/0x80 + __irq_domain_activate_irq+0x32/0x80 + irq_domain_activate_irq+0x25/0x40 + __setup_irq+0x2d2/0x700 + request_threaded_irq+0xfb/0x160 + __bnxt_open_nic+0x3b1/0x750 + bnxt_open_nic+0x19/0x30 + ethtool_set_channels+0x1ac/0x220 + dev_ethtool+0x11ba/0x2240 + dev_ioctl+0x1cf/0x390 + sock_do_ioctl+0x95/0x130 + +Reported-by: Rob Sherwood +Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") +Signed-off-by: Jakub Kicinski +Reviewed-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -6378,14 +6378,14 @@ static int __bnxt_open_nic(struct bnxt * + } + } + +- bnxt_enable_napi(bp); +- + rc = bnxt_init_nic(bp, irq_re_init); + if (rc) { + netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc); +- goto open_err; ++ goto open_err_irq; + } + ++ bnxt_enable_napi(bp); ++ + if (link_re_init) { + mutex_lock(&bp->link_lock); + rc = bnxt_update_phy_setting(bp); +@@ -6410,9 +6410,6 @@ static int __bnxt_open_nic(struct bnxt * + bnxt_vf_reps_open(bp); + return 0; + +-open_err: +- bnxt_disable_napi(bp); +- + open_err_irq: + bnxt_del_napi(bp); + diff --git a/queue-4.14/net-disable-netpoll-on-fresh-napis.patch b/queue-4.14/net-disable-netpoll-on-fresh-napis.patch new file mode 100644 index 00000000000..be9a9b1f36e --- /dev/null +++ b/queue-4.14/net-disable-netpoll-on-fresh-napis.patch @@ -0,0 +1,58 @@ +From foo@baz Fri Sep 11 09:55:41 AM CEST 2020 +From: Jakub Kicinski +Date: Wed, 26 Aug 2020 12:40:06 -0700 +Subject: net: disable netpoll on fresh napis + +From: Jakub Kicinski + +[ Upstream commit 96e97bc07e90f175a8980a22827faf702ca4cb30 ] + +napi_disable() makes sure to set the NAPI_STATE_NPSVC bit to prevent +netpoll from accessing rings before init is complete. However, the +same is not done for fresh napi instances in netif_napi_add(), +even though we expect NAPI instances to be added as disabled. + +This causes crashes during driver reconfiguration (enabling XDP, +changing the channel count) - if there is any printk() after +netif_napi_add() but before napi_enable(). + +To ensure memory ordering is correct we need to use RCU accessors. + +Reported-by: Rob Sherwood +Fixes: 2d8bff12699a ("netpoll: Close race condition between poll_one_napi and napi_disable") +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/dev.c | 3 ++- + net/core/netpoll.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -5532,12 +5532,13 @@ void netif_napi_add(struct net_device *d + pr_err_once("netif_napi_add() called with weight %d on device %s\n", + weight, dev->name); + napi->weight = weight; +- list_add(&napi->dev_list, &dev->napi_list); + napi->dev = dev; + #ifdef CONFIG_NETPOLL + napi->poll_owner = -1; + #endif + set_bit(NAPI_STATE_SCHED, &napi->state); ++ set_bit(NAPI_STATE_NPSVC, &napi->state); ++ list_add_rcu(&napi->dev_list, &dev->napi_list); + napi_hash_add(napi); + } + EXPORT_SYMBOL(netif_napi_add); +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -179,7 +179,7 @@ static void poll_napi(struct net_device + struct napi_struct *napi; + int cpu = smp_processor_id(); + +- list_for_each_entry(napi, &dev->napi_list, dev_list) { ++ list_for_each_entry_rcu(napi, &dev->napi_list, dev_list) { + if (cmpxchg(&napi->poll_owner, -1, cpu) == -1) { + poll_one_napi(napi); + smp_store_release(&napi->poll_owner, -1); diff --git a/queue-4.14/net-usb-dm9601-add-usb-id-of-keenetic-plus-dsl.patch b/queue-4.14/net-usb-dm9601-add-usb-id-of-keenetic-plus-dsl.patch new file mode 100644 index 00000000000..a29b84ba7b5 --- /dev/null +++ b/queue-4.14/net-usb-dm9601-add-usb-id-of-keenetic-plus-dsl.patch @@ -0,0 +1,31 @@ +From foo@baz Fri Sep 11 09:55:41 AM CEST 2020 +From: Kamil Lorenc +Date: Tue, 1 Sep 2020 10:57:38 +0200 +Subject: net: usb: dm9601: Add USB ID of Keenetic Plus DSL + +From: Kamil Lorenc + +[ Upstream commit a609d0259183a841621f252e067f40f8cc25d6f6 ] + +Keenetic Plus DSL is a xDSL modem that uses dm9620 as its USB interface. + +Signed-off-by: Kamil Lorenc +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/dm9601.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/usb/dm9601.c ++++ b/drivers/net/usb/dm9601.c +@@ -625,6 +625,10 @@ static const struct usb_device_id produc + USB_DEVICE(0x0a46, 0x1269), /* DM9621A USB to Fast Ethernet Adapter */ + .driver_info = (unsigned long)&dm9601_info, + }, ++ { ++ USB_DEVICE(0x0586, 0x3427), /* ZyXEL Keenetic Plus DSL xDSL modem */ ++ .driver_info = (unsigned long)&dm9601_info, ++ }, + {}, // END + }; + diff --git a/queue-4.14/netlabel-fix-problems-with-mapping-removal.patch b/queue-4.14/netlabel-fix-problems-with-mapping-removal.patch new file mode 100644 index 00000000000..681eb6b3954 --- /dev/null +++ b/queue-4.14/netlabel-fix-problems-with-mapping-removal.patch @@ -0,0 +1,140 @@ +From foo@baz Fri Sep 11 09:55:41 AM CEST 2020 +From: Paul Moore +Date: Fri, 21 Aug 2020 16:34:52 -0400 +Subject: netlabel: fix problems with mapping removal + +From: Paul Moore + +[ Upstream commit d3b990b7f327e2afa98006e7666fb8ada8ed8683 ] + +This patch fixes two main problems seen when removing NetLabel +mappings: memory leaks and potentially extra audit noise. + +The memory leaks are caused by not properly free'ing the mapping's +address selector struct when free'ing the entire entry as well as +not properly cleaning up a temporary mapping entry when adding new +address selectors to an existing entry. This patch fixes both these +problems such that kmemleak reports no NetLabel associated leaks +after running the SELinux test suite. + +The potentially extra audit noise was caused by the auditing code in +netlbl_domhsh_remove_entry() being called regardless of the entry's +validity. If another thread had already marked the entry as invalid, +but not removed/free'd it from the list of mappings, then it was +possible that an additional mapping removal audit record would be +generated. This patch fixes this by returning early from the removal +function when the entry was previously marked invalid. This change +also had the side benefit of improving the code by decreasing the +indentation level of large chunk of code by one (accounting for most +of the diffstat). + +Fixes: 63c416887437 ("netlabel: Add network address selectors to the NetLabel/LSM domain mapping") +Reported-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/netlabel/netlabel_domainhash.c | 59 ++++++++++++++++++------------------- + 1 file changed, 30 insertions(+), 29 deletions(-) + +--- a/net/netlabel/netlabel_domainhash.c ++++ b/net/netlabel/netlabel_domainhash.c +@@ -99,6 +99,7 @@ static void netlbl_domhsh_free_entry(str + kfree(netlbl_domhsh_addr6_entry(iter6)); + } + #endif /* IPv6 */ ++ kfree(ptr->def.addrsel); + } + kfree(ptr->domain); + kfree(ptr); +@@ -550,6 +551,8 @@ int netlbl_domhsh_add(struct netlbl_dom_ + goto add_return; + } + #endif /* IPv6 */ ++ /* cleanup the new entry since we've moved everything over */ ++ netlbl_domhsh_free_entry(&entry->rcu); + } else + ret_val = -EINVAL; + +@@ -593,6 +596,12 @@ int netlbl_domhsh_remove_entry(struct ne + { + int ret_val = 0; + struct audit_buffer *audit_buf; ++ struct netlbl_af4list *iter4; ++ struct netlbl_domaddr4_map *map4; ++#if IS_ENABLED(CONFIG_IPV6) ++ struct netlbl_af6list *iter6; ++ struct netlbl_domaddr6_map *map6; ++#endif /* IPv6 */ + + if (entry == NULL) + return -ENOENT; +@@ -610,6 +619,9 @@ int netlbl_domhsh_remove_entry(struct ne + ret_val = -ENOENT; + spin_unlock(&netlbl_domhsh_lock); + ++ if (ret_val) ++ return ret_val; ++ + audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); + if (audit_buf != NULL) { + audit_log_format(audit_buf, +@@ -619,40 +631,29 @@ int netlbl_domhsh_remove_entry(struct ne + audit_log_end(audit_buf); + } + +- if (ret_val == 0) { +- struct netlbl_af4list *iter4; +- struct netlbl_domaddr4_map *map4; +-#if IS_ENABLED(CONFIG_IPV6) +- struct netlbl_af6list *iter6; +- struct netlbl_domaddr6_map *map6; +-#endif /* IPv6 */ +- +- switch (entry->def.type) { +- case NETLBL_NLTYPE_ADDRSELECT: +- netlbl_af4list_foreach_rcu(iter4, +- &entry->def.addrsel->list4) { +- map4 = netlbl_domhsh_addr4_entry(iter4); +- cipso_v4_doi_putdef(map4->def.cipso); +- } ++ switch (entry->def.type) { ++ case NETLBL_NLTYPE_ADDRSELECT: ++ netlbl_af4list_foreach_rcu(iter4, &entry->def.addrsel->list4) { ++ map4 = netlbl_domhsh_addr4_entry(iter4); ++ cipso_v4_doi_putdef(map4->def.cipso); ++ } + #if IS_ENABLED(CONFIG_IPV6) +- netlbl_af6list_foreach_rcu(iter6, +- &entry->def.addrsel->list6) { +- map6 = netlbl_domhsh_addr6_entry(iter6); +- calipso_doi_putdef(map6->def.calipso); +- } ++ netlbl_af6list_foreach_rcu(iter6, &entry->def.addrsel->list6) { ++ map6 = netlbl_domhsh_addr6_entry(iter6); ++ calipso_doi_putdef(map6->def.calipso); ++ } + #endif /* IPv6 */ +- break; +- case NETLBL_NLTYPE_CIPSOV4: +- cipso_v4_doi_putdef(entry->def.cipso); +- break; ++ break; ++ case NETLBL_NLTYPE_CIPSOV4: ++ cipso_v4_doi_putdef(entry->def.cipso); ++ break; + #if IS_ENABLED(CONFIG_IPV6) +- case NETLBL_NLTYPE_CALIPSO: +- calipso_doi_putdef(entry->def.calipso); +- break; ++ case NETLBL_NLTYPE_CALIPSO: ++ calipso_doi_putdef(entry->def.calipso); ++ break; + #endif /* IPv6 */ +- } +- call_rcu(&entry->rcu, netlbl_domhsh_free_entry); + } ++ call_rcu(&entry->rcu, netlbl_domhsh_free_entry); + + return ret_val; + } diff --git a/queue-4.14/sctp-not-disable-bh-in-the-whole-sctp_get_port_local.patch b/queue-4.14/sctp-not-disable-bh-in-the-whole-sctp_get_port_local.patch new file mode 100644 index 00000000000..5f7bea39e52 --- /dev/null +++ b/queue-4.14/sctp-not-disable-bh-in-the-whole-sctp_get_port_local.patch @@ -0,0 +1,105 @@ +From foo@baz Fri Sep 11 09:55:41 AM CEST 2020 +From: Xin Long +Date: Fri, 21 Aug 2020 14:59:38 +0800 +Subject: sctp: not disable bh in the whole sctp_get_port_local() + +From: Xin Long + +[ Upstream commit 3106ecb43a05dc3e009779764b9da245a5d082de ] + +With disabling bh in the whole sctp_get_port_local(), when +snum == 0 and too many ports have been used, the do-while +loop will take the cpu for a long time and cause cpu stuck: + + [ ] watchdog: BUG: soft lockup - CPU#11 stuck for 22s! + [ ] RIP: 0010:native_queued_spin_lock_slowpath+0x4de/0x940 + [ ] Call Trace: + [ ] _raw_spin_lock+0xc1/0xd0 + [ ] sctp_get_port_local+0x527/0x650 [sctp] + [ ] sctp_do_bind+0x208/0x5e0 [sctp] + [ ] sctp_autobind+0x165/0x1e0 [sctp] + [ ] sctp_connect_new_asoc+0x355/0x480 [sctp] + [ ] __sctp_connect+0x360/0xb10 [sctp] + +There's no need to disable bh in the whole function of +sctp_get_port_local. So fix this cpu stuck by removing +local_bh_disable() called at the beginning, and using +spin_lock_bh() instead. + +The same thing was actually done for inet_csk_get_port() in +Commit ea8add2b1903 ("tcp/dccp: better use of ephemeral +ports in bind()"). + +Thanks to Marcelo for pointing the buggy code out. + +v1->v2: + - use cond_resched() to yield cpu to other tasks if needed, + as Eric noticed. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Ying Xu +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -7086,8 +7086,6 @@ static long sctp_get_port_local(struct s + + pr_debug("%s: begins, snum:%d\n", __func__, snum); + +- local_bh_disable(); +- + if (snum == 0) { + /* Search for an available port. */ + int low, high, remaining, index; +@@ -7106,20 +7104,21 @@ static long sctp_get_port_local(struct s + continue; + index = sctp_phashfn(sock_net(sk), rover); + head = &sctp_port_hashtable[index]; +- spin_lock(&head->lock); ++ spin_lock_bh(&head->lock); + sctp_for_each_hentry(pp, &head->chain) + if ((pp->port == rover) && + net_eq(sock_net(sk), pp->net)) + goto next; + break; + next: +- spin_unlock(&head->lock); ++ spin_unlock_bh(&head->lock); ++ cond_resched(); + } while (--remaining > 0); + + /* Exhausted local port range during search? */ + ret = 1; + if (remaining <= 0) +- goto fail; ++ return ret; + + /* OK, here is the one we will use. HEAD (the port + * hash table list entry) is non-NULL and we hold it's +@@ -7134,7 +7133,7 @@ static long sctp_get_port_local(struct s + * port iterator, pp being NULL. + */ + head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)]; +- spin_lock(&head->lock); ++ spin_lock_bh(&head->lock); + sctp_for_each_hentry(pp, &head->chain) { + if ((pp->port == snum) && net_eq(pp->net, sock_net(sk))) + goto pp_found; +@@ -7218,10 +7217,7 @@ success: + ret = 0; + + fail_unlock: +- spin_unlock(&head->lock); +- +-fail: +- local_bh_enable(); ++ spin_unlock_bh(&head->lock); + return ret; + } + diff --git a/queue-4.14/series b/queue-4.14/series index 0534695e904..c7000b37905 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -4,3 +4,9 @@ vfio-type1-support-faulting-pfnmap-vmas.patch vfio-pci-fault-mmaps-to-enable-vma-tracking.patch vfio-pci-invalidate-mmaps-and-block-mmio-access-on-disabled-memory.patch vfio-pci-fix-sr-iov-vf-handling-with-mmio-blocking.patch +bnxt-don-t-enable-napi-until-rings-are-ready.patch +netlabel-fix-problems-with-mapping-removal.patch +net-usb-dm9601-add-usb-id-of-keenetic-plus-dsl.patch +sctp-not-disable-bh-in-the-whole-sctp_get_port_local.patch +tipc-fix-shutdown-of-connectionless-socket.patch +net-disable-netpoll-on-fresh-napis.patch diff --git a/queue-4.14/tipc-fix-shutdown-of-connectionless-socket.patch b/queue-4.14/tipc-fix-shutdown-of-connectionless-socket.patch new file mode 100644 index 00000000000..da3b357fa3a --- /dev/null +++ b/queue-4.14/tipc-fix-shutdown-of-connectionless-socket.patch @@ -0,0 +1,85 @@ +From foo@baz Fri Sep 11 09:55:41 AM CEST 2020 +From: Tetsuo Handa +Date: Wed, 2 Sep 2020 22:44:16 +0900 +Subject: tipc: fix shutdown() of connectionless socket + +From: Tetsuo Handa + +[ Upstream commit 2a63866c8b51a3f72cea388dfac259d0e14c4ba6 ] + +syzbot is reporting hung task at nbd_ioctl() [1], for there are two +problems regarding TIPC's connectionless socket's shutdown() operation. + +---------- +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + const int fd = open("/dev/nbd0", 3); + alarm(5); + ioctl(fd, NBD_SET_SOCK, socket(PF_TIPC, SOCK_DGRAM, 0)); + ioctl(fd, NBD_DO_IT, 0); /* To be interrupted by SIGALRM. */ + return 0; +} +---------- + +One problem is that wait_for_completion() from flush_workqueue() from +nbd_start_device_ioctl() from nbd_ioctl() cannot be completed when +nbd_start_device_ioctl() received a signal at wait_event_interruptible(), +for tipc_shutdown() from kernel_sock_shutdown(SHUT_RDWR) from +nbd_mark_nsock_dead() from sock_shutdown() from nbd_start_device_ioctl() +is failing to wake up a WQ thread sleeping at wait_woken() from +tipc_wait_for_rcvmsg() from sock_recvmsg() from sock_xmit() from +nbd_read_stat() from recv_work() scheduled by nbd_start_device() from +nbd_start_device_ioctl(). Fix this problem by always invoking +sk->sk_state_change() (like inet_shutdown() does) when tipc_shutdown() is +called. + +The other problem is that tipc_wait_for_rcvmsg() cannot return when +tipc_shutdown() is called, for tipc_shutdown() sets sk->sk_shutdown to +SEND_SHUTDOWN (despite "how" is SHUT_RDWR) while tipc_wait_for_rcvmsg() +needs sk->sk_shutdown set to RCV_SHUTDOWN or SHUTDOWN_MASK. Fix this +problem by setting sk->sk_shutdown to SHUTDOWN_MASK (like inet_shutdown() +does) when the socket is connectionless. + +[1] https://syzkaller.appspot.com/bug?id=3fe51d307c1f0a845485cf1798aa059d12bf18b2 + +Reported-by: syzbot +Signed-off-by: Tetsuo Handa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/socket.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -2126,18 +2126,21 @@ static int tipc_shutdown(struct socket * + lock_sock(sk); + + __tipc_shutdown(sock, TIPC_CONN_SHUTDOWN); +- sk->sk_shutdown = SEND_SHUTDOWN; ++ if (tipc_sk_type_connectionless(sk)) ++ sk->sk_shutdown = SHUTDOWN_MASK; ++ else ++ sk->sk_shutdown = SEND_SHUTDOWN; + + if (sk->sk_state == TIPC_DISCONNECTING) { + /* Discard any unreceived messages */ + __skb_queue_purge(&sk->sk_receive_queue); + +- /* Wake up anyone sleeping in poll */ +- sk->sk_state_change(sk); + res = 0; + } else { + res = -ENOTCONN; + } ++ /* Wake up anyone sleeping in poll. */ ++ sk->sk_state_change(sk); + + release_sock(sk); + return res;