From: Greg Kroah-Hartman Date: Mon, 21 Jun 2021 11:01:52 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v5.4.128~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c12a205c77074c30c1bb14e270e8cb7fe70ca82;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: dmaengine-pl330-fix-wrong-usage-of-spinlock-flags-in-dma_cyclc.patch net-bridge-fix-vlan-tunnel-dst-null-pointer-dereference.patch net-bridge-fix-vlan-tunnel-dst-refcnt-when-egressing.patch --- diff --git a/queue-4.14/dmaengine-pl330-fix-wrong-usage-of-spinlock-flags-in-dma_cyclc.patch b/queue-4.14/dmaengine-pl330-fix-wrong-usage-of-spinlock-flags-in-dma_cyclc.patch new file mode 100644 index 00000000000..c2010518f80 --- /dev/null +++ b/queue-4.14/dmaengine-pl330-fix-wrong-usage-of-spinlock-flags-in-dma_cyclc.patch @@ -0,0 +1,52 @@ +From 4ad5dd2d7876d79507a20f026507d1a93b8fff10 Mon Sep 17 00:00:00 2001 +From: Bumyong Lee +Date: Fri, 7 May 2021 15:36:47 +0900 +Subject: dmaengine: pl330: fix wrong usage of spinlock flags in dma_cyclc + +From: Bumyong Lee + +commit 4ad5dd2d7876d79507a20f026507d1a93b8fff10 upstream. + +flags varible which is the input parameter of pl330_prep_dma_cyclic() +should not be used by spinlock_irq[save/restore] function. + +Signed-off-by: Jongho Park +Signed-off-by: Bumyong Lee +Signed-off-by: Chanho Park +Link: https://lore.kernel.org/r/20210507063647.111209-1-chanho61.park@samsung.com +Fixes: f6f2421c0a1c ("dmaengine: pl330: Merge dma_pl330_dmac and pl330_dmac structs") +Cc: stable@vger.kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/pl330.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2563,13 +2563,15 @@ static struct dma_async_tx_descriptor *p + for (i = 0; i < len / period_len; i++) { + desc = pl330_get_desc(pch); + if (!desc) { ++ unsigned long iflags; ++ + dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n", + __func__, __LINE__); + + if (!first) + return NULL; + +- spin_lock_irqsave(&pl330->pool_lock, flags); ++ spin_lock_irqsave(&pl330->pool_lock, iflags); + + while (!list_empty(&first->node)) { + desc = list_entry(first->node.next, +@@ -2579,7 +2581,7 @@ static struct dma_async_tx_descriptor *p + + list_move_tail(&first->node, &pl330->desc_pool); + +- spin_unlock_irqrestore(&pl330->pool_lock, flags); ++ spin_unlock_irqrestore(&pl330->pool_lock, iflags); + + return NULL; + } diff --git a/queue-4.14/net-bridge-fix-vlan-tunnel-dst-null-pointer-dereference.patch b/queue-4.14/net-bridge-fix-vlan-tunnel-dst-null-pointer-dereference.patch new file mode 100644 index 00000000000..7963ab25d50 --- /dev/null +++ b/queue-4.14/net-bridge-fix-vlan-tunnel-dst-null-pointer-dereference.patch @@ -0,0 +1,135 @@ +From 58e2071742e38f29f051b709a5cca014ba51166f Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Thu, 10 Jun 2021 15:04:10 +0300 +Subject: net: bridge: fix vlan tunnel dst null pointer dereference + +From: Nikolay Aleksandrov + +commit 58e2071742e38f29f051b709a5cca014ba51166f upstream. + +This patch fixes a tunnel_dst null pointer dereference due to lockless +access in the tunnel egress path. When deleting a vlan tunnel the +tunnel_dst pointer is set to NULL without waiting a grace period (i.e. +while it's still usable) and packets egressing are dereferencing it +without checking. Use READ/WRITE_ONCE to annotate the lockless use of +tunnel_id, use RCU for accessing tunnel_dst and make sure it is read +only once and checked in the egress path. The dst is already properly RCU +protected so we don't need to do anything fancy than to make sure +tunnel_id and tunnel_dst are read only once and checked in the egress path. + +Cc: stable@vger.kernel.org +Fixes: 11538d039ac6 ("bridge: vlan dst_metadata hooks in ingress and egress paths") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_private.h | 4 ++-- + net/bridge/br_vlan_tunnel.c | 38 ++++++++++++++++++++++++-------------- + 2 files changed, 26 insertions(+), 16 deletions(-) + +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -93,8 +93,8 @@ struct br_vlan_stats { + }; + + struct br_tunnel_info { +- __be64 tunnel_id; +- struct metadata_dst *tunnel_dst; ++ __be64 tunnel_id; ++ struct metadata_dst __rcu *tunnel_dst; + }; + + /** +--- a/net/bridge/br_vlan_tunnel.c ++++ b/net/bridge/br_vlan_tunnel.c +@@ -46,26 +46,33 @@ static struct net_bridge_vlan *br_vlan_t + br_vlan_tunnel_rht_params); + } + ++static void vlan_tunnel_info_release(struct net_bridge_vlan *vlan) ++{ ++ struct metadata_dst *tdst = rtnl_dereference(vlan->tinfo.tunnel_dst); ++ ++ WRITE_ONCE(vlan->tinfo.tunnel_id, 0); ++ RCU_INIT_POINTER(vlan->tinfo.tunnel_dst, NULL); ++ dst_release(&tdst->dst); ++} ++ + void vlan_tunnel_info_del(struct net_bridge_vlan_group *vg, + struct net_bridge_vlan *vlan) + { +- if (!vlan->tinfo.tunnel_dst) ++ if (!rcu_access_pointer(vlan->tinfo.tunnel_dst)) + return; + rhashtable_remove_fast(&vg->tunnel_hash, &vlan->tnode, + br_vlan_tunnel_rht_params); +- vlan->tinfo.tunnel_id = 0; +- dst_release(&vlan->tinfo.tunnel_dst->dst); +- vlan->tinfo.tunnel_dst = NULL; ++ vlan_tunnel_info_release(vlan); + } + + static int __vlan_tunnel_info_add(struct net_bridge_vlan_group *vg, + struct net_bridge_vlan *vlan, u32 tun_id) + { +- struct metadata_dst *metadata = NULL; ++ struct metadata_dst *metadata = rtnl_dereference(vlan->tinfo.tunnel_dst); + __be64 key = key32_to_tunnel_id(cpu_to_be32(tun_id)); + int err; + +- if (vlan->tinfo.tunnel_dst) ++ if (metadata) + return -EEXIST; + + metadata = __ip_tun_set_dst(0, 0, 0, 0, 0, TUNNEL_KEY, +@@ -74,8 +81,8 @@ static int __vlan_tunnel_info_add(struct + return -EINVAL; + + metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_BRIDGE; +- vlan->tinfo.tunnel_dst = metadata; +- vlan->tinfo.tunnel_id = key; ++ rcu_assign_pointer(vlan->tinfo.tunnel_dst, metadata); ++ WRITE_ONCE(vlan->tinfo.tunnel_id, key); + + err = rhashtable_lookup_insert_fast(&vg->tunnel_hash, &vlan->tnode, + br_vlan_tunnel_rht_params); +@@ -84,9 +91,7 @@ static int __vlan_tunnel_info_add(struct + + return 0; + out: +- dst_release(&vlan->tinfo.tunnel_dst->dst); +- vlan->tinfo.tunnel_dst = NULL; +- vlan->tinfo.tunnel_id = 0; ++ vlan_tunnel_info_release(vlan); + + return err; + } +@@ -186,12 +191,15 @@ int br_handle_ingress_vlan_tunnel(struct + int br_handle_egress_vlan_tunnel(struct sk_buff *skb, + struct net_bridge_vlan *vlan) + { ++ struct metadata_dst *tunnel_dst; ++ __be64 tunnel_id; + int err; + +- if (!vlan || !vlan->tinfo.tunnel_id) ++ if (!vlan) + return 0; + +- if (unlikely(!skb_vlan_tag_present(skb))) ++ tunnel_id = READ_ONCE(vlan->tinfo.tunnel_id); ++ if (!tunnel_id || unlikely(!skb_vlan_tag_present(skb))) + return 0; + + skb_dst_drop(skb); +@@ -199,7 +207,9 @@ int br_handle_egress_vlan_tunnel(struct + if (err) + return err; + +- skb_dst_set(skb, dst_clone(&vlan->tinfo.tunnel_dst->dst)); ++ tunnel_dst = rcu_dereference(vlan->tinfo.tunnel_dst); ++ if (tunnel_dst) ++ skb_dst_set(skb, dst_clone(&tunnel_dst->dst)); + + return 0; + } diff --git a/queue-4.14/net-bridge-fix-vlan-tunnel-dst-refcnt-when-egressing.patch b/queue-4.14/net-bridge-fix-vlan-tunnel-dst-refcnt-when-egressing.patch new file mode 100644 index 00000000000..f22c33eeea7 --- /dev/null +++ b/queue-4.14/net-bridge-fix-vlan-tunnel-dst-refcnt-when-egressing.patch @@ -0,0 +1,87 @@ +From cfc579f9d89af4ada58c69b03bcaa4887840f3b3 Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Thu, 10 Jun 2021 15:04:11 +0300 +Subject: net: bridge: fix vlan tunnel dst refcnt when egressing + +From: Nikolay Aleksandrov + +commit cfc579f9d89af4ada58c69b03bcaa4887840f3b3 upstream. + +The egress tunnel code uses dst_clone() and directly sets the result +which is wrong because the entry might have 0 refcnt or be already deleted, +causing number of problems. It also triggers the WARN_ON() in dst_hold()[1] +when a refcnt couldn't be taken. Fix it by using dst_hold_safe() and +checking if a reference was actually taken before setting the dst. + +[1] dmesg WARN_ON log and following refcnt errors + WARNING: CPU: 5 PID: 38 at include/net/dst.h:230 br_handle_egress_vlan_tunnel+0x10b/0x134 [bridge] + Modules linked in: 8021q garp mrp bridge stp llc bonding ipv6 virtio_net + CPU: 5 PID: 38 Comm: ksoftirqd/5 Kdump: loaded Tainted: G W 5.13.0-rc3+ #360 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014 + RIP: 0010:br_handle_egress_vlan_tunnel+0x10b/0x134 [bridge] + Code: e8 85 bc 01 e1 45 84 f6 74 90 45 31 f6 85 db 48 c7 c7 a0 02 19 a0 41 0f 94 c6 31 c9 31 d2 44 89 f6 e8 64 bc 01 e1 85 db 75 02 <0f> 0b 31 c9 31 d2 44 89 f6 48 c7 c7 70 02 19 a0 e8 4b bc 01 e1 49 + RSP: 0018:ffff8881003d39e8 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 + RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffffa01902a0 + RBP: ffff8881040c6700 R08: 0000000000000000 R09: 0000000000000001 + R10: 2ce93d0054fe0d00 R11: 54fe0d00000e0000 R12: ffff888109515000 + R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000401 + FS: 0000000000000000(0000) GS:ffff88822bf40000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f42ba70f030 CR3: 0000000109926000 CR4: 00000000000006e0 + Call Trace: + br_handle_vlan+0xbc/0xca [bridge] + __br_forward+0x23/0x164 [bridge] + deliver_clone+0x41/0x48 [bridge] + br_handle_frame_finish+0x36f/0x3aa [bridge] + ? skb_dst+0x2e/0x38 [bridge] + ? br_handle_ingress_vlan_tunnel+0x3e/0x1c8 [bridge] + ? br_handle_frame_finish+0x3aa/0x3aa [bridge] + br_handle_frame+0x2c3/0x377 [bridge] + ? __skb_pull+0x33/0x51 + ? vlan_do_receive+0x4f/0x36a + ? br_handle_frame_finish+0x3aa/0x3aa [bridge] + __netif_receive_skb_core+0x539/0x7c6 + ? __list_del_entry_valid+0x16e/0x1c2 + __netif_receive_skb_list_core+0x6d/0xd6 + netif_receive_skb_list_internal+0x1d9/0x1fa + gro_normal_list+0x22/0x3e + dev_gro_receive+0x55b/0x600 + ? detach_buf_split+0x58/0x140 + napi_gro_receive+0x94/0x12e + virtnet_poll+0x15d/0x315 [virtio_net] + __napi_poll+0x2c/0x1c9 + net_rx_action+0xe6/0x1fb + __do_softirq+0x115/0x2d8 + run_ksoftirqd+0x18/0x20 + smpboot_thread_fn+0x183/0x19c + ? smpboot_unregister_percpu_thread+0x66/0x66 + kthread+0x10a/0x10f + ? kthread_mod_delayed_work+0xb6/0xb6 + ret_from_fork+0x22/0x30 + ---[ end trace 49f61b07f775fd2b ]--- + dst_release: dst:00000000c02d677a refcnt:-1 + dst_release underflow + +Cc: stable@vger.kernel.org +Fixes: 11538d039ac6 ("bridge: vlan dst_metadata hooks in ingress and egress paths") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_vlan_tunnel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/bridge/br_vlan_tunnel.c ++++ b/net/bridge/br_vlan_tunnel.c +@@ -208,8 +208,8 @@ int br_handle_egress_vlan_tunnel(struct + return err; + + tunnel_dst = rcu_dereference(vlan->tinfo.tunnel_dst); +- if (tunnel_dst) +- skb_dst_set(skb, dst_clone(&tunnel_dst->dst)); ++ if (tunnel_dst && dst_hold_safe(&tunnel_dst->dst)) ++ skb_dst_set(skb, &tunnel_dst->dst); + + return 0; + } diff --git a/queue-4.14/series b/queue-4.14/series index da5a446f676..d2cc894d4ab 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -51,3 +51,6 @@ pci-mark-some-nvidia-gpus-to-avoid-bus-reset.patch pci-add-acs-quirk-for-broadcom-bcm57414-nic.patch pci-work-around-huawei-intelligent-nic-vf-flr-erratum.patch arcv2-save-abi-registers-across-signal-handling.patch +dmaengine-pl330-fix-wrong-usage-of-spinlock-flags-in-dma_cyclc.patch +net-bridge-fix-vlan-tunnel-dst-null-pointer-dereference.patch +net-bridge-fix-vlan-tunnel-dst-refcnt-when-egressing.patch