From: Greg Kroah-Hartman Date: Mon, 17 Jul 2017 16:52:20 +0000 (+0200) Subject: 4.12-stable patches X-Git-Tag: v4.12.3~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5eb71c1ea5c4c0722b764e0f3360dd74cd69cc18;p=thirdparty%2Fkernel%2Fstable-queue.git 4.12-stable patches added patches: brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch cxgb4-fix-bug-on-interrupt-deallocating-path-of-uld.patch geneve-fix-hlist-corruption.patch ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch liquidio-fix-bug-in-soft-reset-failure-detection.patch net-core-fix-slab-out-of-bounds-in-netdev_stats_to_stats64.patch net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch net-mlx5-cancel-delayed-recovery-work-when-unloading-the-driver.patch net-mlx5-fix-driver-load-error-flow-when-firmware-is-stuck.patch net-mlx5e-fix-tx-carrier-errors-report-in-get-stats-ndo.patch net-mlx5e-initialize-cee-s-getpermhwaddr-address-buffer-to-0xff.patch rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch sfc-don-t-read-beyond-unicast-address-list.patch staging-android-uapi-drop-definitions-of-removed-ion_ioc_-free-share-ioctls.patch tap-convert-a-mutex-to-a-spinlock.patch virtio-net-fix-leaking-of-ctx-array.patch vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch vxlan-fix-hlist-corruption.patch --- diff --git a/queue-4.12/brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch b/queue-4.12/brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch new file mode 100644 index 00000000000..701c2b9b65e --- /dev/null +++ b/queue-4.12/brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch @@ -0,0 +1,43 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Arend van Spriel +Date: Fri, 7 Jul 2017 21:09:06 +0100 +Subject: brcmfmac: fix possible buffer overflow in brcmf_cfg80211_mgmt_tx() + +From: Arend van Spriel + + +[ Upstream commit 8f44c9a41386729fea410e688959ddaa9d51be7c ] + +The lower level nl80211 code in cfg80211 ensures that "len" is between +25 and NL80211_ATTR_FRAME (2304). We subtract DOT11_MGMT_HDR_LEN (24) from +"len" so thats's max of 2280. However, the action_frame->data[] buffer is +only BRCMF_FIL_ACTION_FRAME_SIZE (1800) bytes long so this memcpy() can +overflow. + + memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], + le16_to_cpu(action_frame->len)); + +Cc: stable@vger.kernel.org # 3.9.x +Fixes: 18e2f61db3b70 ("brcmfmac: P2P action frame tx.") +Reported-by: "freenerguo(郭大兴)" +Signed-off-by: Arend van Spriel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -4851,6 +4851,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wip + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, + GFP_KERNEL); + } else if (ieee80211_is_action(mgmt->frame_control)) { ++ if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { ++ brcmf_err("invalid action frame length\n"); ++ err = -EINVAL; ++ goto exit; ++ } + af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); + if (af_params == NULL) { + brcmf_err("unable to allocate frame\n"); diff --git a/queue-4.12/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch b/queue-4.12/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch new file mode 100644 index 00000000000..c383fb5312d --- /dev/null +++ b/queue-4.12/bridge-mdb-fix-leak-on-complete_info-ptr-on-fail-path.patch @@ -0,0 +1,57 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Eduardo Valentin +Date: Tue, 11 Jul 2017 14:55:12 -0700 +Subject: bridge: mdb: fix leak on complete_info ptr on fail path + +From: Eduardo Valentin + + +[ Upstream commit 1bfb159673957644951ab0a8d2aec44b93ddb1ae ] + +We currently get the following kmemleak report: +unreferenced object 0xffff8800039d9820 (size 32): + comm "softirq", pid 0, jiffies 4295212383 (age 792.416s) + hex dump (first 32 bytes): + 00 0c e0 03 00 88 ff ff ff 02 00 00 00 00 00 00 ................ + 00 00 00 01 ff 11 00 02 86 dd 00 00 ff ff ff ff ................ + backtrace: + [] kmemleak_alloc+0x4a/0xa0 + [] kmem_cache_alloc_trace+0xb8/0x1c0 + [] __br_mdb_notify+0x2a3/0x300 [bridge] + [] br_mdb_notify+0x6e/0x70 [bridge] + [] br_multicast_add_group+0x109/0x150 [bridge] + [] br_ip6_multicast_add_group+0x58/0x60 [bridge] + [] br_multicast_rcv+0x1d5/0xdb0 [bridge] + [] br_handle_frame_finish+0xcf/0x510 [bridge] + [] br_nf_hook_thresh.part.27+0xb/0x10 [br_netfilter] + [] br_nf_hook_thresh+0x48/0xb0 [br_netfilter] + [] br_nf_pre_routing_finish_ipv6+0x109/0x1d0 [br_netfilter] + [] br_nf_pre_routing_ipv6+0xd0/0x14c [br_netfilter] + [] br_nf_pre_routing+0x197/0x3d0 [br_netfilter] + [] nf_iterate+0x52/0x60 + [] nf_hook_slow+0x5c/0xb0 + [] br_handle_frame+0x1a4/0x2c0 [bridge] + +This happens when switchdev_port_obj_add() fails. This patch +frees complete_info object in the fail path. + +Reviewed-by: Vallish Vaidyeshwara +Signed-off-by: Eduardo Valentin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_mdb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/bridge/br_mdb.c ++++ b/net/bridge/br_mdb.c +@@ -323,7 +323,8 @@ static void __br_mdb_notify(struct net_d + __mdb_entry_to_br_ip(entry, &complete_info->ip); + mdb.obj.complete_priv = complete_info; + mdb.obj.complete = br_mdb_complete; +- switchdev_port_obj_add(port_dev, &mdb.obj); ++ if (switchdev_port_obj_add(port_dev, &mdb.obj)) ++ kfree(complete_info); + } + } else if (port_dev && type == RTM_DELMDB) { + switchdev_port_obj_del(port_dev, &mdb.obj); diff --git a/queue-4.12/cxgb4-fix-bug-on-interrupt-deallocating-path-of-uld.patch b/queue-4.12/cxgb4-fix-bug-on-interrupt-deallocating-path-of-uld.patch new file mode 100644 index 00000000000..9bfad7c477a --- /dev/null +++ b/queue-4.12/cxgb4-fix-bug-on-interrupt-deallocating-path-of-uld.patch @@ -0,0 +1,162 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: "Guilherme G. Piccoli" +Date: Mon, 10 Jul 2017 10:55:46 -0300 +Subject: cxgb4: fix BUG() on interrupt deallocating path of ULD + +From: "Guilherme G. Piccoli" + + +[ Upstream commit 6a146f3a5894b751cef16feb3d7903e45e3c445c ] + +Since the introduction of ULD (Upper-Layer Drivers), the MSI-X +deallocating path changed in cxgb4: the driver frees the interrupts +of ULD when unregistering it or on shutdown PCI handler. + +Problem is that if a MSI-X is not freed before deallocated in the PCI +layer, it will trigger a BUG() due to still "alive" interrupt being +tentatively quiesced. + +The below trace was observed when doing a simple unbind of Chelsio's +adapter PCI function, like: + "echo 001e:80:00.4 > /sys/bus/pci/drivers/cxgb4/unbind" + +Trace: + + kernel BUG at drivers/pci/msi.c:352! + Oops: Exception in kernel mode, sig: 5 [#1] + ... + NIP [c0000000005a5e60] free_msi_irqs+0xa0/0x250 + LR [c0000000005a5e50] free_msi_irqs+0x90/0x250 + Call Trace: + [c0000000005a5e50] free_msi_irqs+0x90/0x250 (unreliable) + [c0000000005a72c4] pci_disable_msix+0x124/0x180 + [d000000011e06708] disable_msi+0x88/0xb0 [cxgb4] + [d000000011e06948] free_some_resources+0xa8/0x160 [cxgb4] + [d000000011e06d60] remove_one+0x170/0x3c0 [cxgb4] + [c00000000058a910] pci_device_remove+0x70/0x110 + [c00000000064ef04] device_release_driver_internal+0x1f4/0x2c0 + ... + +This patch fixes the issue by refactoring the shutdown path of ULD on +cxgb4 driver, by properly freeing and disabling interrupts on PCI +remove handler too. + +Fixes: 0fbc81b3ad51 ("Allocate resources dynamically for all cxgb4 ULD's") +Reported-by: Harsha Thyagaraja +Signed-off-by: Guilherme G. Piccoli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 16 ++++++--- + drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c | 42 ++++++++++++++---------- + 2 files changed, 36 insertions(+), 22 deletions(-) + +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +@@ -2055,12 +2055,12 @@ static void detach_ulds(struct adapter * + + mutex_lock(&uld_mutex); + list_del(&adap->list_node); ++ + for (i = 0; i < CXGB4_ULD_MAX; i++) +- if (adap->uld && adap->uld[i].handle) { ++ if (adap->uld && adap->uld[i].handle) + adap->uld[i].state_change(adap->uld[i].handle, + CXGB4_STATE_DETACH); +- adap->uld[i].handle = NULL; +- } ++ + if (netevent_registered && list_empty(&adapter_list)) { + unregister_netevent_notifier(&cxgb4_netevent_nb); + netevent_registered = false; +@@ -5086,8 +5086,10 @@ static void remove_one(struct pci_dev *p + */ + destroy_workqueue(adapter->workq); + +- if (is_uld(adapter)) ++ if (is_uld(adapter)) { + detach_ulds(adapter); ++ t4_uld_clean_up(adapter); ++ } + + disable_interrupts(adapter); + +@@ -5164,7 +5166,11 @@ static void shutdown_one(struct pci_dev + if (adapter->port[i]->reg_state == NETREG_REGISTERED) + cxgb_close(adapter->port[i]); + +- t4_uld_clean_up(adapter); ++ if (is_uld(adapter)) { ++ detach_ulds(adapter); ++ t4_uld_clean_up(adapter); ++ } ++ + disable_interrupts(adapter); + disable_msi(adapter); + +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c +@@ -589,22 +589,37 @@ void t4_uld_mem_free(struct adapter *ada + kfree(adap->uld); + } + ++/* This function should be called with uld_mutex taken. */ ++static void cxgb4_shutdown_uld_adapter(struct adapter *adap, enum cxgb4_uld type) ++{ ++ if (adap->uld[type].handle) { ++ adap->uld[type].handle = NULL; ++ adap->uld[type].add = NULL; ++ release_sge_txq_uld(adap, type); ++ ++ if (adap->flags & FULL_INIT_DONE) ++ quiesce_rx_uld(adap, type); ++ ++ if (adap->flags & USING_MSIX) ++ free_msix_queue_irqs_uld(adap, type); ++ ++ free_sge_queues_uld(adap, type); ++ free_queues_uld(adap, type); ++ } ++} ++ + void t4_uld_clean_up(struct adapter *adap) + { + unsigned int i; + +- if (!adap->uld) +- return; ++ mutex_lock(&uld_mutex); + for (i = 0; i < CXGB4_ULD_MAX; i++) { + if (!adap->uld[i].handle) + continue; +- if (adap->flags & FULL_INIT_DONE) +- quiesce_rx_uld(adap, i); +- if (adap->flags & USING_MSIX) +- free_msix_queue_irqs_uld(adap, i); +- free_sge_queues_uld(adap, i); +- free_queues_uld(adap, i); ++ ++ cxgb4_shutdown_uld_adapter(adap, i); + } ++ mutex_unlock(&uld_mutex); + } + + static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld) +@@ -782,15 +797,8 @@ int cxgb4_unregister_uld(enum cxgb4_uld + continue; + if (type == CXGB4_ULD_ISCSIT && is_t4(adap->params.chip)) + continue; +- adap->uld[type].handle = NULL; +- adap->uld[type].add = NULL; +- release_sge_txq_uld(adap, type); +- if (adap->flags & FULL_INIT_DONE) +- quiesce_rx_uld(adap, type); +- if (adap->flags & USING_MSIX) +- free_msix_queue_irqs_uld(adap, type); +- free_sge_queues_uld(adap, type); +- free_queues_uld(adap, type); ++ ++ cxgb4_shutdown_uld_adapter(adap, type); + } + mutex_unlock(&uld_mutex); + diff --git a/queue-4.12/geneve-fix-hlist-corruption.patch b/queue-4.12/geneve-fix-hlist-corruption.patch new file mode 100644 index 00000000000..4f3f304b5fb --- /dev/null +++ b/queue-4.12/geneve-fix-hlist-corruption.patch @@ -0,0 +1,132 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Jiri Benc +Date: Sun, 2 Jul 2017 19:00:58 +0200 +Subject: geneve: fix hlist corruption + +From: Jiri Benc + + +[ Upstream commit 4b4c21fad6ae6bd58ff1566f23b0f4f70fdc9a30 ] + +It's not a good idea to add the same hlist_node to two different hash lists. +This leads to various hard to debug memory corruptions. + +Fixes: 8ed66f0e8235 ("geneve: implement support for IPv6-based tunnels") +Cc: John W. Linville +Signed-off-by: Jiri Benc +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/geneve.c | 48 ++++++++++++++++++++++++++++++++---------------- + 1 file changed, 32 insertions(+), 16 deletions(-) + +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -45,9 +45,17 @@ struct geneve_net { + + static unsigned int geneve_net_id; + ++struct geneve_dev_node { ++ struct hlist_node hlist; ++ struct geneve_dev *geneve; ++}; ++ + /* Pseudo network device */ + struct geneve_dev { +- struct hlist_node hlist; /* vni hash table */ ++ struct geneve_dev_node hlist4; /* vni hash table for IPv4 socket */ ++#if IS_ENABLED(CONFIG_IPV6) ++ struct geneve_dev_node hlist6; /* vni hash table for IPv6 socket */ ++#endif + struct net *net; /* netns for packet i/o */ + struct net_device *dev; /* netdev for geneve tunnel */ + struct ip_tunnel_info info; +@@ -123,16 +131,16 @@ static struct geneve_dev *geneve_lookup( + __be32 addr, u8 vni[]) + { + struct hlist_head *vni_list_head; +- struct geneve_dev *geneve; ++ struct geneve_dev_node *node; + __u32 hash; + + /* Find the device for this VNI */ + hash = geneve_net_vni_hash(vni); + vni_list_head = &gs->vni_list[hash]; +- hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) { +- if (eq_tun_id_and_vni((u8 *)&geneve->info.key.tun_id, vni) && +- addr == geneve->info.key.u.ipv4.dst) +- return geneve; ++ hlist_for_each_entry_rcu(node, vni_list_head, hlist) { ++ if (eq_tun_id_and_vni((u8 *)&node->geneve->info.key.tun_id, vni) && ++ addr == node->geneve->info.key.u.ipv4.dst) ++ return node->geneve; + } + return NULL; + } +@@ -142,16 +150,16 @@ static struct geneve_dev *geneve6_lookup + struct in6_addr addr6, u8 vni[]) + { + struct hlist_head *vni_list_head; +- struct geneve_dev *geneve; ++ struct geneve_dev_node *node; + __u32 hash; + + /* Find the device for this VNI */ + hash = geneve_net_vni_hash(vni); + vni_list_head = &gs->vni_list[hash]; +- hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) { +- if (eq_tun_id_and_vni((u8 *)&geneve->info.key.tun_id, vni) && +- ipv6_addr_equal(&addr6, &geneve->info.key.u.ipv6.dst)) +- return geneve; ++ hlist_for_each_entry_rcu(node, vni_list_head, hlist) { ++ if (eq_tun_id_and_vni((u8 *)&node->geneve->info.key.tun_id, vni) && ++ ipv6_addr_equal(&addr6, &node->geneve->info.key.u.ipv6.dst)) ++ return node->geneve; + } + return NULL; + } +@@ -579,6 +587,7 @@ static int geneve_sock_add(struct geneve + { + struct net *net = geneve->net; + struct geneve_net *gn = net_generic(net, geneve_net_id); ++ struct geneve_dev_node *node; + struct geneve_sock *gs; + __u8 vni[3]; + __u32 hash; +@@ -597,15 +606,20 @@ static int geneve_sock_add(struct geneve + out: + gs->collect_md = geneve->collect_md; + #if IS_ENABLED(CONFIG_IPV6) +- if (ipv6) ++ if (ipv6) { + rcu_assign_pointer(geneve->sock6, gs); +- else ++ node = &geneve->hlist6; ++ } else + #endif ++ { + rcu_assign_pointer(geneve->sock4, gs); ++ node = &geneve->hlist4; ++ } ++ node->geneve = geneve; + + tunnel_id_to_vni(geneve->info.key.tun_id, vni); + hash = geneve_net_vni_hash(vni); +- hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]); ++ hlist_add_head_rcu(&node->hlist, &gs->vni_list[hash]); + return 0; + } + +@@ -632,8 +646,10 @@ static int geneve_stop(struct net_device + { + struct geneve_dev *geneve = netdev_priv(dev); + +- if (!hlist_unhashed(&geneve->hlist)) +- hlist_del_rcu(&geneve->hlist); ++ hlist_del_init_rcu(&geneve->hlist4.hlist); ++#if IS_ENABLED(CONFIG_IPV6) ++ hlist_del_init_rcu(&geneve->hlist6.hlist); ++#endif + geneve_sock_release(geneve); + return 0; + } diff --git a/queue-4.12/ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch b/queue-4.12/ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch new file mode 100644 index 00000000000..fc3a3d1260b --- /dev/null +++ b/queue-4.12/ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch @@ -0,0 +1,76 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Sabrina Dubroca +Date: Thu, 29 Jun 2017 16:56:54 +0200 +Subject: ipv6: dad: don't remove dynamic addresses if link is down + +From: Sabrina Dubroca + + +[ Upstream commit ec8add2a4c9df723c94a863b8fcd6d93c472deed ] + +Currently, when the link for $DEV is down, this command succeeds but the +address is removed immediately by DAD (1): + + ip addr add 1111::12/64 dev $DEV valid_lft 3600 preferred_lft 1800 + +In the same situation, this will succeed and not remove the address (2): + + ip addr add 1111::12/64 dev $DEV + ip addr change 1111::12/64 dev $DEV valid_lft 3600 preferred_lft 1800 + +The comment in addrconf_dad_begin() when !IF_READY makes it look like +this is the intended behavior, but doesn't explain why: + + * If the device is not ready: + * - keep it tentative if it is a permanent address. + * - otherwise, kill it. + +We clearly cannot prevent userspace from doing (2), but we can make (1) +work consistently with (2). + +addrconf_dad_stop() is only called in two cases: if DAD failed, or to +skip DAD when the link is down. In that second case, the fix is to avoid +deleting the address, like we already do for permanent addresses. + +Fixes: 3c21edbd1137 ("[IPV6]: Defer IPv6 device initialization until the link becomes ready.") +Signed-off-by: Sabrina Dubroca +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/addrconf.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1912,15 +1912,7 @@ static void addrconf_dad_stop(struct ine + if (dad_failed) + ifp->flags |= IFA_F_DADFAILED; + +- if (ifp->flags&IFA_F_PERMANENT) { +- spin_lock_bh(&ifp->lock); +- addrconf_del_dad_work(ifp); +- ifp->flags |= IFA_F_TENTATIVE; +- spin_unlock_bh(&ifp->lock); +- if (dad_failed) +- ipv6_ifa_notify(0, ifp); +- in6_ifa_put(ifp); +- } else if (ifp->flags&IFA_F_TEMPORARY) { ++ if (ifp->flags&IFA_F_TEMPORARY) { + struct inet6_ifaddr *ifpub; + spin_lock_bh(&ifp->lock); + ifpub = ifp->ifpub; +@@ -1933,6 +1925,14 @@ static void addrconf_dad_stop(struct ine + spin_unlock_bh(&ifp->lock); + } + ipv6_del_addr(ifp); ++ } else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) { ++ spin_lock_bh(&ifp->lock); ++ addrconf_del_dad_work(ifp); ++ ifp->flags |= IFA_F_TENTATIVE; ++ spin_unlock_bh(&ifp->lock); ++ if (dad_failed) ++ ipv6_ifa_notify(0, ifp); ++ in6_ifa_put(ifp); + } else { + ipv6_del_addr(ifp); + } diff --git a/queue-4.12/liquidio-fix-bug-in-soft-reset-failure-detection.patch b/queue-4.12/liquidio-fix-bug-in-soft-reset-failure-detection.patch new file mode 100644 index 00000000000..10e4415a2ec --- /dev/null +++ b/queue-4.12/liquidio-fix-bug-in-soft-reset-failure-detection.patch @@ -0,0 +1,51 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Derek Chickles +Date: Wed, 5 Jul 2017 11:59:27 -0700 +Subject: liquidio: fix bug in soft reset failure detection + +From: Derek Chickles + + +[ Upstream commit 05a6b4cae8c0cc1680c9dd33a97a49a13c0f01bc ] + +The code that detects a failed soft reset of Octeon is comparing the wrong +value against the reset value of the Octeon SLI_SCRATCH_1 register, +resulting in an inability to detect a soft reset failure. Fix it by using +the correct value in the comparison, which is any non-zero value. + +Fixes: f21fb3ed364b ("Add support of Cavium Liquidio ethernet adapters") +Fixes: c0eab5b3580a ("liquidio: CN23XX firmware download") +Signed-off-by: Derek Chickles +Signed-off-by: Satanand Burla +Signed-off-by: Raghu Vatsavayi +Signed-off-by: Felix Manlunas +Reviewed-by: Leon Romanovsky +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c | 2 +- + drivers/net/ethernet/cavium/liquidio/cn66xx_device.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c ++++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +@@ -221,7 +221,7 @@ static int cn23xx_pf_soft_reset(struct o + /* Wait for 100ms as Octeon resets. */ + mdelay(100); + +- if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1) == 0x1234ULL) { ++ if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1)) { + dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Soft reset failed\n", + oct->octeon_id); + return 1; +--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c ++++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c +@@ -44,7 +44,7 @@ int lio_cn6xxx_soft_reset(struct octeon_ + /* Wait for 10ms as Octeon resets. */ + mdelay(100); + +- if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1) == 0x1234ULL) { ++ if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1)) { + dev_err(&oct->pci_dev->dev, "Soft reset failed\n"); + return 1; + } diff --git a/queue-4.12/net-core-fix-slab-out-of-bounds-in-netdev_stats_to_stats64.patch b/queue-4.12/net-core-fix-slab-out-of-bounds-in-netdev_stats_to_stats64.patch new file mode 100644 index 00000000000..be798317eb9 --- /dev/null +++ b/queue-4.12/net-core-fix-slab-out-of-bounds-in-netdev_stats_to_stats64.patch @@ -0,0 +1,174 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Alban Browaeys +Date: Mon, 3 Jul 2017 03:20:13 +0200 +Subject: net: core: Fix slab-out-of-bounds in netdev_stats_to_stats64 + +From: Alban Browaeys + + +[ Upstream commit 9af9959e142c274f4a30fefb71d97d2b028b337f ] + +commit 9256645af098 ("net/core: relax BUILD_BUG_ON in +netdev_stats_to_stats64") made an attempt to read beyond +the size of the source a possibility. + +Fix to only copy src size to dest. As dest might be bigger than src. + + ================================================================== + BUG: KASAN: slab-out-of-bounds in netdev_stats_to_stats64+0xe/0x30 at addr ffff8801be248b20 + Read of size 192 by task VBoxNetAdpCtl/6734 + CPU: 1 PID: 6734 Comm: VBoxNetAdpCtl Tainted: G O 4.11.4prahal+intel+ #118 + Hardware name: LENOVO 20CDCTO1WW/20CDCTO1WW, BIOS GQET52WW (1.32 ) 05/04/2017 + Call Trace: + dump_stack+0x63/0x86 + kasan_object_err+0x1c/0x70 + kasan_report+0x270/0x520 + ? netdev_stats_to_stats64+0xe/0x30 + ? sched_clock_cpu+0x1b/0x190 + ? __module_address+0x3e/0x3b0 + ? unwind_next_frame+0x1ea/0xb00 + check_memory_region+0x13c/0x1a0 + memcpy+0x23/0x50 + netdev_stats_to_stats64+0xe/0x30 + dev_get_stats+0x1b9/0x230 + rtnl_fill_stats+0x44/0xc00 + ? nla_put+0xc6/0x130 + rtnl_fill_ifinfo+0xe9e/0x3700 + ? rtnl_fill_vfinfo+0xde0/0xde0 + ? sched_clock+0x9/0x10 + ? sched_clock+0x9/0x10 + ? sched_clock_local+0x120/0x130 + ? __module_address+0x3e/0x3b0 + ? unwind_next_frame+0x1ea/0xb00 + ? sched_clock+0x9/0x10 + ? sched_clock+0x9/0x10 + ? sched_clock_cpu+0x1b/0x190 + ? VBoxNetAdpLinuxIOCtlUnlocked+0x14b/0x280 [vboxnetadp] + ? depot_save_stack+0x1d8/0x4a0 + ? depot_save_stack+0x34f/0x4a0 + ? depot_save_stack+0x34f/0x4a0 + ? save_stack+0xb1/0xd0 + ? save_stack_trace+0x16/0x20 + ? save_stack+0x46/0xd0 + ? kasan_slab_alloc+0x12/0x20 + ? __kmalloc_node_track_caller+0x10d/0x350 + ? __kmalloc_reserve.isra.36+0x2c/0xc0 + ? __alloc_skb+0xd0/0x560 + ? rtmsg_ifinfo_build_skb+0x61/0x120 + ? rtmsg_ifinfo.part.25+0x16/0xb0 + ? rtmsg_ifinfo+0x47/0x70 + ? register_netdev+0x15/0x30 + ? vboxNetAdpOsCreate+0xc0/0x1c0 [vboxnetadp] + ? vboxNetAdpCreate+0x210/0x400 [vboxnetadp] + ? VBoxNetAdpLinuxIOCtlUnlocked+0x14b/0x280 [vboxnetadp] + ? do_vfs_ioctl+0x17f/0xff0 + ? SyS_ioctl+0x74/0x80 + ? do_syscall_64+0x182/0x390 + ? __alloc_skb+0xd0/0x560 + ? __alloc_skb+0xd0/0x560 + ? save_stack_trace+0x16/0x20 + ? init_object+0x64/0xa0 + ? ___slab_alloc+0x1ae/0x5c0 + ? ___slab_alloc+0x1ae/0x5c0 + ? __alloc_skb+0xd0/0x560 + ? sched_clock+0x9/0x10 + ? kasan_unpoison_shadow+0x35/0x50 + ? kasan_kmalloc+0xad/0xe0 + ? __kmalloc_node_track_caller+0x246/0x350 + ? __alloc_skb+0xd0/0x560 + ? kasan_unpoison_shadow+0x35/0x50 + ? memset+0x31/0x40 + ? __alloc_skb+0x31f/0x560 + ? napi_consume_skb+0x320/0x320 + ? br_get_link_af_size_filtered+0xb7/0x120 [bridge] + ? if_nlmsg_size+0x440/0x630 + rtmsg_ifinfo_build_skb+0x83/0x120 + rtmsg_ifinfo.part.25+0x16/0xb0 + rtmsg_ifinfo+0x47/0x70 + register_netdevice+0xa2b/0xe50 + ? __kmalloc+0x171/0x2d0 + ? netdev_change_features+0x80/0x80 + register_netdev+0x15/0x30 + vboxNetAdpOsCreate+0xc0/0x1c0 [vboxnetadp] + vboxNetAdpCreate+0x210/0x400 [vboxnetadp] + ? vboxNetAdpComposeMACAddress+0x1d0/0x1d0 [vboxnetadp] + ? kasan_check_write+0x14/0x20 + VBoxNetAdpLinuxIOCtlUnlocked+0x14b/0x280 [vboxnetadp] + ? VBoxNetAdpLinuxOpen+0x20/0x20 [vboxnetadp] + ? lock_acquire+0x11c/0x270 + ? __audit_syscall_entry+0x2fb/0x660 + do_vfs_ioctl+0x17f/0xff0 + ? __audit_syscall_entry+0x2fb/0x660 + ? ioctl_preallocate+0x1d0/0x1d0 + ? __audit_syscall_entry+0x2fb/0x660 + ? kmem_cache_free+0xb2/0x250 + ? syscall_trace_enter+0x537/0xd00 + ? exit_to_usermode_loop+0x100/0x100 + SyS_ioctl+0x74/0x80 + ? do_sys_open+0x350/0x350 + ? do_vfs_ioctl+0xff0/0xff0 + do_syscall_64+0x182/0x390 + entry_SYSCALL64_slow_path+0x25/0x25 + RIP: 0033:0x7f7e39a1ae07 + RSP: 002b:00007ffc6f04c6d8 EFLAGS: 00000206 ORIG_RAX: 0000000000000010 + RAX: ffffffffffffffda RBX: 00007ffc6f04c730 RCX: 00007f7e39a1ae07 + RDX: 00007ffc6f04c730 RSI: 00000000c0207601 RDI: 0000000000000007 + RBP: 00007ffc6f04c700 R08: 00007ffc6f04c780 R09: 0000000000000008 + R10: 0000000000000541 R11: 0000000000000206 R12: 0000000000000007 + R13: 00000000c0207601 R14: 00007ffc6f04c730 R15: 0000000000000012 + Object at ffff8801be248008, in cache kmalloc-4096 size: 4096 + Allocated: + PID = 6734 + save_stack_trace+0x16/0x20 + save_stack+0x46/0xd0 + kasan_kmalloc+0xad/0xe0 + __kmalloc+0x171/0x2d0 + alloc_netdev_mqs+0x8a7/0xbe0 + vboxNetAdpOsCreate+0x65/0x1c0 [vboxnetadp] + vboxNetAdpCreate+0x210/0x400 [vboxnetadp] + VBoxNetAdpLinuxIOCtlUnlocked+0x14b/0x280 [vboxnetadp] + do_vfs_ioctl+0x17f/0xff0 + SyS_ioctl+0x74/0x80 + do_syscall_64+0x182/0x390 + return_from_SYSCALL_64+0x0/0x6a + Freed: + PID = 5600 + save_stack_trace+0x16/0x20 + save_stack+0x46/0xd0 + kasan_slab_free+0x73/0xc0 + kfree+0xe4/0x220 + kvfree+0x25/0x30 + single_release+0x74/0xb0 + __fput+0x265/0x6b0 + ____fput+0x9/0x10 + task_work_run+0xd5/0x150 + exit_to_usermode_loop+0xe2/0x100 + do_syscall_64+0x26c/0x390 + return_from_SYSCALL_64+0x0/0x6a + Memory state around the buggy address: + ffff8801be248a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff8801be248b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + >ffff8801be248b80: 00 00 00 00 00 00 00 00 00 00 00 07 fc fc fc fc + ^ + ffff8801be248c00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff8801be248c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ================================================================== + +Signed-off-by: Alban Browaeys +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 +@@ -7751,7 +7751,7 @@ void netdev_stats_to_stats64(struct rtnl + { + #if BITS_PER_LONG == 64 + BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats)); +- memcpy(stats64, netdev_stats, sizeof(*stats64)); ++ memcpy(stats64, netdev_stats, sizeof(*netdev_stats)); + /* zero out counters that only exist in rtnl_link_stats64 */ + memset((char *)stats64 + sizeof(*netdev_stats), 0, + sizeof(*stats64) - sizeof(*netdev_stats)); diff --git a/queue-4.12/net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch b/queue-4.12/net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch new file mode 100644 index 00000000000..8bf83483bc6 --- /dev/null +++ b/queue-4.12/net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch @@ -0,0 +1,92 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: David Ahern +Date: Wed, 5 Jul 2017 14:41:46 -0600 +Subject: net: ipv6: Compare lwstate in detecting duplicate nexthops + +From: David Ahern + + +[ Upstream commit f06b7549b79e29a672336d4e134524373fb7a232 ] + +Lennert reported a failure to add different mpls encaps in a multipath +route: + + $ ip -6 route add 1234::/16 \ + nexthop encap mpls 10 via fe80::1 dev ens3 \ + nexthop encap mpls 20 via fe80::1 dev ens3 + RTNETLINK answers: File exists + +The problem is that the duplicate nexthop detection does not compare +lwtunnel configuration. Add it. + +Fixes: 19e42e451506 ("ipv6: support for fib route lwtunnel encap attributes") +Signed-off-by: David Ahern +Reported-by: João Taveira Araújo +Reported-by: Lennert Buytenhek +Acked-by: Roopa Prabhu +Tested-by: Lennert Buytenhek +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/ip6_route.h | 8 ++++++++ + net/ipv6/ip6_fib.c | 5 +---- + net/ipv6/route.c | 8 +------- + 3 files changed, 10 insertions(+), 11 deletions(-) + +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -22,6 +22,7 @@ struct route_info { + #include + #include + #include ++#include + #include + #include + #include +@@ -233,4 +234,11 @@ static inline struct in6_addr *rt6_nexth + return daddr; + } + ++static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b) ++{ ++ return a->dst.dev == b->dst.dev && ++ a->rt6i_idev == b->rt6i_idev && ++ ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) && ++ !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate); ++} + #endif +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -784,10 +784,7 @@ static int fib6_add_rt2node(struct fib6_ + goto next_iter; + } + +- if (iter->dst.dev == rt->dst.dev && +- iter->rt6i_idev == rt->rt6i_idev && +- ipv6_addr_equal(&iter->rt6i_gateway, +- &rt->rt6i_gateway)) { ++ if (rt6_duplicate_nexthop(iter, rt)) { + if (rt->rt6i_nsiblings) + rt->rt6i_nsiblings = 0; + if (!(iter->rt6i_flags & RTF_EXPIRES)) +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -3048,17 +3048,11 @@ static int ip6_route_info_append(struct + struct rt6_info *rt, struct fib6_config *r_cfg) + { + struct rt6_nh *nh; +- struct rt6_info *rtnh; + int err = -EEXIST; + + list_for_each_entry(nh, rt6_nh_list, next) { + /* check if rt6_info already exists */ +- rtnh = nh->rt6_info; +- +- if (rtnh->dst.dev == rt->dst.dev && +- rtnh->rt6i_idev == rt->rt6i_idev && +- ipv6_addr_equal(&rtnh->rt6i_gateway, +- &rt->rt6i_gateway)) ++ if (rt6_duplicate_nexthop(nh->rt6_info, rt)) + return err; + } + diff --git a/queue-4.12/net-mlx5-cancel-delayed-recovery-work-when-unloading-the-driver.patch b/queue-4.12/net-mlx5-cancel-delayed-recovery-work-when-unloading-the-driver.patch new file mode 100644 index 00000000000..06fb21ad905 --- /dev/null +++ b/queue-4.12/net-mlx5-cancel-delayed-recovery-work-when-unloading-the-driver.patch @@ -0,0 +1,97 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Mohamad Haj Yahia +Date: Thu, 30 Mar 2017 17:09:00 +0300 +Subject: net/mlx5: Cancel delayed recovery work when unloading the driver + +From: Mohamad Haj Yahia + + +[ Upstream commit 2a0165a034ac024b60cca49c61e46f4afa2e4d98 ] + +Draining the health workqueue will ignore future health works including +the one that report hardware failure and thus we can't enter error state +Instead cancel the recovery flow and make sure only recovery flow won't +be scheduled. + +Fixes: 5e44fca50470 ('net/mlx5: Only cancel recovery work when cleaning up device') +Signed-off-by: Mohamad Haj Yahia +Signed-off-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/health.c | 15 ++++++++++++++- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- + include/linux/mlx5/driver.h | 1 + + 3 files changed, 16 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c +@@ -67,6 +67,7 @@ enum { + + enum { + MLX5_DROP_NEW_HEALTH_WORK, ++ MLX5_DROP_NEW_RECOVERY_WORK, + }; + + static u8 get_nic_state(struct mlx5_core_dev *dev) +@@ -193,7 +194,7 @@ static void health_care(struct work_stru + mlx5_handle_bad_state(dev); + + spin_lock(&health->wq_lock); +- if (!test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags)) ++ if (!test_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags)) + schedule_delayed_work(&health->recover_work, recover_delay); + else + dev_err(&dev->pdev->dev, +@@ -313,6 +314,7 @@ void mlx5_start_health_poll(struct mlx5_ + init_timer(&health->timer); + health->sick = 0; + clear_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags); ++ clear_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags); + health->health = &dev->iseg->health; + health->health_counter = &dev->iseg->health_counter; + +@@ -335,11 +337,22 @@ void mlx5_drain_health_wq(struct mlx5_co + + spin_lock(&health->wq_lock); + set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags); ++ set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags); + spin_unlock(&health->wq_lock); + cancel_delayed_work_sync(&health->recover_work); + cancel_work_sync(&health->work); + } + ++void mlx5_drain_health_recovery(struct mlx5_core_dev *dev) ++{ ++ struct mlx5_core_health *health = &dev->priv.health; ++ ++ spin_lock(&health->wq_lock); ++ set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags); ++ spin_unlock(&health->wq_lock); ++ cancel_delayed_work_sync(&dev->priv.health.recover_work); ++} ++ + void mlx5_health_cleanup(struct mlx5_core_dev *dev) + { + struct mlx5_core_health *health = &dev->priv.health; +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1228,7 +1228,7 @@ static int mlx5_unload_one(struct mlx5_c + int err = 0; + + if (cleanup) +- mlx5_drain_health_wq(dev); ++ mlx5_drain_health_recovery(dev); + + mutex_lock(&dev->intf_state_mutex); + if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) { +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -925,6 +925,7 @@ int mlx5_health_init(struct mlx5_core_de + void mlx5_start_health_poll(struct mlx5_core_dev *dev); + void mlx5_stop_health_poll(struct mlx5_core_dev *dev); + void mlx5_drain_health_wq(struct mlx5_core_dev *dev); ++void mlx5_drain_health_recovery(struct mlx5_core_dev *dev); + int mlx5_buf_alloc_node(struct mlx5_core_dev *dev, int size, + struct mlx5_buf *buf, int node); + int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, struct mlx5_buf *buf); diff --git a/queue-4.12/net-mlx5-fix-driver-load-error-flow-when-firmware-is-stuck.patch b/queue-4.12/net-mlx5-fix-driver-load-error-flow-when-firmware-is-stuck.patch new file mode 100644 index 00000000000..41e533110bb --- /dev/null +++ b/queue-4.12/net-mlx5-fix-driver-load-error-flow-when-firmware-is-stuck.patch @@ -0,0 +1,32 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Gal Pressman +Date: Mon, 19 Jun 2017 18:25:59 +0300 +Subject: net/mlx5: Fix driver load error flow when firmware is stuck + +From: Gal Pressman + + +[ Upstream commit 8ce59b16b4b6eacedaec1f7b652b4781cdbfe15f ] + +When wait for firmware init fails, previous code would mistakenly +return success and cause inconsistency in the driver state. + +Fixes: 6c780a0267b8 ("net/mlx5: Wait for FW readiness before initializing command interface") +Signed-off-by: Gal Pressman +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1020,7 +1020,7 @@ static int mlx5_load_one(struct mlx5_cor + if (err) { + dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n", + FW_PRE_INIT_TIMEOUT_MILI); +- goto out; ++ goto out_err; + } + + err = mlx5_cmd_init(dev); diff --git a/queue-4.12/net-mlx5e-fix-tx-carrier-errors-report-in-get-stats-ndo.patch b/queue-4.12/net-mlx5e-fix-tx-carrier-errors-report-in-get-stats-ndo.patch new file mode 100644 index 00000000000..81141adfebd --- /dev/null +++ b/queue-4.12/net-mlx5e-fix-tx-carrier-errors-report-in-get-stats-ndo.patch @@ -0,0 +1,32 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Gal Pressman +Date: Sun, 25 Jun 2017 16:46:25 +0300 +Subject: net/mlx5e: Fix TX carrier errors report in get stats ndo + +From: Gal Pressman + + +[ Upstream commit 8ff93de7668bd81bc8efa819d1184ebd48fae72d ] + +Symbol error during carrier counter from PPCNT was mistakenly reported as +TX carrier errors in get_stats ndo, although it's an RX counter. + +Fixes: 269e6b3af3bf ("net/mlx5e: Report additional error statistics in get stats ndo") +Signed-off-by: Gal Pressman +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3053,8 +3053,6 @@ mlx5e_get_stats(struct net_device *dev, + PPORT_802_3_GET(pstats, a_frame_check_sequence_errors); + stats->rx_frame_errors = PPORT_802_3_GET(pstats, a_alignment_errors); + stats->tx_aborted_errors = PPORT_2863_GET(pstats, if_out_discards); +- stats->tx_carrier_errors = +- PPORT_802_3_GET(pstats, a_symbol_error_during_carrier); + stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + + stats->rx_frame_errors; + stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors; diff --git a/queue-4.12/net-mlx5e-initialize-cee-s-getpermhwaddr-address-buffer-to-0xff.patch b/queue-4.12/net-mlx5e-initialize-cee-s-getpermhwaddr-address-buffer-to-0xff.patch new file mode 100644 index 00000000000..819d5204dd8 --- /dev/null +++ b/queue-4.12/net-mlx5e-initialize-cee-s-getpermhwaddr-address-buffer-to-0xff.patch @@ -0,0 +1,40 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Huy Nguyen +Date: Thu, 29 Jun 2017 16:50:01 -0500 +Subject: net/mlx5e: Initialize CEE's getpermhwaddr address buffer to 0xff + +From: Huy Nguyen + + +[ Upstream commit d968f0f2e4404152f37ed2384b4a2269dd2dae5a ] + +Latest change in open-lldp code uses bytes 6-11 of perm_addr buffer +as the Ethernet source address for the host TLV packet. +Since our driver does not fill these bytes, they stay at zero and +the open-lldp code ends up sending the TLV packet with zero source +address and the switch drops this packet. + +The fix is to initialize these bytes to 0xff. The open-lldp code +considers 0xff:ff:ff:ff:ff:ff as the invalid address and falls back to +use the host's mac address as the Ethernet source address. + +Fixes: 3a6a931dfb8e ("net/mlx5e: Support DCBX CEE API") +Signed-off-by: Huy Nguyen +Reviewed-by: Daniel Jurgens +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -464,6 +464,8 @@ static void mlx5e_dcbnl_getpermhwaddr(st + if (!perm_addr) + return; + ++ memset(perm_addr, 0xff, MAX_ADDR_LEN); ++ + mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr); + } + diff --git a/queue-4.12/rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch b/queue-4.12/rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch new file mode 100644 index 00000000000..aff7aa24faf --- /dev/null +++ b/queue-4.12/rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch @@ -0,0 +1,38 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Sowmini Varadhan +Date: Thu, 6 Jul 2017 08:15:06 -0700 +Subject: rds: tcp: use sock_create_lite() to create the accept socket + +From: Sowmini Varadhan + + +[ Upstream commit 0933a578cd55b02dc80f219dc8f2efb17ec61c9a ] + +There are two problems with calling sock_create_kern() from +rds_tcp_accept_one() +1. it sets up a new_sock->sk that is wasteful, because this ->sk + is going to get replaced by inet_accept() in the subsequent ->accept() +2. The new_sock->sk is a leaked reference in sock_graft() which + expects to find a null parent->sk + +Avoid these problems by calling sock_create_lite(). + +Signed-off-by: Sowmini Varadhan +Acked-by: Santosh Shilimkar +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/tcp_listen.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/rds/tcp_listen.c ++++ b/net/rds/tcp_listen.c +@@ -125,7 +125,7 @@ int rds_tcp_accept_one(struct socket *so + if (!sock) /* module unload or netns delete in progress */ + return -ENETUNREACH; + +- ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, ++ ret = sock_create_lite(sock->sk->sk_family, + sock->sk->sk_type, sock->sk->sk_protocol, + &new_sock); + if (ret) diff --git a/queue-4.12/sfc-don-t-read-beyond-unicast-address-list.patch b/queue-4.12/sfc-don-t-read-beyond-unicast-address-list.patch new file mode 100644 index 00000000000..7e334a3c1e7 --- /dev/null +++ b/queue-4.12/sfc-don-t-read-beyond-unicast-address-list.patch @@ -0,0 +1,63 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Bert Kenward +Date: Wed, 12 Jul 2017 17:19:41 +0100 +Subject: sfc: don't read beyond unicast address list + +From: Bert Kenward + + +[ Upstream commit c70d68150f71b84cea6997a53493e17bf18a54db ] + +If we have more than 32 unicast MAC addresses assigned to an interface +we will read beyond the end of the address table in the driver when +adding filters. The next 256 entries store multicast addresses, so we +will end up attempting to insert duplicate filters, which is mostly +harmless. If we add more than 288 unicast addresses we will then read +past the multicast address table, which is likely to be more exciting. + +Fixes: 12fb0da45c9a ("sfc: clean fallbacks between promisc/normal in efx_ef10_filter_sync_rx_mode") +Signed-off-by: Bert Kenward +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sfc/ef10.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/sfc/ef10.c ++++ b/drivers/net/ethernet/sfc/ef10.c +@@ -5034,12 +5034,9 @@ static void efx_ef10_filter_uc_addr_list + struct efx_ef10_filter_table *table = efx->filter_state; + struct net_device *net_dev = efx->net_dev; + struct netdev_hw_addr *uc; +- int addr_count; + unsigned int i; + +- addr_count = netdev_uc_count(net_dev); + table->uc_promisc = !!(net_dev->flags & IFF_PROMISC); +- table->dev_uc_count = 1 + addr_count; + ether_addr_copy(table->dev_uc_list[0].addr, net_dev->dev_addr); + i = 1; + netdev_for_each_uc_addr(uc, net_dev) { +@@ -5050,6 +5047,8 @@ static void efx_ef10_filter_uc_addr_list + ether_addr_copy(table->dev_uc_list[i].addr, uc->addr); + i++; + } ++ ++ table->dev_uc_count = i; + } + + static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx) +@@ -5057,12 +5056,11 @@ static void efx_ef10_filter_mc_addr_list + struct efx_ef10_filter_table *table = efx->filter_state; + struct net_device *net_dev = efx->net_dev; + struct netdev_hw_addr *mc; +- unsigned int i, addr_count; ++ unsigned int i; + + table->mc_overflow = false; + table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI)); + +- addr_count = netdev_mc_count(net_dev); + i = 0; + netdev_for_each_mc_addr(mc, net_dev) { + if (i >= EFX_EF10_FILTER_DEV_MC_MAX) { diff --git a/queue-4.12/staging-android-uapi-drop-definitions-of-removed-ion_ioc_-free-share-ioctls.patch b/queue-4.12/staging-android-uapi-drop-definitions-of-removed-ion_ioc_-free-share-ioctls.patch new file mode 100644 index 00000000000..b3f960eeaac --- /dev/null +++ b/queue-4.12/staging-android-uapi-drop-definitions-of-removed-ion_ioc_-free-share-ioctls.patch @@ -0,0 +1,48 @@ +From f7a320ffebe2bdce3a189ecb531a401c653f754f Mon Sep 17 00:00:00 2001 +From: Gleb Fotengauer-Malinovskiy +Date: Tue, 30 May 2017 17:11:35 +0300 +Subject: staging: android: uapi: drop definitions of removed ION_IOC_{FREE,SHARE} ioctls + +From: Gleb Fotengauer-Malinovskiy + +commit f7a320ffebe2bdce3a189ecb531a401c653f754f upstream. + +This problem was found by strace ioctl list generator. + +Fixes: 15c6098cfec5 ("staging: android: ion: Remove ion_handle and ion_client") +Signed-off-by: Gleb Fotengauer-Malinovskiy +Acked-by: Laura Abbott +Cc: "Dmitry V. Levin" +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/android/uapi/ion.h | 18 ------------------ + 1 file changed, 18 deletions(-) + +--- a/drivers/staging/android/uapi/ion.h ++++ b/drivers/staging/android/uapi/ion.h +@@ -131,24 +131,6 @@ struct ion_heap_query { + struct ion_allocation_data) + + /** +- * DOC: ION_IOC_FREE - free memory +- * +- * Takes an ion_handle_data struct and frees the handle. +- */ +-#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) +- +-/** +- * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation +- * +- * Takes an ion_fd_data struct with the handle field populated with a valid +- * opaque handle. Returns the struct with the fd field set to a file +- * descriptor open in the current address space. This file descriptor +- * can then be passed to another process. The corresponding opaque handle can +- * be retrieved via ION_IOC_IMPORT. +- */ +-#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) +- +-/** + * DOC: ION_IOC_HEAP_QUERY - information about available heaps + * + * Takes an ion_heap_query structure and populates information about diff --git a/queue-4.12/tap-convert-a-mutex-to-a-spinlock.patch b/queue-4.12/tap-convert-a-mutex-to-a-spinlock.patch new file mode 100644 index 00000000000..48c5b09b3c7 --- /dev/null +++ b/queue-4.12/tap-convert-a-mutex-to-a-spinlock.patch @@ -0,0 +1,95 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: WANG Cong +Date: Mon, 10 Jul 2017 10:05:50 -0700 +Subject: tap: convert a mutex to a spinlock + +From: WANG Cong + + +[ Upstream commit ffa423fb3251f8737303ffc3b0659e86e501808e ] + +We are not allowed to block on the RCU reader side, so can't +just hold the mutex as before. As a quick fix, convert it to +a spinlock. + +Fixes: d9f1f61c0801 ("tap: Extending tap device create/destroy APIs") +Reported-by: Christian Borntraeger +Tested-by: Christian Borntraeger +Cc: Sainath Grandhi +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tap.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/net/tap.c ++++ b/drivers/net/tap.c +@@ -106,7 +106,7 @@ struct major_info { + struct rcu_head rcu; + dev_t major; + struct idr minor_idr; +- struct mutex minor_lock; ++ spinlock_t minor_lock; + const char *device_name; + struct list_head next; + }; +@@ -416,15 +416,15 @@ int tap_get_minor(dev_t major, struct ta + goto unlock; + } + +- mutex_lock(&tap_major->minor_lock); +- retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_KERNEL); ++ spin_lock(&tap_major->minor_lock); ++ retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_ATOMIC); + if (retval >= 0) { + tap->minor = retval; + } else if (retval == -ENOSPC) { + netdev_err(tap->dev, "Too many tap devices\n"); + retval = -EINVAL; + } +- mutex_unlock(&tap_major->minor_lock); ++ spin_unlock(&tap_major->minor_lock); + + unlock: + rcu_read_unlock(); +@@ -442,12 +442,12 @@ void tap_free_minor(dev_t major, struct + goto unlock; + } + +- mutex_lock(&tap_major->minor_lock); ++ spin_lock(&tap_major->minor_lock); + if (tap->minor) { + idr_remove(&tap_major->minor_idr, tap->minor); + tap->minor = 0; + } +- mutex_unlock(&tap_major->minor_lock); ++ spin_unlock(&tap_major->minor_lock); + + unlock: + rcu_read_unlock(); +@@ -467,13 +467,13 @@ static struct tap_dev *dev_get_by_tap_fi + goto unlock; + } + +- mutex_lock(&tap_major->minor_lock); ++ spin_lock(&tap_major->minor_lock); + tap = idr_find(&tap_major->minor_idr, minor); + if (tap) { + dev = tap->dev; + dev_hold(dev); + } +- mutex_unlock(&tap_major->minor_lock); ++ spin_unlock(&tap_major->minor_lock); + + unlock: + rcu_read_unlock(); +@@ -1227,7 +1227,7 @@ static int tap_list_add(dev_t major, con + tap_major->major = MAJOR(major); + + idr_init(&tap_major->minor_idr); +- mutex_init(&tap_major->minor_lock); ++ spin_lock_init(&tap_major->minor_lock); + + tap_major->device_name = device_name; + diff --git a/queue-4.12/virtio-net-fix-leaking-of-ctx-array.patch b/queue-4.12/virtio-net-fix-leaking-of-ctx-array.patch new file mode 100644 index 00000000000..622324fe244 --- /dev/null +++ b/queue-4.12/virtio-net-fix-leaking-of-ctx-array.patch @@ -0,0 +1,29 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Jason Wang +Date: Fri, 7 Jul 2017 19:56:09 +0800 +Subject: virtio-net: fix leaking of ctx array + +From: Jason Wang + + +[ Upstream commit 55281621b6047d2ffb934a0b984ab0cdb1ad1d76 ] + +Fixes: commit d45b897b11ea ("virtio_net: allow specifying context for rx") +Signed-off-by: Jason Wang +Acked-by: Michael S. Tsirkin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -2221,6 +2221,7 @@ static int virtnet_find_vqs(struct virtn + kfree(names); + kfree(callbacks); + kfree(vqs); ++ kfree(ctx); + + return 0; + diff --git a/queue-4.12/vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch b/queue-4.12/vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch new file mode 100644 index 00000000000..64b42f9f40c --- /dev/null +++ b/queue-4.12/vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch @@ -0,0 +1,117 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Nikolay Aleksandrov +Date: Thu, 6 Jul 2017 15:24:40 +0300 +Subject: vrf: fix bug_on triggered by rx when destroying a vrf + +From: Nikolay Aleksandrov + + +[ Upstream commit f630c38ef0d785101363a8992bbd4f302180f86f ] + +When destroying a VRF device we cleanup the slaves in its ndo_uninit() +function, but that causes packets to be switched (skb->dev == vrf being +destroyed) even though we're pass the point where the VRF should be +receiving any packets while it is being dismantled. This causes a BUG_ON +to trigger if we have raw sockets (trace below). +The reason is that the inetdev of the VRF has been destroyed but we're +still sending packets up the stack with it, so let's free the slaves in +the dellink callback as David Ahern suggested. + +Note that this fix doesn't prevent packets from going up when the VRF +device is admin down. + +[ 35.631371] ------------[ cut here ]------------ +[ 35.631603] kernel BUG at net/ipv4/fib_frontend.c:285! +[ 35.631854] invalid opcode: 0000 [#1] SMP +[ 35.631977] Modules linked in: +[ 35.632081] CPU: 2 PID: 22 Comm: ksoftirqd/2 Not tainted 4.12.0-rc7+ #45 +[ 35.632247] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 35.632477] task: ffff88005ad68000 task.stack: ffff88005ad64000 +[ 35.632632] RIP: 0010:fib_compute_spec_dst+0xfc/0x1ee +[ 35.632769] RSP: 0018:ffff88005ad67978 EFLAGS: 00010202 +[ 35.632910] RAX: 0000000000000001 RBX: ffff880059a7f200 RCX: 0000000000000000 +[ 35.633084] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff82274af0 +[ 35.633256] RBP: ffff88005ad679f8 R08: 000000000001ef70 R09: 0000000000000046 +[ 35.633430] R10: ffff88005ad679f8 R11: ffff880037731cb0 R12: 0000000000000001 +[ 35.633603] R13: ffff8800599e3000 R14: 0000000000000000 R15: ffff8800599cb852 +[ 35.634114] FS: 0000000000000000(0000) GS:ffff88005d900000(0000) knlGS:0000000000000000 +[ 35.634306] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 35.634456] CR2: 00007f3563227095 CR3: 000000000201d000 CR4: 00000000000406e0 +[ 35.634632] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 35.634865] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 35.635055] Call Trace: +[ 35.635271] ? __lock_acquire+0xf0d/0x1117 +[ 35.635522] ipv4_pktinfo_prepare+0x82/0x151 +[ 35.635831] raw_rcv_skb+0x17/0x3c +[ 35.636062] raw_rcv+0xe5/0xf7 +[ 35.636287] raw_local_deliver+0x169/0x1d9 +[ 35.636534] ip_local_deliver_finish+0x87/0x1c4 +[ 35.636820] ip_local_deliver+0x63/0x7f +[ 35.637058] ip_rcv_finish+0x340/0x3a1 +[ 35.637295] ip_rcv+0x314/0x34a +[ 35.637525] __netif_receive_skb_core+0x49f/0x7c5 +[ 35.637780] ? lock_acquire+0x13f/0x1d7 +[ 35.638018] ? lock_acquire+0x15e/0x1d7 +[ 35.638259] __netif_receive_skb+0x1e/0x94 +[ 35.638502] ? __netif_receive_skb+0x1e/0x94 +[ 35.638748] netif_receive_skb_internal+0x74/0x300 +[ 35.639002] ? dev_gro_receive+0x2ed/0x411 +[ 35.639246] ? lock_is_held_type+0xc4/0xd2 +[ 35.639491] napi_gro_receive+0x105/0x1a0 +[ 35.639736] receive_buf+0xc32/0xc74 +[ 35.639965] ? detach_buf+0x67/0x153 +[ 35.640201] ? virtqueue_get_buf_ctx+0x120/0x176 +[ 35.640453] virtnet_poll+0x128/0x1c5 +[ 35.640690] net_rx_action+0x103/0x343 +[ 35.640932] __do_softirq+0x1c7/0x4b7 +[ 35.641171] run_ksoftirqd+0x23/0x5c +[ 35.641403] smpboot_thread_fn+0x24f/0x26d +[ 35.641646] ? sort_range+0x22/0x22 +[ 35.641878] kthread+0x129/0x131 +[ 35.642104] ? __list_add+0x31/0x31 +[ 35.642335] ? __list_add+0x31/0x31 +[ 35.642568] ret_from_fork+0x2a/0x40 +[ 35.642804] Code: 05 bd 87 a3 00 01 e8 1f ef 98 ff 4d 85 f6 48 c7 c7 f0 4a 27 82 41 0f 94 c4 31 c9 31 d2 41 0f b6 f4 e8 04 71 a1 ff 45 84 e4 74 02 <0f> 0b 0f b7 93 c4 00 00 00 4d 8b a5 80 05 00 00 48 03 93 d0 00 +[ 35.644342] RIP: fib_compute_spec_dst+0xfc/0x1ee RSP: ffff88005ad67978 + +Fixes: 193125dbd8eb ("net: Introduce VRF device driver") +Reported-by: Chris Cormier +Signed-off-by: Nikolay Aleksandrov +Acked-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vrf.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -926,15 +926,10 @@ static int vrf_del_slave(struct net_devi + static void vrf_dev_uninit(struct net_device *dev) + { + struct net_vrf *vrf = netdev_priv(dev); +- struct net_device *port_dev; +- struct list_head *iter; + + vrf_rtable_release(dev, vrf); + vrf_rt6_release(dev, vrf); + +- netdev_for_each_lower_dev(dev, port_dev, iter) +- vrf_del_slave(dev, port_dev); +- + free_percpu(dev->dstats); + dev->dstats = NULL; + } +@@ -1389,6 +1384,12 @@ static int vrf_validate(struct nlattr *t + + static void vrf_dellink(struct net_device *dev, struct list_head *head) + { ++ struct net_device *port_dev; ++ struct list_head *iter; ++ ++ netdev_for_each_lower_dev(dev, port_dev, iter) ++ vrf_del_slave(dev, port_dev); ++ + unregister_netdevice_queue(dev, head); + } + diff --git a/queue-4.12/vxlan-fix-hlist-corruption.patch b/queue-4.12/vxlan-fix-hlist-corruption.patch new file mode 100644 index 00000000000..10050de931b --- /dev/null +++ b/queue-4.12/vxlan-fix-hlist-corruption.patch @@ -0,0 +1,119 @@ +From foo@baz Mon Jul 17 18:46:41 CEST 2017 +From: Jiri Benc +Date: Sun, 2 Jul 2017 19:00:57 +0200 +Subject: vxlan: fix hlist corruption + +From: Jiri Benc + + +[ Upstream commit 69e766612c4bcb79e19cebed9eed61d4222c1d47 ] + +It's not a good idea to add the same hlist_node to two different hash lists. +This leads to various hard to debug memory corruptions. + +Fixes: b1be00a6c39f ("vxlan: support both IPv4 and IPv6 sockets in a single vxlan device") +Signed-off-by: Jiri Benc +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan.c | 30 ++++++++++++++++++++---------- + include/net/vxlan.h | 10 +++++++++- + 2 files changed, 29 insertions(+), 11 deletions(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -228,15 +228,15 @@ static struct vxlan_sock *vxlan_find_soc + + static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni) + { +- struct vxlan_dev *vxlan; ++ struct vxlan_dev_node *node; + + /* For flow based devices, map all packets to VNI 0 */ + if (vs->flags & VXLAN_F_COLLECT_METADATA) + vni = 0; + +- hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { +- if (vxlan->default_dst.remote_vni == vni) +- return vxlan; ++ hlist_for_each_entry_rcu(node, vni_head(vs, vni), hlist) { ++ if (node->vxlan->default_dst.remote_vni == vni) ++ return node->vxlan; + } + + return NULL; +@@ -2365,17 +2365,22 @@ static void vxlan_vs_del_dev(struct vxla + struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + + spin_lock(&vn->sock_lock); +- hlist_del_init_rcu(&vxlan->hlist); ++ hlist_del_init_rcu(&vxlan->hlist4.hlist); ++#if IS_ENABLED(CONFIG_IPV6) ++ hlist_del_init_rcu(&vxlan->hlist6.hlist); ++#endif + spin_unlock(&vn->sock_lock); + } + +-static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) ++static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan, ++ struct vxlan_dev_node *node) + { + struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + __be32 vni = vxlan->default_dst.remote_vni; + ++ node->vxlan = vxlan; + spin_lock(&vn->sock_lock); +- hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni)); ++ hlist_add_head_rcu(&node->hlist, vni_head(vs, vni)); + spin_unlock(&vn->sock_lock); + } + +@@ -2819,6 +2824,7 @@ static int __vxlan_sock_add(struct vxlan + { + struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + struct vxlan_sock *vs = NULL; ++ struct vxlan_dev_node *node; + + if (!vxlan->cfg.no_share) { + spin_lock(&vn->sock_lock); +@@ -2836,12 +2842,16 @@ static int __vxlan_sock_add(struct vxlan + if (IS_ERR(vs)) + return PTR_ERR(vs); + #if IS_ENABLED(CONFIG_IPV6) +- if (ipv6) ++ if (ipv6) { + rcu_assign_pointer(vxlan->vn6_sock, vs); +- else ++ node = &vxlan->hlist6; ++ } else + #endif ++ { + rcu_assign_pointer(vxlan->vn4_sock, vs); +- vxlan_vs_add_dev(vs, vxlan); ++ node = &vxlan->hlist4; ++ } ++ vxlan_vs_add_dev(vs, vxlan, node); + return 0; + } + +--- a/include/net/vxlan.h ++++ b/include/net/vxlan.h +@@ -221,9 +221,17 @@ struct vxlan_config { + bool no_share; + }; + ++struct vxlan_dev_node { ++ struct hlist_node hlist; ++ struct vxlan_dev *vxlan; ++}; ++ + /* Pseudo network device */ + struct vxlan_dev { +- struct hlist_node hlist; /* vni hash table */ ++ struct vxlan_dev_node hlist4; /* vni hash table for IPv4 socket */ ++#if IS_ENABLED(CONFIG_IPV6) ++ struct vxlan_dev_node hlist6; /* vni hash table for IPv6 socket */ ++#endif + struct list_head next; /* vxlan's per namespace list */ + struct vxlan_sock __rcu *vn4_sock; /* listening socket for IPv4 */ + #if IS_ENABLED(CONFIG_IPV6)