From 474200e63c761805177e8244a8390bf3c5cf0501 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 11 Aug 2025 00:39:20 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...fix-missing-error-handling-in-ca0132.patch | 47 ++ .../benet-fix-bug-when-creating-vfs.patch | 61 +++ ...alicious-packets-in-ipv6_gso_segment.patch | 103 +++++ ...-drop-ufo-packets-in-udp_rcv_segment.patch | 122 ++++++ ...rectly-set-gso_segs-when-lro-is-used.patch | 59 +++ ...-mlx5e-add-handle-shampo-cqe-support.patch | 410 ++++++++++++++++++ ...hanging-napi-when-netcons-gets-enabl.patch | 95 ++++ ...le-bounds-checking-in-nfs_fh_to_dent.patch | 51 +++ ...tion-flags-for-nfsiod-s-__gfp_noretr.patch | 55 +++ .../nfsv4.2-another-fix-for-listxattr.patch | 53 +++ ...y-mscc-fix-parsing-of-unicast-frames.patch | 53 +++ ...on-t-attempt-pnfs-on-fatal-ds-errors.patch | 176 ++++++++ ...sure-minimal-skb-length-in-pptp_xmit.patch | 92 ++++ .../pptp-fix-pptp_xmit-error-path.patch | 84 ++++ queue-5.15/series | 20 + ...ecv_done-cleanup-before-notifying-th.patch | 79 ++++ ...ecv_done-avoid-touching-data_transfe.patch | 67 +++ ...ecv_done-consistently-call-put_recvm.patch | 105 +++++ ...sure-we-call-ib_dma_unmap_single-onl.patch | 68 +++ ...-remove-separate-empty_recvmsg_queue.patch | 169 ++++++++ .../xarray-add-calls-to-might_alloc.patch | 159 +++++++ 21 files changed, 2128 insertions(+) create mode 100644 queue-5.15/alsa-hda-ca0132-fix-missing-error-handling-in-ca0132.patch create mode 100644 queue-5.15/benet-fix-bug-when-creating-vfs.patch create mode 100644 queue-5.15/ipv6-reject-malicious-packets-in-ipv6_gso_segment.patch create mode 100644 queue-5.15/net-drop-ufo-packets-in-udp_rcv_segment.patch create mode 100644 queue-5.15/net-mlx5-correctly-set-gso_segs-when-lro-is-used.patch create mode 100644 queue-5.15/net-mlx5e-add-handle-shampo-cqe-support.patch create mode 100644 queue-5.15/netpoll-prevent-hanging-napi-when-netcons-gets-enabl.patch create mode 100644 queue-5.15/nfs-fix-filehandle-bounds-checking-in-nfs_fh_to_dent.patch create mode 100644 queue-5.15/nfs-fixup-allocation-flags-for-nfsiod-s-__gfp_noretr.patch create mode 100644 queue-5.15/nfsv4.2-another-fix-for-listxattr.patch create mode 100644 queue-5.15/phy-mscc-fix-parsing-of-unicast-frames.patch create mode 100644 queue-5.15/pnfs-flexfiles-don-t-attempt-pnfs-on-fatal-ds-errors.patch create mode 100644 queue-5.15/pptp-ensure-minimal-skb-length-in-pptp_xmit.patch create mode 100644 queue-5.15/pptp-fix-pptp_xmit-error-path.patch create mode 100644 queue-5.15/smb-client-let-recv_done-cleanup-before-notifying-th.patch create mode 100644 queue-5.15/smb-server-let-recv_done-avoid-touching-data_transfe.patch create mode 100644 queue-5.15/smb-server-let-recv_done-consistently-call-put_recvm.patch create mode 100644 queue-5.15/smb-server-make-sure-we-call-ib_dma_unmap_single-onl.patch create mode 100644 queue-5.15/smb-server-remove-separate-empty_recvmsg_queue.patch create mode 100644 queue-5.15/xarray-add-calls-to-might_alloc.patch diff --git a/queue-5.15/alsa-hda-ca0132-fix-missing-error-handling-in-ca0132.patch b/queue-5.15/alsa-hda-ca0132-fix-missing-error-handling-in-ca0132.patch new file mode 100644 index 0000000000..ab930a8ba7 --- /dev/null +++ b/queue-5.15/alsa-hda-ca0132-fix-missing-error-handling-in-ca0132.patch @@ -0,0 +1,47 @@ +From 932c6523c597abbbb1c1ecdf93899771d1f07327 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Aug 2025 11:44:22 +0200 +Subject: ALSA: hda/ca0132: Fix missing error handling in + ca0132_alt_select_out() + +From: Takashi Iwai + +[ Upstream commit 9f320dfb0ffc555aa2eac8331dee0c2c16f67633 ] + +There are a couple of cases where the error is ignored or the error +code isn't propagated in ca0132_alt_select_out(). Fix those. + +Fixes: def3f0a5c700 ("ALSA: hda/ca0132 - Add quirk output selection structures.") +Link: https://patch.msgid.link/20250806094423.8843-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_ca0132.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c +index fab7c329acbe..a922c5079880 100644 +--- a/sound/pci/hda/patch_ca0132.c ++++ b/sound/pci/hda/patch_ca0132.c +@@ -4794,7 +4794,8 @@ static int ca0132_alt_select_out(struct hda_codec *codec) + if (err < 0) + goto exit; + +- if (ca0132_alt_select_out_quirk_set(codec) < 0) ++ err = ca0132_alt_select_out_quirk_set(codec); ++ if (err < 0) + goto exit; + + switch (spec->cur_out_type) { +@@ -4884,6 +4885,8 @@ static int ca0132_alt_select_out(struct hda_codec *codec) + spec->bass_redirection_val); + else + err = ca0132_alt_surround_set_bass_redirection(codec, 0); ++ if (err < 0) ++ goto exit; + + /* Unmute DSP now that we're done with output selection. */ + err = dspio_set_uint_param(codec, 0x96, +-- +2.39.5 + diff --git a/queue-5.15/benet-fix-bug-when-creating-vfs.patch b/queue-5.15/benet-fix-bug-when-creating-vfs.patch new file mode 100644 index 0000000000..d44926d2a9 --- /dev/null +++ b/queue-5.15/benet-fix-bug-when-creating-vfs.patch @@ -0,0 +1,61 @@ +From e43bffc1f98a33b287909c33ad2f2e4f81a8cee9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Aug 2025 12:13:37 +0200 +Subject: benet: fix BUG when creating VFs + +From: Michal Schmidt + +[ Upstream commit 5a40f8af2ba1b9bdf46e2db10e8c9710538fbc63 ] + +benet crashes as soon as SRIOV VFs are created: + + kernel BUG at mm/vmalloc.c:3457! + Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI + CPU: 4 UID: 0 PID: 7408 Comm: test.sh Kdump: loaded Not tainted 6.16.0+ #1 PREEMPT(voluntary) + [...] + RIP: 0010:vunmap+0x5f/0x70 + [...] + Call Trace: + + __iommu_dma_free+0xe8/0x1c0 + be_cmd_set_mac_list+0x3fe/0x640 [be2net] + be_cmd_set_mac+0xaf/0x110 [be2net] + be_vf_eth_addr_config+0x19f/0x330 [be2net] + be_vf_setup+0x4f7/0x990 [be2net] + be_pci_sriov_configure+0x3a1/0x470 [be2net] + sriov_numvfs_store+0x20b/0x380 + kernfs_fop_write_iter+0x354/0x530 + vfs_write+0x9b9/0xf60 + ksys_write+0xf3/0x1d0 + do_syscall_64+0x8c/0x3d0 + +be_cmd_set_mac_list() calls dma_free_coherent() under a spin_lock_bh. +Fix it by freeing only after the lock has been released. + +Fixes: 1a82d19ca2d6 ("be2net: fix sleeping while atomic bugs in be_ndo_bridge_getlink") +Signed-off-by: Michal Schmidt +Reviewed-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250801101338.72502-1-mschmidt@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/emulex/benet/be_cmds.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c +index 1cdb7ca019f5..96a8749cf34f 100644 +--- a/drivers/net/ethernet/emulex/benet/be_cmds.c ++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c +@@ -3851,8 +3851,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, + status = be_mcc_notify_wait(adapter); + + err: +- dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); + spin_unlock_bh(&adapter->mcc_lock); ++ dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); + return status; + } + +-- +2.39.5 + diff --git a/queue-5.15/ipv6-reject-malicious-packets-in-ipv6_gso_segment.patch b/queue-5.15/ipv6-reject-malicious-packets-in-ipv6_gso_segment.patch new file mode 100644 index 0000000000..1129fc2fd8 --- /dev/null +++ b/queue-5.15/ipv6-reject-malicious-packets-in-ipv6_gso_segment.patch @@ -0,0 +1,103 @@ +From c53b0a0a5d0f0197ad1effd382f1ec61e6450706 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Jul 2025 13:17:38 +0000 +Subject: ipv6: reject malicious packets in ipv6_gso_segment() + +From: Eric Dumazet + +[ Upstream commit d45cf1e7d7180256e17c9ce88e32e8061a7887fe ] + +syzbot was able to craft a packet with very long IPv6 extension headers +leading to an overflow of skb->transport_header. + +This 16bit field has a limited range. + +Add skb_reset_transport_header_careful() helper and use it +from ipv6_gso_segment() + +WARNING: CPU: 0 PID: 5871 at ./include/linux/skbuff.h:3032 skb_reset_transport_header include/linux/skbuff.h:3032 [inline] +WARNING: CPU: 0 PID: 5871 at ./include/linux/skbuff.h:3032 ipv6_gso_segment+0x15e2/0x21e0 net/ipv6/ip6_offload.c:151 +Modules linked in: +CPU: 0 UID: 0 PID: 5871 Comm: syz-executor211 Not tainted 6.16.0-rc6-syzkaller-g7abc678e3084 #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 + RIP: 0010:skb_reset_transport_header include/linux/skbuff.h:3032 [inline] + RIP: 0010:ipv6_gso_segment+0x15e2/0x21e0 net/ipv6/ip6_offload.c:151 +Call Trace: + + skb_mac_gso_segment+0x31c/0x640 net/core/gso.c:53 + nsh_gso_segment+0x54a/0xe10 net/nsh/nsh.c:110 + skb_mac_gso_segment+0x31c/0x640 net/core/gso.c:53 + __skb_gso_segment+0x342/0x510 net/core/gso.c:124 + skb_gso_segment include/net/gso.h:83 [inline] + validate_xmit_skb+0x857/0x11b0 net/core/dev.c:3950 + validate_xmit_skb_list+0x84/0x120 net/core/dev.c:4000 + sch_direct_xmit+0xd3/0x4b0 net/sched/sch_generic.c:329 + __dev_xmit_skb net/core/dev.c:4102 [inline] + __dev_queue_xmit+0x17b6/0x3a70 net/core/dev.c:4679 + +Fixes: d1da932ed4ec ("ipv6: Separate ipv6 offload support") +Reported-by: syzbot+af43e647fd835acc02df@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/688a1a05.050a0220.5d226.0008.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Dawid Osuchowski +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250730131738.3385939-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/linux/skbuff.h | 23 +++++++++++++++++++++++ + net/ipv6/ip6_offload.c | 4 +++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 7f52562fac19..9155d0d7f706 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2646,6 +2646,29 @@ static inline void skb_reset_transport_header(struct sk_buff *skb) + skb->transport_header = skb->data - skb->head; + } + ++/** ++ * skb_reset_transport_header_careful - conditionally reset transport header ++ * @skb: buffer to alter ++ * ++ * Hardened version of skb_reset_transport_header(). ++ * ++ * Returns: true if the operation was a success. ++ */ ++static inline bool __must_check ++skb_reset_transport_header_careful(struct sk_buff *skb) ++{ ++ long offset = skb->data - skb->head; ++ ++ if (unlikely(offset != (typeof(skb->transport_header))offset)) ++ return false; ++ ++ if (unlikely(offset == (typeof(skb->transport_header))~0U)) ++ return false; ++ ++ skb->transport_header = offset; ++ return true; ++} ++ + static inline void skb_set_transport_header(struct sk_buff *skb, + const int offset) + { +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index 30c56143d79b..0de54467ee84 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -112,7 +112,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, + + ops = rcu_dereference(inet6_offloads[proto]); + if (likely(ops && ops->callbacks.gso_segment)) { +- skb_reset_transport_header(skb); ++ if (!skb_reset_transport_header_careful(skb)) ++ goto out; ++ + segs = ops->callbacks.gso_segment(skb, features); + if (!segs) + skb->network_header = skb_mac_header(skb) + nhoff - skb->head; +-- +2.39.5 + diff --git a/queue-5.15/net-drop-ufo-packets-in-udp_rcv_segment.patch b/queue-5.15/net-drop-ufo-packets-in-udp_rcv_segment.patch new file mode 100644 index 0000000000..37723540e4 --- /dev/null +++ b/queue-5.15/net-drop-ufo-packets-in-udp_rcv_segment.patch @@ -0,0 +1,122 @@ +From 9348e97d96da420e4b9d376318cdfe822b87461e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Jul 2025 18:14:58 +0800 +Subject: net: drop UFO packets in udp_rcv_segment() + +From: Wang Liang + +[ Upstream commit d46e51f1c78b9ab9323610feb14238d06d46d519 ] + +When sending a packet with virtio_net_hdr to tun device, if the gso_type +in virtio_net_hdr is SKB_GSO_UDP and the gso_size is less than udphdr +size, below crash may happen. + + ------------[ cut here ]------------ + kernel BUG at net/core/skbuff.c:4572! + Oops: invalid opcode: 0000 [#1] SMP NOPTI + CPU: 0 UID: 0 PID: 62 Comm: mytest Not tainted 6.16.0-rc7 #203 PREEMPT(voluntary) + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 + RIP: 0010:skb_pull_rcsum+0x8e/0xa0 + Code: 00 00 5b c3 cc cc cc cc 8b 93 88 00 00 00 f7 da e8 37 44 38 00 f7 d8 89 83 88 00 00 00 48 8b 83 c8 00 00 00 5b c3 cc cc cc cc <0f> 0b 0f 0b 66 66 2e 0f 1f 84 00 000 + RSP: 0018:ffffc900001fba38 EFLAGS: 00000297 + RAX: 0000000000000004 RBX: ffff8880040c1000 RCX: ffffc900001fb948 + RDX: ffff888003e6d700 RSI: 0000000000000008 RDI: ffff88800411a062 + RBP: ffff8880040c1000 R08: 0000000000000000 R09: 0000000000000001 + R10: ffff888003606c00 R11: 0000000000000001 R12: 0000000000000000 + R13: ffff888004060900 R14: ffff888004050000 R15: ffff888004060900 + FS: 000000002406d3c0(0000) GS:ffff888084a19000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000020000040 CR3: 0000000004007000 CR4: 00000000000006f0 + Call Trace: + + udp_queue_rcv_one_skb+0x176/0x4b0 net/ipv4/udp.c:2445 + udp_queue_rcv_skb+0x155/0x1f0 net/ipv4/udp.c:2475 + udp_unicast_rcv_skb+0x71/0x90 net/ipv4/udp.c:2626 + __udp4_lib_rcv+0x433/0xb00 net/ipv4/udp.c:2690 + ip_protocol_deliver_rcu+0xa6/0x160 net/ipv4/ip_input.c:205 + ip_local_deliver_finish+0x72/0x90 net/ipv4/ip_input.c:233 + ip_sublist_rcv_finish+0x5f/0x70 net/ipv4/ip_input.c:579 + ip_sublist_rcv+0x122/0x1b0 net/ipv4/ip_input.c:636 + ip_list_rcv+0xf7/0x130 net/ipv4/ip_input.c:670 + __netif_receive_skb_list_core+0x21d/0x240 net/core/dev.c:6067 + netif_receive_skb_list_internal+0x186/0x2b0 net/core/dev.c:6210 + napi_complete_done+0x78/0x180 net/core/dev.c:6580 + tun_get_user+0xa63/0x1120 drivers/net/tun.c:1909 + tun_chr_write_iter+0x65/0xb0 drivers/net/tun.c:1984 + vfs_write+0x300/0x420 fs/read_write.c:593 + ksys_write+0x60/0xd0 fs/read_write.c:686 + do_syscall_64+0x50/0x1c0 arch/x86/entry/syscall_64.c:63 + + +To trigger gso segment in udp_queue_rcv_skb(), we should also set option +UDP_ENCAP_ESPINUDP to enable udp_sk(sk)->encap_rcv. When the encap_rcv +hook return 1 in udp_queue_rcv_one_skb(), udp_csum_pull_header() will try +to pull udphdr, but the skb size has been segmented to gso size, which +leads to this crash. + +Previous commit cf329aa42b66 ("udp: cope with UDP GRO packet misdirection") +introduces segmentation in UDP receive path only for GRO, which was never +intended to be used for UFO, so drop UFO packets in udp_rcv_segment(). + +Link: https://lore.kernel.org/netdev/20250724083005.3918375-1-wangliang74@huawei.com/ +Link: https://lore.kernel.org/netdev/20250729123907.3318425-1-wangliang74@huawei.com/ +Fixes: cf329aa42b66 ("udp: cope with UDP GRO packet misdirection") +Suggested-by: Willem de Bruijn +Signed-off-by: Wang Liang +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250730101458.3470788-1-wangliang74@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/udp.h | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/include/net/udp.h b/include/net/udp.h +index 10508c66e7a1..3dbfa4cfac50 100644 +--- a/include/net/udp.h ++++ b/include/net/udp.h +@@ -483,6 +483,16 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk, + { + netdev_features_t features = NETIF_F_SG; + struct sk_buff *segs; ++ int drop_count; ++ ++ /* ++ * Segmentation in UDP receive path is only for UDP GRO, drop udp ++ * fragmentation offload (UFO) packets. ++ */ ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) { ++ drop_count = 1; ++ goto drop; ++ } + + /* Avoid csum recalculation by skb_segment unless userspace explicitly + * asks for the final checksum values +@@ -506,16 +516,18 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk, + */ + segs = __skb_gso_segment(skb, features, false); + if (IS_ERR_OR_NULL(segs)) { +- int segs_nr = skb_shinfo(skb)->gso_segs; +- +- atomic_add(segs_nr, &sk->sk_drops); +- SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, segs_nr); +- kfree_skb(skb); +- return NULL; ++ drop_count = skb_shinfo(skb)->gso_segs; ++ goto drop; + } + + consume_skb(skb); + return segs; ++ ++drop: ++ atomic_add(drop_count, &sk->sk_drops); ++ SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, drop_count); ++ kfree_skb(skb); ++ return NULL; + } + + static inline void udp_post_segment_fix_csum(struct sk_buff *skb) +-- +2.39.5 + diff --git a/queue-5.15/net-mlx5-correctly-set-gso_segs-when-lro-is-used.patch b/queue-5.15/net-mlx5-correctly-set-gso_segs-when-lro-is-used.patch new file mode 100644 index 0000000000..3ada681240 --- /dev/null +++ b/queue-5.15/net-mlx5-correctly-set-gso_segs-when-lro-is-used.patch @@ -0,0 +1,59 @@ +From b65bec5b3641bb30d8fe92ae0c81f30922488a6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Jul 2025 11:34:00 -0700 +Subject: net/mlx5: Correctly set gso_segs when LRO is used + +From: Christoph Paasch + +[ Upstream commit 77bf1c55b2acc7fa3734b14f4561e3d75aea1a90 ] + +When gso_segs is left at 0, a number of assumptions will end up being +incorrect throughout the stack. + +For example, in the GRO-path, we set NAPI_GRO_CB()->count to gso_segs. +So, if a non-LRO'ed packet followed by an LRO'ed packet is being +processed in GRO, the first one will have NAPI_GRO_CB()->count set to 1 and +the next one to 0 (in dev_gro_receive()). +Since commit 531d0d32de3e +("net/mlx5: Correctly set gso_size when LRO is used") +these packets will get merged (as their gso_size now matches). +So, we end up in gro_complete() with NAPI_GRO_CB()->count == 1 and thus +don't call inet_gro_complete(). Meaning, checksum-validation in +tcp_checksum_complete() will fail with a "hw csum failure". + +Even before the above mentioned commit, incorrect gso_segs means that other +things like TCP's accounting of incoming packets (tp->segs_in, +data_segs_in, rcv_ooopack) will be incorrect. Which means that if one +does bytes_received/data_segs_in, the result will be bigger than the +MTU. + +Fix this by initializing gso_segs correctly when LRO is used. + +Fixes: e586b3b0baee ("net/mlx5: Ethernet Datapath files") +Reported-by: Gal Pressman +Closes: https://lore.kernel.org/netdev/6583783f-f0fb-4fb1-a415-feec8155bc69@nvidia.com/ +Signed-off-by: Christoph Paasch +Reviewed-by: Gal Pressman +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250729-mlx5_gso_segs-v1-1-b48c480c1c12@openai.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +index de2737b1a7e1..b64bb0c7b9db 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +@@ -1065,6 +1065,7 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe, + unsigned int hdrlen = mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt); + + skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt - hdrlen, lro_num_seg); ++ skb_shinfo(skb)->gso_segs = lro_num_seg; + /* Subtract one since we already counted this as one + * "regular" packet in mlx5e_complete_rx_cqe() + */ +-- +2.39.5 + diff --git a/queue-5.15/net-mlx5e-add-handle-shampo-cqe-support.patch b/queue-5.15/net-mlx5e-add-handle-shampo-cqe-support.patch new file mode 100644 index 0000000000..409bbdf6ea --- /dev/null +++ b/queue-5.15/net-mlx5e-add-handle-shampo-cqe-support.patch @@ -0,0 +1,410 @@ +From 5a2b15eac40c87f48365ca3beba0e2110a6b8a68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 May 2020 15:45:38 +0300 +Subject: net/mlx5e: Add handle SHAMPO cqe support + +From: Khalid Manaa + +[ Upstream commit f97d5c2a453e26071e3b0ec12161de57c4a237c4 ] + +This patch adds the new CQE SHAMPO fields: +- flush: indicates that we must close the current session and pass the SKB + to the network stack. + +- match: indicates that the current packet matches the oppened session, + the packet will be merge into the current SKB. + +- header_size: the size of the packet headers that written into the headers + buffer. + +- header_entry_index: the entry index in the headers buffer. + +- data_offset: packets data offset in the WQE. + +Also new cqe handler is added to handle SHAMPO packets: +- The new handler uses CQE SHAMPO fields to build the SKB. + CQE's Flush and match fields are not used in this patch, packets are not + merged in this patch. + +Signed-off-by: Khalid Manaa +Reviewed-by: Tariq Toukan +Signed-off-by: Saeed Mahameed +Stable-dep-of: 77bf1c55b2ac ("net/mlx5: Correctly set gso_segs when LRO is used") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + + .../net/ethernet/mellanox/mlx5/core/en_rx.c | 205 +++++++++++++++--- + include/linux/mlx5/device.h | 23 +- + 3 files changed, 194 insertions(+), 35 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 4f711f1af6c1..376a886c17fd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -918,6 +918,7 @@ struct mlx5e_priv { + struct mlx5e_rx_handlers { + mlx5e_fp_handle_rx_cqe handle_rx_cqe; + mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe; ++ mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe_shampo; + }; + + extern const struct mlx5e_rx_handlers mlx5e_rx_handlers_nic; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +index 2f6d3473bcbf..de2737b1a7e1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +@@ -62,10 +62,12 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w + u16 cqe_bcnt, u32 head_offset, u32 page_idx); + static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); + static void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); ++static void mlx5e_handle_rx_cqe_mpwrq_shampo(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe); + + const struct mlx5e_rx_handlers mlx5e_rx_handlers_nic = { + .handle_rx_cqe = mlx5e_handle_rx_cqe, + .handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq, ++ .handle_rx_cqe_mpwqe_shampo = mlx5e_handle_rx_cqe_mpwrq_shampo, + }; + + static inline bool mlx5e_rx_hw_stamp(struct hwtstamp_config *config) +@@ -185,8 +187,9 @@ static inline u32 mlx5e_decompress_cqes_cont(struct mlx5e_rq *rq, + mlx5e_read_mini_arr_slot(wq, cqd, cqcc); + + mlx5e_decompress_cqe_no_hash(rq, wq, cqcc); +- INDIRECT_CALL_2(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq, +- mlx5e_handle_rx_cqe, rq, &cqd->title); ++ INDIRECT_CALL_3(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq, ++ mlx5e_handle_rx_cqe_mpwrq_shampo, mlx5e_handle_rx_cqe, ++ rq, &cqd->title); + } + mlx5e_cqes_update_owner(wq, cqcc - wq->cc); + wq->cc = cqcc; +@@ -206,8 +209,9 @@ static inline u32 mlx5e_decompress_cqes_start(struct mlx5e_rq *rq, + mlx5e_read_title_slot(rq, wq, cc); + mlx5e_read_mini_arr_slot(wq, cqd, cc + 1); + mlx5e_decompress_cqe(rq, wq, cc); +- INDIRECT_CALL_2(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq, +- mlx5e_handle_rx_cqe, rq, &cqd->title); ++ INDIRECT_CALL_3(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq, ++ mlx5e_handle_rx_cqe_mpwrq_shampo, mlx5e_handle_rx_cqe, ++ rq, &cqd->title); + cqd->mini_arr_idx++; + + return mlx5e_decompress_cqes_cont(rq, wq, 1, budget_rem) - 1; +@@ -449,13 +453,13 @@ mlx5e_add_skb_frag(struct mlx5e_rq *rq, struct sk_buff *skb, + static inline void + mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb, + struct mlx5e_dma_info *dma_info, +- int offset_from, u32 headlen) ++ int offset_from, int dma_offset, u32 headlen) + { + const void *from = page_address(dma_info->page) + offset_from; + /* Aligning len to sizeof(long) optimizes memcpy performance */ + unsigned int len = ALIGN(headlen, sizeof(long)); + +- dma_sync_single_for_cpu(pdev, dma_info->addr + offset_from, len, ++ dma_sync_single_for_cpu(pdev, dma_info->addr + dma_offset, len, + DMA_FROM_DEVICE); + skb_copy_to_linear_data(skb, from, len); + } +@@ -783,8 +787,8 @@ static void mlx5e_lro_update_tcp_hdr(struct mlx5_cqe64 *cqe, struct tcphdr *tcp) + + if (tcp_ack) { + tcp->ack = 1; +- tcp->ack_seq = cqe->lro_ack_seq_num; +- tcp->window = cqe->lro_tcp_win; ++ tcp->ack_seq = cqe->lro.ack_seq_num; ++ tcp->window = cqe->lro.tcp_win; + } + } + +@@ -811,7 +815,7 @@ static unsigned int mlx5e_lro_update_hdr(struct sk_buff *skb, + tcp = ip_p + sizeof(struct iphdr); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + +- ipv4->ttl = cqe->lro_min_ttl; ++ ipv4->ttl = cqe->lro.min_ttl; + ipv4->tot_len = cpu_to_be16(tot_len); + ipv4->check = 0; + ipv4->check = ip_fast_csum((unsigned char *)ipv4, +@@ -831,7 +835,7 @@ static unsigned int mlx5e_lro_update_hdr(struct sk_buff *skb, + tcp = ip_p + sizeof(struct ipv6hdr); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + +- ipv6->hop_limit = cqe->lro_min_ttl; ++ ipv6->hop_limit = cqe->lro.min_ttl; + ipv6->payload_len = cpu_to_be16(payload_len); + + mlx5e_lro_update_tcp_hdr(cqe, tcp); +@@ -1205,7 +1209,8 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe, + } + + /* copy header */ +- mlx5e_copy_skb_header(rq->pdev, skb, head_wi->di, head_wi->offset, headlen); ++ mlx5e_copy_skb_header(rq->pdev, skb, head_wi->di, head_wi->offset, head_wi->offset, ++ headlen); + /* skb linear part was allocated with headlen and aligned to long */ + skb->tail += headlen; + skb->len += headlen; +@@ -1401,6 +1406,30 @@ const struct mlx5e_rx_handlers mlx5e_rx_handlers_rep = { + }; + #endif + ++static void ++mlx5e_fill_skb_data(struct sk_buff *skb, struct mlx5e_rq *rq, struct mlx5e_dma_info *di, ++ u32 data_bcnt, u32 data_offset) ++{ ++ net_prefetchw(skb->data); ++ ++ while (data_bcnt) { ++ u32 pg_consumed_bytes = min_t(u32, PAGE_SIZE - data_offset, data_bcnt); ++ unsigned int truesize; ++ ++ if (test_bit(MLX5E_RQ_STATE_SHAMPO, &rq->state)) ++ truesize = pg_consumed_bytes; ++ else ++ truesize = ALIGN(pg_consumed_bytes, BIT(rq->mpwqe.log_stride_sz)); ++ ++ mlx5e_add_skb_frag(rq, skb, di, data_offset, ++ pg_consumed_bytes, truesize); ++ ++ data_bcnt -= pg_consumed_bytes; ++ data_offset = 0; ++ di++; ++ } ++} ++ + static struct sk_buff * + mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, + u16 cqe_bcnt, u32 head_offset, u32 page_idx) +@@ -1426,20 +1455,9 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w + frag_offset -= PAGE_SIZE; + } + +- while (byte_cnt) { +- u32 pg_consumed_bytes = +- min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); +- unsigned int truesize = +- ALIGN(pg_consumed_bytes, BIT(rq->mpwqe.log_stride_sz)); +- +- mlx5e_add_skb_frag(rq, skb, di, frag_offset, +- pg_consumed_bytes, truesize); +- byte_cnt -= pg_consumed_bytes; +- frag_offset = 0; +- di++; +- } ++ mlx5e_fill_skb_data(skb, rq, di, byte_cnt, frag_offset); + /* copy header */ +- mlx5e_copy_skb_header(rq->pdev, skb, head_di, head_offset, headlen); ++ mlx5e_copy_skb_header(rq->pdev, skb, head_di, head_offset, head_offset, headlen); + /* skb linear part was allocated with headlen and aligned to long */ + skb->tail += headlen; + skb->len += headlen; +@@ -1493,6 +1511,123 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, + return skb; + } + ++static struct sk_buff * ++mlx5e_skb_from_cqe_shampo(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, ++ struct mlx5_cqe64 *cqe, u16 header_index) ++{ ++ struct mlx5e_dma_info *head = &rq->mpwqe.shampo->info[header_index]; ++ u16 head_offset = head->addr & (PAGE_SIZE - 1); ++ u16 head_size = cqe->shampo.header_size; ++ u16 rx_headroom = rq->buff.headroom; ++ struct sk_buff *skb = NULL; ++ void *hdr, *data; ++ u32 frag_size; ++ ++ hdr = page_address(head->page) + head_offset; ++ data = hdr + rx_headroom; ++ frag_size = MLX5_SKB_FRAG_SZ(rx_headroom + head_size); ++ ++ if (likely(frag_size <= BIT(MLX5E_SHAMPO_LOG_MAX_HEADER_ENTRY_SIZE))) { ++ /* build SKB around header */ ++ dma_sync_single_range_for_cpu(rq->pdev, head->addr, 0, frag_size, DMA_FROM_DEVICE); ++ prefetchw(hdr); ++ prefetch(data); ++ skb = mlx5e_build_linear_skb(rq, hdr, frag_size, rx_headroom, head_size); ++ ++ if (unlikely(!skb)) ++ return NULL; ++ ++ /* queue up for recycling/reuse */ ++ page_ref_inc(head->page); ++ ++ } else { ++ /* allocate SKB and copy header for large header */ ++ skb = napi_alloc_skb(rq->cq.napi, ++ ALIGN(head_size, sizeof(long))); ++ if (unlikely(!skb)) { ++ rq->stats->buff_alloc_err++; ++ return NULL; ++ } ++ ++ prefetchw(skb->data); ++ mlx5e_copy_skb_header(rq->pdev, skb, head, ++ head_offset + rx_headroom, ++ rx_headroom, head_size); ++ /* skb linear part was allocated with headlen and aligned to long */ ++ skb->tail += head_size; ++ skb->len += head_size; ++ } ++ return skb; ++} ++ ++static void ++mlx5e_free_rx_shampo_hd_entry(struct mlx5e_rq *rq, u16 header_index) ++{ ++ struct mlx5e_shampo_hd *shampo = rq->mpwqe.shampo; ++ u64 addr = shampo->info[header_index].addr; ++ ++ if (((header_index + 1) & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1)) == 0) { ++ shampo->info[header_index].addr = ALIGN_DOWN(addr, PAGE_SIZE); ++ mlx5e_page_release(rq, &shampo->info[header_index], true); ++ } ++ bitmap_clear(shampo->bitmap, header_index, 1); ++} ++ ++static void mlx5e_handle_rx_cqe_mpwrq_shampo(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) ++{ ++ u16 data_bcnt = mpwrq_get_cqe_byte_cnt(cqe) - cqe->shampo.header_size; ++ u16 header_index = be16_to_cpu(cqe->shampo.header_entry_index); ++ u32 wqe_offset = be32_to_cpu(cqe->shampo.data_offset); ++ u16 cstrides = mpwrq_get_cqe_consumed_strides(cqe); ++ u32 data_offset = wqe_offset & (PAGE_SIZE - 1); ++ u32 cqe_bcnt = mpwrq_get_cqe_byte_cnt(cqe); ++ u16 wqe_id = be16_to_cpu(cqe->wqe_id); ++ u32 page_idx = wqe_offset >> PAGE_SHIFT; ++ struct mlx5e_rx_wqe_ll *wqe; ++ struct sk_buff *skb = NULL; ++ struct mlx5e_dma_info *di; ++ struct mlx5e_mpw_info *wi; ++ struct mlx5_wq_ll *wq; ++ ++ wi = &rq->mpwqe.info[wqe_id]; ++ wi->consumed_strides += cstrides; ++ ++ if (unlikely(MLX5E_RX_ERR_CQE(cqe))) { ++ trigger_report(rq, cqe); ++ rq->stats->wqe_err++; ++ goto mpwrq_cqe_out; ++ } ++ ++ if (unlikely(mpwrq_is_filler_cqe(cqe))) { ++ struct mlx5e_rq_stats *stats = rq->stats; ++ ++ stats->mpwqe_filler_cqes++; ++ stats->mpwqe_filler_strides += cstrides; ++ goto mpwrq_cqe_out; ++ } ++ ++ skb = mlx5e_skb_from_cqe_shampo(rq, wi, cqe, header_index); ++ ++ if (unlikely(!skb)) ++ goto free_hd_entry; ++ ++ di = &wi->umr.dma_info[page_idx]; ++ mlx5e_fill_skb_data(skb, rq, di, data_bcnt, data_offset); ++ ++ mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); ++ napi_gro_receive(rq->cq.napi, skb); ++free_hd_entry: ++ mlx5e_free_rx_shampo_hd_entry(rq, header_index); ++mpwrq_cqe_out: ++ if (likely(wi->consumed_strides < rq->mpwqe.num_strides)) ++ return; ++ ++ wq = &rq->mpwqe.wq; ++ wqe = mlx5_wq_ll_get_wqe(wq, wqe_id); ++ mlx5e_free_rx_mpwqe(rq, wi, true); ++ mlx5_wq_ll_pop(wq, cqe->wqe_id, &wqe->next.next_wqe_index); ++} ++ + static void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) + { + u16 cstrides = mpwrq_get_cqe_consumed_strides(cqe); +@@ -1585,8 +1720,9 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) + + mlx5_cqwq_pop(cqwq); + +- INDIRECT_CALL_2(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq, +- mlx5e_handle_rx_cqe, rq, cqe); ++ INDIRECT_CALL_3(rq->handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq, ++ mlx5e_handle_rx_cqe, mlx5e_handle_rx_cqe_mpwrq_shampo, ++ rq, cqe); + } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(cqwq))); + + out: +@@ -1790,15 +1926,24 @@ int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool + rq->post_wqes = mlx5e_post_rx_mpwqes; + rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe; + +- rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe; + if (mlx5_fpga_is_ipsec_device(mdev)) { + netdev_err(netdev, "MPWQE RQ with Innova IPSec offload not supported\n"); + return -EINVAL; + } +- if (!rq->handle_rx_cqe) { +- netdev_err(netdev, "RX handler of MPWQE RQ is not set\n"); +- return -EINVAL; ++ if (params->packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO) { ++ rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe_shampo; ++ if (!rq->handle_rx_cqe) { ++ netdev_err(netdev, "RX handler of SHAMPO MPWQE RQ is not set\n"); ++ return -EINVAL; ++ } ++ } else { ++ rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe; ++ if (!rq->handle_rx_cqe) { ++ netdev_err(netdev, "RX handler of MPWQE RQ is not set\n"); ++ return -EINVAL; ++ } + } ++ + break; + default: /* MLX5_WQ_TYPE_CYCLIC */ + rq->wqe.skb_from_cqe = xsk ? +diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h +index afc7e2d81b6d..2b8398b939db 100644 +--- a/include/linux/mlx5/device.h ++++ b/include/linux/mlx5/device.h +@@ -797,10 +797,23 @@ struct mlx5_cqe64 { + u8 tls_outer_l3_tunneled; + u8 rsvd0; + __be16 wqe_id; +- u8 lro_tcppsh_abort_dupack; +- u8 lro_min_ttl; +- __be16 lro_tcp_win; +- __be32 lro_ack_seq_num; ++ union { ++ struct { ++ u8 tcppsh_abort_dupack; ++ u8 min_ttl; ++ __be16 tcp_win; ++ __be32 ack_seq_num; ++ } lro; ++ struct { ++ u8 reserved0:1; ++ u8 match:1; ++ u8 flush:1; ++ u8 reserved3:5; ++ u8 header_size; ++ __be16 header_entry_index; ++ __be32 data_offset; ++ } shampo; ++ }; + __be32 rss_hash_result; + u8 rss_hash_type; + u8 ml_path; +@@ -870,7 +883,7 @@ static inline u8 get_cqe_opcode(struct mlx5_cqe64 *cqe) + + static inline u8 get_cqe_lro_tcppsh(struct mlx5_cqe64 *cqe) + { +- return (cqe->lro_tcppsh_abort_dupack >> 6) & 1; ++ return (cqe->lro.tcppsh_abort_dupack >> 6) & 1; + } + + static inline u8 get_cqe_l4_hdr_type(struct mlx5_cqe64 *cqe) +-- +2.39.5 + diff --git a/queue-5.15/netpoll-prevent-hanging-napi-when-netcons-gets-enabl.patch b/queue-5.15/netpoll-prevent-hanging-napi-when-netcons-gets-enabl.patch new file mode 100644 index 0000000000..2f3c10880f --- /dev/null +++ b/queue-5.15/netpoll-prevent-hanging-napi-when-netcons-gets-enabl.patch @@ -0,0 +1,95 @@ +From 50364824a79c144cadd66da297418e748f70486d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Jul 2025 18:08:46 -0700 +Subject: netpoll: prevent hanging NAPI when netcons gets enabled + +From: Jakub Kicinski + +[ Upstream commit 2da4def0f487f24bbb0cece3bb2bcdcb918a0b72 ] + +Paolo spotted hangs in NIPA running driver tests against virtio. +The tests hang in virtnet_close() -> virtnet_napi_tx_disable(). + +The problem is only reproducible if running multiple of our tests +in sequence (I used TEST_PROGS="xdp.py ping.py netcons_basic.sh \ +netpoll_basic.py stats.py"). Initial suspicion was that this is +a simple case of double-disable of NAPI, but instrumenting the +code reveals: + + Deadlocked on NAPI ffff888007cd82c0 (virtnet_poll_tx): + state: 0x37, disabled: false, owner: 0, listed: false, weight: 64 + +The NAPI was not in fact disabled, owner is 0 (rather than -1), +so the NAPI "thinks" it's scheduled for CPU 0 but it's not listed +(!list_empty(&n->poll_list) => false). It seems odd that normal NAPI +processing would wedge itself like this. + +Better suspicion is that netpoll gets enabled while NAPI is polling, +and also grabs the NAPI instance. This confuses napi_complete_done(): + + [netpoll] [normal NAPI] + napi_poll() + have = netpoll_poll_lock() + rcu_access_pointer(dev->npinfo) + return NULL # no netpoll + __napi_poll() + ->poll(->weight) + poll_napi() + cmpxchg(->poll_owner, -1, cpu) + poll_one_napi() + set_bit(NAPI_STATE_NPSVC, ->state) + napi_complete_done() + if (NAPIF_STATE_NPSVC) + return false + # exit without clearing SCHED + +This feels very unlikely, but perhaps virtio has some interactions +with the hypervisor in the NAPI ->poll that makes the race window +larger? + +Best I could to to prove the theory was to add and trigger this +warning in napi_poll (just before netpoll_poll_unlock()): + + WARN_ONCE(!have && rcu_access_pointer(n->dev->npinfo) && + napi_is_scheduled(n) && list_empty(&n->poll_list), + "NAPI race with netpoll %px", n); + +If this warning hits the next virtio_close() will hang. + +This patch survived 30 test iterations without a hang (without it +the longest clean run was around 10). Credit for triggering this +goes to Breno's recent netconsole tests. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Paolo Abeni +Link: https://lore.kernel.org/c5a93ed1-9abe-4880-a3bb-8d1678018b1d@redhat.com +Acked-by: Jason Wang +Reviewed-by: Xuan Zhuo +Link: https://patch.msgid.link/20250726010846.1105875-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/netpoll.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/core/netpoll.c b/net/core/netpoll.c +index 87f5a837410c..c900badd5325 100644 +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -800,6 +800,13 @@ int netpoll_setup(struct netpoll *np) + goto put; + + rtnl_unlock(); ++ ++ /* Make sure all NAPI polls which started before dev->npinfo ++ * was visible have exited before we start calling NAPI poll. ++ * NAPI skips locking if dev->npinfo is NULL. ++ */ ++ synchronize_rcu(); ++ + return 0; + + put: +-- +2.39.5 + diff --git a/queue-5.15/nfs-fix-filehandle-bounds-checking-in-nfs_fh_to_dent.patch b/queue-5.15/nfs-fix-filehandle-bounds-checking-in-nfs_fh_to_dent.patch new file mode 100644 index 0000000000..1b0456787d --- /dev/null +++ b/queue-5.15/nfs-fix-filehandle-bounds-checking-in-nfs_fh_to_dent.patch @@ -0,0 +1,51 @@ +From 48dfbfa122323c30b1757ebd606f695122cff7e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Jul 2025 09:24:58 -0400 +Subject: NFS: Fix filehandle bounds checking in nfs_fh_to_dentry() + +From: Trond Myklebust + +[ Upstream commit ef93a685e01a281b5e2a25ce4e3428cf9371a205 ] + +The function needs to check the minimal filehandle length before it can +access the embedded filehandle. + +Reported-by: zhangjian +Fixes: 20fa19027286 ("nfs: add export operations") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/export.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/fs/nfs/export.c b/fs/nfs/export.c +index eafa9d7b0911..6bbe92a4eb0c 100644 +--- a/fs/nfs/export.c ++++ b/fs/nfs/export.c +@@ -67,14 +67,21 @@ nfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + struct nfs4_label *label = NULL; + struct nfs_fattr *fattr = NULL; + struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw); +- size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; ++ size_t fh_size = offsetof(struct nfs_fh, data); + const struct nfs_rpc_ops *rpc_ops; + struct dentry *dentry; + struct inode *inode; +- int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); ++ int len = EMBED_FH_OFF; + u32 *p = fid->raw; + int ret; + ++ /* Initial check of bounds */ ++ if (fh_len < len + XDR_QUADLEN(fh_size) || ++ fh_len > XDR_QUADLEN(NFS_MAXFHSIZE)) ++ return NULL; ++ /* Calculate embedded filehandle size */ ++ fh_size += server_fh->size; ++ len += XDR_QUADLEN(fh_size); + /* NULL translates to ESTALE */ + if (fh_len < len || fh_type != len) + return NULL; +-- +2.39.5 + diff --git a/queue-5.15/nfs-fixup-allocation-flags-for-nfsiod-s-__gfp_noretr.patch b/queue-5.15/nfs-fixup-allocation-flags-for-nfsiod-s-__gfp_noretr.patch new file mode 100644 index 0000000000..1a3a76b7ae --- /dev/null +++ b/queue-5.15/nfs-fixup-allocation-flags-for-nfsiod-s-__gfp_noretr.patch @@ -0,0 +1,55 @@ +From 1a654646acaf6755670ac52483b661f78bc0f0af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 21:47:43 -0400 +Subject: NFS: Fixup allocation flags for nfsiod's __GFP_NORETRY + +From: Benjamin Coddington + +[ Upstream commit 99765233ab42bf7a4950377ad7894dce8a5c0e60 ] + +If the NFS client is doing writeback from a workqueue context, avoid using +__GFP_NORETRY for allocations if the task has set PF_MEMALLOC_NOIO or +PF_MEMALLOC_NOFS. The combination of these flags makes memory allocation +failures much more likely. + +We've seen those allocation failures show up when the loopback driver is +doing writeback from a workqueue to a file on NFS, where memory allocation +failure results in errors or corruption within the loopback device's +filesystem. + +Suggested-by: Trond Myklebust +Fixes: 0bae835b63c5 ("NFS: Avoid writeback threads getting stuck in mempool_alloc()") +Signed-off-by: Benjamin Coddington +Reviewed-by: Laurence Oberman +Tested-by: Laurence Oberman +Reviewed-by: Jeff Layton +Link: https://lore.kernel.org/r/f83ac1155a4bc670f2663959a7a068571e06afd9.1752111622.git.bcodding@redhat.com +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/internal.h | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h +index a6d0b64dda36..76605eb93609 100644 +--- a/fs/nfs/internal.h ++++ b/fs/nfs/internal.h +@@ -581,9 +581,12 @@ nfs_write_match_verf(const struct nfs_writeverf *verf, + + static inline gfp_t nfs_io_gfp_mask(void) + { +- if (current->flags & PF_WQ_WORKER) +- return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; +- return GFP_KERNEL; ++ gfp_t ret = current_gfp_context(GFP_KERNEL); ++ ++ /* For workers __GFP_NORETRY only with __GFP_IO or __GFP_FS */ ++ if ((current->flags & PF_WQ_WORKER) && ret == GFP_KERNEL) ++ ret |= __GFP_NORETRY | __GFP_NOWARN; ++ return ret; + } + + /* unlink.c */ +-- +2.39.5 + diff --git a/queue-5.15/nfsv4.2-another-fix-for-listxattr.patch b/queue-5.15/nfsv4.2-another-fix-for-listxattr.patch new file mode 100644 index 0000000000..2a7f0272d1 --- /dev/null +++ b/queue-5.15/nfsv4.2-another-fix-for-listxattr.patch @@ -0,0 +1,53 @@ +From ab4bf135f34ecc0e9296527f1d97e63ce4eb64ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Jul 2025 16:56:41 -0400 +Subject: NFSv4.2: another fix for listxattr + +From: Olga Kornievskaia + +[ Upstream commit 9acb237deff7667b0f6b10fe6b1b70c4429ea049 ] + +Currently, when the server supports NFS4.1 security labels then +security.selinux label in included twice. Instead, only add it +when the server doesn't possess security label support. + +Fixes: 243fea134633 ("NFSv4.2: fix listxattr to return selinux security label") +Signed-off-by: Olga Kornievskaia +Link: https://lore.kernel.org/r/20250722205641.79394-1-okorniev@redhat.com +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 9d4e4146efef..528e904f5475 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -10528,7 +10528,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { + + static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size) + { +- ssize_t error, error2, error3, error4; ++ ssize_t error, error2, error3, error4 = 0; + size_t left = size; + + error = generic_listxattr(dentry, list, left); +@@ -10556,9 +10556,11 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size) + left -= error3; + } + +- error4 = security_inode_listsecurity(d_inode(dentry), list, left); +- if (error4 < 0) +- return error4; ++ if (!nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) { ++ error4 = security_inode_listsecurity(d_inode(dentry), list, left); ++ if (error4 < 0) ++ return error4; ++ } + + error += error2 + error3 + error4; + if (size && error > size) +-- +2.39.5 + diff --git a/queue-5.15/phy-mscc-fix-parsing-of-unicast-frames.patch b/queue-5.15/phy-mscc-fix-parsing-of-unicast-frames.patch new file mode 100644 index 0000000000..13f0ed13e5 --- /dev/null +++ b/queue-5.15/phy-mscc-fix-parsing-of-unicast-frames.patch @@ -0,0 +1,53 @@ +From cbfd55cd49ddff99337d47772b3a34e87054f68c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Jul 2025 16:03:07 +0200 +Subject: phy: mscc: Fix parsing of unicast frames + +From: Horatiu Vultur + +[ Upstream commit 6fb5ff63b35b7e849cc8510957f25753f87f63d2 ] + +According to the 1588 standard, it is possible to use both unicast and +multicast frames to send the PTP information. It was noticed that if the +frames were unicast they were not processed by the analyzer meaning that +they were not timestamped. Therefore fix this to match also these +unicast frames. + +Fixes: ab2bf9339357 ("net: phy: mscc: 1588 block initialization") +Signed-off-by: Horatiu Vultur +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250726140307.3039694-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mscc/mscc_ptp.c | 1 + + drivers/net/phy/mscc/mscc_ptp.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/phy/mscc/mscc_ptp.c b/drivers/net/phy/mscc/mscc_ptp.c +index 7a3a8cce02d3..92f59c964409 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.c ++++ b/drivers/net/phy/mscc/mscc_ptp.c +@@ -897,6 +897,7 @@ static int vsc85xx_eth1_conf(struct phy_device *phydev, enum ts_blk blk, + get_unaligned_be32(ptp_multicast)); + } else { + val |= ANA_ETH1_FLOW_ADDR_MATCH2_ANY_MULTICAST; ++ val |= ANA_ETH1_FLOW_ADDR_MATCH2_ANY_UNICAST; + vsc85xx_ts_write_csr(phydev, blk, + MSCC_ANA_ETH1_FLOW_ADDR_MATCH2(0), val); + vsc85xx_ts_write_csr(phydev, blk, +diff --git a/drivers/net/phy/mscc/mscc_ptp.h b/drivers/net/phy/mscc/mscc_ptp.h +index da3465360e90..ae9ad925bfa8 100644 +--- a/drivers/net/phy/mscc/mscc_ptp.h ++++ b/drivers/net/phy/mscc/mscc_ptp.h +@@ -98,6 +98,7 @@ + #define MSCC_ANA_ETH1_FLOW_ADDR_MATCH2(x) (MSCC_ANA_ETH1_FLOW_ENA(x) + 3) + #define ANA_ETH1_FLOW_ADDR_MATCH2_MASK_MASK GENMASK(22, 20) + #define ANA_ETH1_FLOW_ADDR_MATCH2_ANY_MULTICAST 0x400000 ++#define ANA_ETH1_FLOW_ADDR_MATCH2_ANY_UNICAST 0x200000 + #define ANA_ETH1_FLOW_ADDR_MATCH2_FULL_ADDR 0x100000 + #define ANA_ETH1_FLOW_ADDR_MATCH2_SRC_DEST_MASK GENMASK(17, 16) + #define ANA_ETH1_FLOW_ADDR_MATCH2_SRC_DEST 0x020000 +-- +2.39.5 + diff --git a/queue-5.15/pnfs-flexfiles-don-t-attempt-pnfs-on-fatal-ds-errors.patch b/queue-5.15/pnfs-flexfiles-don-t-attempt-pnfs-on-fatal-ds-errors.patch new file mode 100644 index 0000000000..26fe845ca5 --- /dev/null +++ b/queue-5.15/pnfs-flexfiles-don-t-attempt-pnfs-on-fatal-ds-errors.patch @@ -0,0 +1,176 @@ +From a84cf8c10a084b2b595a990f59a29a10649897c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Jun 2025 09:17:51 +0200 +Subject: pNFS/flexfiles: don't attempt pnfs on fatal DS errors + +From: Tigran Mkrtchyan + +[ Upstream commit f06bedfa62d57f7b67d44aacd6badad2e13a803f ] + +When an applications get killed (SIGTERM/SIGINT) while pNFS client performs a connection +to DS, client ends in an infinite loop of connect-disconnect. This +source of the issue, it that flexfilelayoutdev#nfs4_ff_layout_prepare_ds gets an error +on nfs4_pnfs_ds_connect with status ERESTARTSYS, which is set by rpc_signal_task, but +the error is treated as transient, thus retried. + +The issue is reproducible with Ctrl+C the following script(there should be ~1000 files in +a directory, client should must not have any connections to DSes): + +``` +echo 3 > /proc/sys/vm/drop_caches + +for i in * +do + head -1 $i +done +``` + +The change aims to propagate the nfs4_ff_layout_prepare_ds error state +to the caller that can decide whatever this is a retryable error or not. + +Signed-off-by: Tigran Mkrtchyan +Link: https://lore.kernel.org/r/20250627071751.189663-1-tigran.mkrtchyan@desy.de +Fixes: 260f32adb88d ("pNFS/flexfiles: Check the result of nfs4_pnfs_ds_connect") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 26 ++++++++++++++--------- + fs/nfs/flexfilelayout/flexfilelayoutdev.c | 6 +++--- + 2 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index 7a568d2de472..14c7de8fd781 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -739,14 +739,14 @@ ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg, + { + struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); + struct nfs4_ff_layout_mirror *mirror; +- struct nfs4_pnfs_ds *ds; ++ struct nfs4_pnfs_ds *ds = ERR_PTR(-EAGAIN); + u32 idx; + + /* mirrors are initially sorted by efficiency */ + for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) { + mirror = FF_LAYOUT_COMP(lseg, idx); + ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); +- if (!ds) ++ if (IS_ERR(ds)) + continue; + + if (check_device && +@@ -754,10 +754,10 @@ ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg, + continue; + + *best_idx = idx; +- return ds; ++ break; + } + +- return NULL; ++ return ds; + } + + static struct nfs4_pnfs_ds * +@@ -933,7 +933,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio, + for (i = 0; i < pgio->pg_mirror_count; i++) { + mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i); + ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, mirror, true); +- if (!ds) { ++ if (IS_ERR(ds)) { + if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg)) + goto out_mds; + pnfs_generic_pg_cleanup(pgio); +@@ -1826,6 +1826,7 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) + u32 idx = hdr->pgio_mirror_idx; + int vers; + struct nfs_fh *fh; ++ bool ds_fatal_error = false; + + dprintk("--> %s ino %lu pgbase %u req %zu@%llu\n", + __func__, hdr->inode->i_ino, +@@ -1833,8 +1834,10 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) + + mirror = FF_LAYOUT_COMP(lseg, idx); + ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); +- if (!ds) ++ if (IS_ERR(ds)) { ++ ds_fatal_error = nfs_error_is_fatal(PTR_ERR(ds)); + goto out_failed; ++ } + + ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, + hdr->inode); +@@ -1875,7 +1878,7 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) + return PNFS_ATTEMPTED; + + out_failed: +- if (ff_layout_avoid_mds_available_ds(lseg)) ++ if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error) + return PNFS_TRY_AGAIN; + trace_pnfs_mds_fallback_read_pagelist(hdr->inode, + hdr->args.offset, hdr->args.count, +@@ -1896,11 +1899,14 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) + int vers; + struct nfs_fh *fh; + u32 idx = hdr->pgio_mirror_idx; ++ bool ds_fatal_error = false; + + mirror = FF_LAYOUT_COMP(lseg, idx); + ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); +- if (!ds) ++ if (IS_ERR(ds)) { ++ ds_fatal_error = nfs_error_is_fatal(PTR_ERR(ds)); + goto out_failed; ++ } + + ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, + hdr->inode); +@@ -1943,7 +1949,7 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) + return PNFS_ATTEMPTED; + + out_failed: +- if (ff_layout_avoid_mds_available_ds(lseg)) ++ if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error) + return PNFS_TRY_AGAIN; + trace_pnfs_mds_fallback_write_pagelist(hdr->inode, + hdr->args.offset, hdr->args.count, +@@ -1985,7 +1991,7 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how) + idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); + mirror = FF_LAYOUT_COMP(lseg, idx); + ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); +- if (!ds) ++ if (IS_ERR(ds)) + goto out_err; + + ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, +diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c +index 4b0cdddce6eb..11777d33a85e 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c ++++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c +@@ -368,11 +368,11 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, + struct nfs4_ff_layout_mirror *mirror, + bool fail_return) + { +- struct nfs4_pnfs_ds *ds = NULL; ++ struct nfs4_pnfs_ds *ds; + struct inode *ino = lseg->pls_layout->plh_inode; + struct nfs_server *s = NFS_SERVER(ino); + unsigned int max_payload; +- int status; ++ int status = -EAGAIN; + + if (!ff_layout_init_mirror_ds(lseg->pls_layout, mirror)) + goto noconnect; +@@ -410,7 +410,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, + ff_layout_send_layouterror(lseg); + if (fail_return || !ff_layout_has_available_ds(lseg)) + pnfs_error_mark_layout_for_return(ino, lseg); +- ds = NULL; ++ ds = ERR_PTR(status); + out: + return ds; + } +-- +2.39.5 + diff --git a/queue-5.15/pptp-ensure-minimal-skb-length-in-pptp_xmit.patch b/queue-5.15/pptp-ensure-minimal-skb-length-in-pptp_xmit.patch new file mode 100644 index 0000000000..df44e95267 --- /dev/null +++ b/queue-5.15/pptp-ensure-minimal-skb-length-in-pptp_xmit.patch @@ -0,0 +1,92 @@ +From 5d04210c5a1cb6811401193cd56ce89b037cb70f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Jul 2025 08:02:07 +0000 +Subject: pptp: ensure minimal skb length in pptp_xmit() + +From: Eric Dumazet + +[ Upstream commit de9c4861fb42f0cd72da844c3c34f692d5895b7b ] + +Commit aabc6596ffb3 ("net: ppp: Add bound checking for skb data +on ppp_sync_txmung") fixed ppp_sync_txmunge() + +We need a similar fix in pptp_xmit(), otherwise we might +read uninit data as reported by syzbot. + +BUG: KMSAN: uninit-value in pptp_xmit+0xc34/0x2720 drivers/net/ppp/pptp.c:193 + pptp_xmit+0xc34/0x2720 drivers/net/ppp/pptp.c:193 + ppp_channel_bridge_input drivers/net/ppp/ppp_generic.c:2290 [inline] + ppp_input+0x1d6/0xe60 drivers/net/ppp/ppp_generic.c:2314 + pppoe_rcv_core+0x1e8/0x760 drivers/net/ppp/pppoe.c:379 + sk_backlog_rcv+0x142/0x420 include/net/sock.h:1148 + __release_sock+0x1d3/0x330 net/core/sock.c:3213 + release_sock+0x6b/0x270 net/core/sock.c:3767 + pppoe_sendmsg+0x15d/0xcb0 drivers/net/ppp/pppoe.c:904 + sock_sendmsg_nosec net/socket.c:712 [inline] + __sock_sendmsg+0x330/0x3d0 net/socket.c:727 + ____sys_sendmsg+0x893/0xd80 net/socket.c:2566 + ___sys_sendmsg+0x271/0x3b0 net/socket.c:2620 + __sys_sendmmsg+0x2d9/0x7c0 net/socket.c:2709 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: syzbot+afad90ffc8645324afe5@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/68887d86.a00a0220.b12ec.00cd.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Dawid Osuchowski +Link: https://patch.msgid.link/20250729080207.1863408-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/pptp.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 32183f24e63f..951dac268adb 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -159,9 +159,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + int len; + unsigned char *data; + __u32 seq_recv; +- +- +- struct rtable *rt; ++ struct rtable *rt = NULL; + struct net_device *tdev; + struct iphdr *iph; + int max_headroom; +@@ -179,16 +177,20 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + + if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { + struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); +- if (!new_skb) { +- ip_rt_put(rt); ++ ++ if (!new_skb) + goto tx_error; +- } ++ + if (skb->sk) + skb_set_owner_w(new_skb, skb->sk); + consume_skb(skb); + skb = new_skb; + } + ++ /* Ensure we can safely access protocol field and LCP code */ ++ if (!pskb_may_pull(skb, 3)) ++ goto tx_error; ++ + data = skb->data; + islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7; + +@@ -262,6 +264,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + return 1; + + tx_error: ++ ip_rt_put(rt); + kfree_skb(skb); + return 1; + } +-- +2.39.5 + diff --git a/queue-5.15/pptp-fix-pptp_xmit-error-path.patch b/queue-5.15/pptp-fix-pptp_xmit-error-path.patch new file mode 100644 index 0000000000..b6bdc48bab --- /dev/null +++ b/queue-5.15/pptp-fix-pptp_xmit-error-path.patch @@ -0,0 +1,84 @@ +From f0119df1dbbdb8b812235fcf22b6b8968daa7897 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Aug 2025 14:21:46 +0000 +Subject: pptp: fix pptp_xmit() error path + +From: Eric Dumazet + +[ Upstream commit ae633388cae349886f1a3cfb27aa092854b24c1b ] + +I accidentally added a bug in pptp_xmit() that syzbot caught for us. + +Only call ip_rt_put() if a route has been allocated. + +BUG: unable to handle page fault for address: ffffffffffffffdb +PGD df3b067 P4D df3b067 PUD df3d067 PMD 0 +Oops: Oops: 0002 [#1] SMP KASAN PTI +CPU: 1 UID: 0 PID: 6346 Comm: syz.0.336 Not tainted 6.16.0-next-20250804-syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 +RIP: 0010:arch_atomic_add_return arch/x86/include/asm/atomic.h:85 [inline] +RIP: 0010:raw_atomic_sub_return_release include/linux/atomic/atomic-arch-fallback.h:846 [inline] +RIP: 0010:atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:327 [inline] +RIP: 0010:__rcuref_put include/linux/rcuref.h:109 [inline] +RIP: 0010:rcuref_put+0x172/0x210 include/linux/rcuref.h:173 +Call Trace: + + dst_release+0x24/0x1b0 net/core/dst.c:167 + ip_rt_put include/net/route.h:285 [inline] + pptp_xmit+0x14b/0x1a90 drivers/net/ppp/pptp.c:267 + __ppp_channel_push+0xf2/0x1c0 drivers/net/ppp/ppp_generic.c:2166 + ppp_channel_push+0x123/0x660 drivers/net/ppp/ppp_generic.c:2198 + ppp_write+0x2b0/0x400 drivers/net/ppp/ppp_generic.c:544 + vfs_write+0x27b/0xb30 fs/read_write.c:684 + ksys_write+0x145/0x250 fs/read_write.c:738 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: de9c4861fb42 ("pptp: ensure minimal skb length in pptp_xmit()") +Reported-by: syzbot+27d7cfbc93457e472e00@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/689095a5.050a0220.1fc43d.0009.GAE@google.com/ +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250807142146.2877060-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/pptp.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 951dac268adb..bf011bbb6105 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -159,17 +159,17 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + int len; + unsigned char *data; + __u32 seq_recv; +- struct rtable *rt = NULL; ++ struct rtable *rt; + struct net_device *tdev; + struct iphdr *iph; + int max_headroom; + + if (sk_pppox(po)->sk_state & PPPOX_DEAD) +- goto tx_error; ++ goto tx_drop; + + rt = pptp_route_output(po, &fl4); + if (IS_ERR(rt)) +- goto tx_error; ++ goto tx_drop; + + tdev = rt->dst.dev; + +@@ -265,6 +265,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + + tx_error: + ip_rt_put(rt); ++tx_drop: + kfree_skb(skb); + return 1; + } +-- +2.39.5 + diff --git a/queue-5.15/series b/queue-5.15/series index 2db3d1d5ff..878713db0d 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -223,3 +223,23 @@ powerpc-eeh-export-eeh_unfreeze_pe.patch powerpc-eeh-rely-on-dev-link_active_reporting.patch powerpc-eeh-make-eeh-driver-device-hotplug-safe.patch pci-pnv_php-fix-surprise-plug-detection-and-recovery.patch +pnfs-flexfiles-don-t-attempt-pnfs-on-fatal-ds-errors.patch +nfs-fix-filehandle-bounds-checking-in-nfs_fh_to_dent.patch +nfsv4.2-another-fix-for-listxattr.patch +xarray-add-calls-to-might_alloc.patch +nfs-fixup-allocation-flags-for-nfsiod-s-__gfp_noretr.patch +netpoll-prevent-hanging-napi-when-netcons-gets-enabl.patch +phy-mscc-fix-parsing-of-unicast-frames.patch +pptp-ensure-minimal-skb-length-in-pptp_xmit.patch +net-mlx5e-add-handle-shampo-cqe-support.patch +net-mlx5-correctly-set-gso_segs-when-lro-is-used.patch +ipv6-reject-malicious-packets-in-ipv6_gso_segment.patch +net-drop-ufo-packets-in-udp_rcv_segment.patch +benet-fix-bug-when-creating-vfs.patch +alsa-hda-ca0132-fix-missing-error-handling-in-ca0132.patch +smb-server-remove-separate-empty_recvmsg_queue.patch +smb-server-make-sure-we-call-ib_dma_unmap_single-onl.patch +smb-server-let-recv_done-consistently-call-put_recvm.patch +smb-server-let-recv_done-avoid-touching-data_transfe.patch +smb-client-let-recv_done-cleanup-before-notifying-th.patch +pptp-fix-pptp_xmit-error-path.patch diff --git a/queue-5.15/smb-client-let-recv_done-cleanup-before-notifying-th.patch b/queue-5.15/smb-client-let-recv_done-cleanup-before-notifying-th.patch new file mode 100644 index 0000000000..56863f8181 --- /dev/null +++ b/queue-5.15/smb-client-let-recv_done-cleanup-before-notifying-th.patch @@ -0,0 +1,79 @@ +From 490d7970baa5ebe456c77d9ded7fc291b84b36d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Aug 2025 14:10:15 +0200 +Subject: smb: client: let recv_done() cleanup before notifying the callers. + +From: Stefan Metzmacher + +[ Upstream commit bdd7afc6dca5e0ebbb75583484aa6ea9e03fbb13 ] + +We should call put_receive_buffer() before waking up the callers. + +For the internal error case of response->type being unexpected, +we now also call smbd_disconnect_rdma_connection() instead +of not waking up the callers at all. + +Note that the SMBD_TRANSFER_DATA case still has problems, +which will be addressed in the next commit in order to make +it easier to review this one. + +Cc: Steve French +Cc: Tom Talpey +Cc: Long Li +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Fixes: f198186aa9bb ("CIFS: SMBD: Establish SMB Direct connection") +Signed-off-by: Stefan Metzmacher +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smbdirect.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c +index a9a5d27b8d38..48bd879349fb 100644 +--- a/fs/cifs/smbdirect.c ++++ b/fs/cifs/smbdirect.c +@@ -455,7 +455,6 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { + log_rdma_recv(INFO, "wc->status=%d opcode=%d\n", + wc->status, wc->opcode); +- smbd_disconnect_rdma_connection(info); + goto error; + } + +@@ -472,8 +471,9 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + info->full_packet_received = true; + info->negotiate_done = + process_negotiation_response(response, wc->byte_len); ++ put_receive_buffer(info, response); + complete(&info->negotiate_completion); +- break; ++ return; + + /* SMBD data transfer packet */ + case SMBD_TRANSFER_DATA: +@@ -530,14 +530,16 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + } + + return; +- +- default: +- log_rdma_recv(ERR, +- "unexpected response type=%d\n", response->type); + } + ++ /* ++ * This is an internal error! ++ */ ++ log_rdma_recv(ERR, "unexpected response type=%d\n", response->type); ++ WARN_ON_ONCE(response->type != SMBD_TRANSFER_DATA); + error: + put_receive_buffer(info, response); ++ smbd_disconnect_rdma_connection(info); + } + + static struct rdma_cm_id *smbd_create_id( +-- +2.39.5 + diff --git a/queue-5.15/smb-server-let-recv_done-avoid-touching-data_transfe.patch b/queue-5.15/smb-server-let-recv_done-avoid-touching-data_transfe.patch new file mode 100644 index 0000000000..2e87575e14 --- /dev/null +++ b/queue-5.15/smb-server-let-recv_done-avoid-touching-data_transfe.patch @@ -0,0 +1,67 @@ +From b16a9ab179b099ef765b5a149bdf003b253cddec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Aug 2025 14:15:53 +0200 +Subject: smb: server: let recv_done() avoid touching data_transfer after + cleanup/move + +From: Stefan Metzmacher + +[ Upstream commit a6c015b7ac2d8c5233337e5793f50d04fac17669 ] + +Calling enqueue_reassembly() and wake_up_interruptible(&t->wait_reassembly_queue) +or put_receive_buffer() means the recvmsg/data_transfer pointer might +get re-used by another thread, which means these should be +the last operations before calling return. + +Cc: Namjae Jeon +Cc: Steve French +Cc: Tom Talpey +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") +Signed-off-by: Stefan Metzmacher +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/transport_rdma.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c +index 07e1e6bbdd54..2f0263290584 100644 +--- a/fs/ksmbd/transport_rdma.c ++++ b/fs/ksmbd/transport_rdma.c +@@ -575,16 +575,11 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + else + t->full_packet_received = true; + +- enqueue_reassembly(t, recvmsg, (int)data_length); +- wake_up_interruptible(&t->wait_reassembly_queue); +- + spin_lock(&t->receive_credit_lock); + receive_credits = --(t->recv_credits); + avail_recvmsg_count = t->count_avail_recvmsg; + spin_unlock(&t->receive_credit_lock); + } else { +- put_recvmsg(t, recvmsg); +- + spin_lock(&t->receive_credit_lock); + receive_credits = --(t->recv_credits); + avail_recvmsg_count = ++(t->count_avail_recvmsg); +@@ -606,6 +601,13 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count)) + mod_delayed_work(smb_direct_wq, + &t->post_recv_credits_work, 0); ++ ++ if (data_length) { ++ enqueue_reassembly(t, recvmsg, (int)data_length); ++ wake_up_interruptible(&t->wait_reassembly_queue); ++ } else ++ put_recvmsg(t, recvmsg); ++ + return; + } + } +-- +2.39.5 + diff --git a/queue-5.15/smb-server-let-recv_done-consistently-call-put_recvm.patch b/queue-5.15/smb-server-let-recv_done-consistently-call-put_recvm.patch new file mode 100644 index 0000000000..7ecd029bab --- /dev/null +++ b/queue-5.15/smb-server-let-recv_done-consistently-call-put_recvm.patch @@ -0,0 +1,105 @@ +From ed6fd10a44ecb6cd8e8e3db63da023606dcd2bad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Aug 2025 14:15:52 +0200 +Subject: smb: server: let recv_done() consistently call + put_recvmsg/smb_direct_disconnect_rdma_connection + +From: Stefan Metzmacher + +[ Upstream commit cfe76fdbb9729c650f3505d9cfb2f70ddda2dbdc ] + +We should call put_recvmsg() before smb_direct_disconnect_rdma_connection() +in order to call it before waking up the callers. + +In all error cases we should call smb_direct_disconnect_rdma_connection() +in order to avoid stale connections. + +Cc: Namjae Jeon +Cc: Steve French +Cc: Tom Talpey +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") +Signed-off-by: Stefan Metzmacher +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/transport_rdma.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c +index dd37cabe8cbc..07e1e6bbdd54 100644 +--- a/fs/ksmbd/transport_rdma.c ++++ b/fs/ksmbd/transport_rdma.c +@@ -515,13 +515,13 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + t = recvmsg->transport; + + if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { ++ put_recvmsg(t, recvmsg); + if (wc->status != IB_WC_WR_FLUSH_ERR) { + pr_err("Recv error. status='%s (%d)' opcode=%d\n", + ib_wc_status_msg(wc->status), wc->status, + wc->opcode); + smb_direct_disconnect_rdma_connection(t); + } +- put_recvmsg(t, recvmsg); + return; + } + +@@ -536,6 +536,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + case SMB_DIRECT_MSG_NEGOTIATE_REQ: + if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) { + put_recvmsg(t, recvmsg); ++ smb_direct_disconnect_rdma_connection(t); + return; + } + t->negotiation_requested = true; +@@ -543,7 +544,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + t->status = SMB_DIRECT_CS_CONNECTED; + enqueue_reassembly(t, recvmsg, 0); + wake_up_interruptible(&t->wait_status); +- break; ++ return; + case SMB_DIRECT_MSG_DATA_TRANSFER: { + struct smb_direct_data_transfer *data_transfer = + (struct smb_direct_data_transfer *)recvmsg->packet; +@@ -553,6 +554,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + if (wc->byte_len < + offsetof(struct smb_direct_data_transfer, padding)) { + put_recvmsg(t, recvmsg); ++ smb_direct_disconnect_rdma_connection(t); + return; + } + +@@ -561,6 +563,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + if (wc->byte_len < sizeof(struct smb_direct_data_transfer) + + (u64)data_length) { + put_recvmsg(t, recvmsg); ++ smb_direct_disconnect_rdma_connection(t); + return; + } + +@@ -603,11 +606,16 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count)) + mod_delayed_work(smb_direct_wq, + &t->post_recv_credits_work, 0); +- break; ++ return; + } +- default: +- break; + } ++ ++ /* ++ * This is an internal error! ++ */ ++ WARN_ON_ONCE(recvmsg->type != SMB_DIRECT_MSG_DATA_TRANSFER); ++ put_recvmsg(t, recvmsg); ++ smb_direct_disconnect_rdma_connection(t); + } + + static int smb_direct_post_recv(struct smb_direct_transport *t, +-- +2.39.5 + diff --git a/queue-5.15/smb-server-make-sure-we-call-ib_dma_unmap_single-onl.patch b/queue-5.15/smb-server-make-sure-we-call-ib_dma_unmap_single-onl.patch new file mode 100644 index 0000000000..b8622f10b1 --- /dev/null +++ b/queue-5.15/smb-server-make-sure-we-call-ib_dma_unmap_single-onl.patch @@ -0,0 +1,68 @@ +From 5e2b9de3e04488516620da2f9079123d62bddcdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Aug 2025 14:15:51 +0200 +Subject: smb: server: make sure we call ib_dma_unmap_single() only if we + called ib_dma_map_single already + +From: Stefan Metzmacher + +[ Upstream commit afb4108c92898350e66b9a009692230bcdd2ac73 ] + +In case of failures either ib_dma_map_single() might not be called yet +or ib_dma_unmap_single() was already called. + +We should make sure put_recvmsg() only calls ib_dma_unmap_single() if needed. + +Cc: Namjae Jeon +Cc: Steve French +Cc: Tom Talpey +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") +Signed-off-by: Stefan Metzmacher +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/transport_rdma.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c +index 2644117305c2..dd37cabe8cbc 100644 +--- a/fs/ksmbd/transport_rdma.c ++++ b/fs/ksmbd/transport_rdma.c +@@ -263,8 +263,13 @@ smb_direct_recvmsg *get_free_recvmsg(struct smb_direct_transport *t) + static void put_recvmsg(struct smb_direct_transport *t, + struct smb_direct_recvmsg *recvmsg) + { +- ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, +- recvmsg->sge.length, DMA_FROM_DEVICE); ++ if (likely(recvmsg->sge.length != 0)) { ++ ib_dma_unmap_single(t->cm_id->device, ++ recvmsg->sge.addr, ++ recvmsg->sge.length, ++ DMA_FROM_DEVICE); ++ recvmsg->sge.length = 0; ++ } + + spin_lock(&t->recvmsg_queue_lock); + list_add(&recvmsg->list, &t->recvmsg_queue); +@@ -632,6 +637,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t, + ib_dma_unmap_single(t->cm_id->device, + recvmsg->sge.addr, recvmsg->sge.length, + DMA_FROM_DEVICE); ++ recvmsg->sge.length = 0; + smb_direct_disconnect_rdma_connection(t); + return ret; + } +@@ -1813,6 +1819,7 @@ static int smb_direct_create_pools(struct smb_direct_transport *t) + if (!recvmsg) + goto err; + recvmsg->transport = t; ++ recvmsg->sge.length = 0; + list_add(&recvmsg->list, &t->recvmsg_queue); + } + t->count_avail_recvmsg = t->recv_credit_max; +-- +2.39.5 + diff --git a/queue-5.15/smb-server-remove-separate-empty_recvmsg_queue.patch b/queue-5.15/smb-server-remove-separate-empty_recvmsg_queue.patch new file mode 100644 index 0000000000..85ba59fd49 --- /dev/null +++ b/queue-5.15/smb-server-remove-separate-empty_recvmsg_queue.patch @@ -0,0 +1,169 @@ +From 5c6cdbaad503b024a57f5c2e4ea2a26af71db74c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Aug 2025 14:15:50 +0200 +Subject: smb: server: remove separate empty_recvmsg_queue + +From: Stefan Metzmacher + +[ Upstream commit 01027a62b508c48c762096f347de925eedcbd008 ] + +There's no need to maintain two lists, we can just +have a single list of receive buffers, which are free to use. + +Cc: Steve French +Cc: Tom Talpey +Cc: linux-cifs@vger.kernel.org +Cc: samba-technical@lists.samba.org +Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") +Signed-off-by: Stefan Metzmacher +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/transport_rdma.c | 60 ++++++--------------------------------- + 1 file changed, 8 insertions(+), 52 deletions(-) + +diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c +index 91e663d5d5bc..2644117305c2 100644 +--- a/fs/ksmbd/transport_rdma.c ++++ b/fs/ksmbd/transport_rdma.c +@@ -128,9 +128,6 @@ struct smb_direct_transport { + spinlock_t recvmsg_queue_lock; + struct list_head recvmsg_queue; + +- spinlock_t empty_recvmsg_queue_lock; +- struct list_head empty_recvmsg_queue; +- + int send_credit_target; + atomic_t send_credits; + spinlock_t lock_new_recv_credits; +@@ -274,32 +271,6 @@ static void put_recvmsg(struct smb_direct_transport *t, + spin_unlock(&t->recvmsg_queue_lock); + } + +-static struct +-smb_direct_recvmsg *get_empty_recvmsg(struct smb_direct_transport *t) +-{ +- struct smb_direct_recvmsg *recvmsg = NULL; +- +- spin_lock(&t->empty_recvmsg_queue_lock); +- if (!list_empty(&t->empty_recvmsg_queue)) { +- recvmsg = list_first_entry(&t->empty_recvmsg_queue, +- struct smb_direct_recvmsg, list); +- list_del(&recvmsg->list); +- } +- spin_unlock(&t->empty_recvmsg_queue_lock); +- return recvmsg; +-} +- +-static void put_empty_recvmsg(struct smb_direct_transport *t, +- struct smb_direct_recvmsg *recvmsg) +-{ +- ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, +- recvmsg->sge.length, DMA_FROM_DEVICE); +- +- spin_lock(&t->empty_recvmsg_queue_lock); +- list_add_tail(&recvmsg->list, &t->empty_recvmsg_queue); +- spin_unlock(&t->empty_recvmsg_queue_lock); +-} +- + static void enqueue_reassembly(struct smb_direct_transport *t, + struct smb_direct_recvmsg *recvmsg, + int data_length) +@@ -384,9 +355,6 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id) + spin_lock_init(&t->recvmsg_queue_lock); + INIT_LIST_HEAD(&t->recvmsg_queue); + +- spin_lock_init(&t->empty_recvmsg_queue_lock); +- INIT_LIST_HEAD(&t->empty_recvmsg_queue); +- + init_waitqueue_head(&t->wait_send_pending); + atomic_set(&t->send_pending, 0); + +@@ -548,7 +516,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + wc->opcode); + smb_direct_disconnect_rdma_connection(t); + } +- put_empty_recvmsg(t, recvmsg); ++ put_recvmsg(t, recvmsg); + return; + } + +@@ -562,7 +530,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + switch (recvmsg->type) { + case SMB_DIRECT_MSG_NEGOTIATE_REQ: + if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) { +- put_empty_recvmsg(t, recvmsg); ++ put_recvmsg(t, recvmsg); + return; + } + t->negotiation_requested = true; +@@ -579,7 +547,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + + if (wc->byte_len < + offsetof(struct smb_direct_data_transfer, padding)) { +- put_empty_recvmsg(t, recvmsg); ++ put_recvmsg(t, recvmsg); + return; + } + +@@ -587,7 +555,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + if (data_length) { + if (wc->byte_len < sizeof(struct smb_direct_data_transfer) + + (u64)data_length) { +- put_empty_recvmsg(t, recvmsg); ++ put_recvmsg(t, recvmsg); + return; + } + +@@ -607,7 +575,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) + avail_recvmsg_count = t->count_avail_recvmsg; + spin_unlock(&t->receive_credit_lock); + } else { +- put_empty_recvmsg(t, recvmsg); ++ put_recvmsg(t, recvmsg); + + spin_lock(&t->receive_credit_lock); + receive_credits = --(t->recv_credits); +@@ -805,7 +773,6 @@ static void smb_direct_post_recv_credits(struct work_struct *work) + struct smb_direct_recvmsg *recvmsg; + int receive_credits, credits = 0; + int ret; +- int use_free = 1; + + spin_lock(&t->receive_credit_lock); + receive_credits = t->recv_credits; +@@ -813,18 +780,9 @@ static void smb_direct_post_recv_credits(struct work_struct *work) + + if (receive_credits < t->recv_credit_target) { + while (true) { +- if (use_free) +- recvmsg = get_free_recvmsg(t); +- else +- recvmsg = get_empty_recvmsg(t); +- if (!recvmsg) { +- if (use_free) { +- use_free = 0; +- continue; +- } else { +- break; +- } +- } ++ recvmsg = get_free_recvmsg(t); ++ if (!recvmsg) ++ break; + + recvmsg->type = SMB_DIRECT_MSG_DATA_TRANSFER; + recvmsg->first_segment = false; +@@ -1800,8 +1758,6 @@ static void smb_direct_destroy_pools(struct smb_direct_transport *t) + + while ((recvmsg = get_free_recvmsg(t))) + mempool_free(recvmsg, t->recvmsg_mempool); +- while ((recvmsg = get_empty_recvmsg(t))) +- mempool_free(recvmsg, t->recvmsg_mempool); + + mempool_destroy(t->recvmsg_mempool); + t->recvmsg_mempool = NULL; +-- +2.39.5 + diff --git a/queue-5.15/xarray-add-calls-to-might_alloc.patch b/queue-5.15/xarray-add-calls-to-might_alloc.patch new file mode 100644 index 0000000000..380fead7db --- /dev/null +++ b/queue-5.15/xarray-add-calls-to-might_alloc.patch @@ -0,0 +1,159 @@ +From 09c1abb89784df1bfe21d65522ab50c4707b3550 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Jul 2022 14:51:00 -0400 +Subject: XArray: Add calls to might_alloc() + +From: Matthew Wilcox (Oracle) + +[ Upstream commit 1dd685c414a7b9fdb3d23aca3aedae84f0b998ae ] + +Catch bogus GFP flags deterministically, instead of occasionally +when we actually have to allocate memory. + +Reported-by: Nikolay Borisov +Signed-off-by: Matthew Wilcox (Oracle) +Stable-dep-of: 99765233ab42 ("NFS: Fixup allocation flags for nfsiod's __GFP_NORETRY") +Signed-off-by: Sasha Levin +--- + include/linux/xarray.h | 15 +++++++++++++++ + tools/include/linux/sched/mm.h | 2 ++ + 2 files changed, 17 insertions(+) + +diff --git a/include/linux/xarray.h b/include/linux/xarray.h +index a91e3d90df8a..549f222a2a6f 100644 +--- a/include/linux/xarray.h ++++ b/include/linux/xarray.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -585,6 +586,7 @@ static inline void *xa_store_bh(struct xarray *xa, unsigned long index, + { + void *curr; + ++ might_alloc(gfp); + xa_lock_bh(xa); + curr = __xa_store(xa, index, entry, gfp); + xa_unlock_bh(xa); +@@ -611,6 +613,7 @@ static inline void *xa_store_irq(struct xarray *xa, unsigned long index, + { + void *curr; + ++ might_alloc(gfp); + xa_lock_irq(xa); + curr = __xa_store(xa, index, entry, gfp); + xa_unlock_irq(xa); +@@ -686,6 +689,7 @@ static inline void *xa_cmpxchg(struct xarray *xa, unsigned long index, + { + void *curr; + ++ might_alloc(gfp); + xa_lock(xa); + curr = __xa_cmpxchg(xa, index, old, entry, gfp); + xa_unlock(xa); +@@ -713,6 +717,7 @@ static inline void *xa_cmpxchg_bh(struct xarray *xa, unsigned long index, + { + void *curr; + ++ might_alloc(gfp); + xa_lock_bh(xa); + curr = __xa_cmpxchg(xa, index, old, entry, gfp); + xa_unlock_bh(xa); +@@ -740,6 +745,7 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index, + { + void *curr; + ++ might_alloc(gfp); + xa_lock_irq(xa); + curr = __xa_cmpxchg(xa, index, old, entry, gfp); + xa_unlock_irq(xa); +@@ -769,6 +775,7 @@ static inline int __must_check xa_insert(struct xarray *xa, + { + int err; + ++ might_alloc(gfp); + xa_lock(xa); + err = __xa_insert(xa, index, entry, gfp); + xa_unlock(xa); +@@ -798,6 +805,7 @@ static inline int __must_check xa_insert_bh(struct xarray *xa, + { + int err; + ++ might_alloc(gfp); + xa_lock_bh(xa); + err = __xa_insert(xa, index, entry, gfp); + xa_unlock_bh(xa); +@@ -827,6 +835,7 @@ static inline int __must_check xa_insert_irq(struct xarray *xa, + { + int err; + ++ might_alloc(gfp); + xa_lock_irq(xa); + err = __xa_insert(xa, index, entry, gfp); + xa_unlock_irq(xa); +@@ -856,6 +865,7 @@ static inline __must_check int xa_alloc(struct xarray *xa, u32 *id, + { + int err; + ++ might_alloc(gfp); + xa_lock(xa); + err = __xa_alloc(xa, id, entry, limit, gfp); + xa_unlock(xa); +@@ -885,6 +895,7 @@ static inline int __must_check xa_alloc_bh(struct xarray *xa, u32 *id, + { + int err; + ++ might_alloc(gfp); + xa_lock_bh(xa); + err = __xa_alloc(xa, id, entry, limit, gfp); + xa_unlock_bh(xa); +@@ -914,6 +925,7 @@ static inline int __must_check xa_alloc_irq(struct xarray *xa, u32 *id, + { + int err; + ++ might_alloc(gfp); + xa_lock_irq(xa); + err = __xa_alloc(xa, id, entry, limit, gfp); + xa_unlock_irq(xa); +@@ -947,6 +959,7 @@ static inline int xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, + { + int err; + ++ might_alloc(gfp); + xa_lock(xa); + err = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp); + xa_unlock(xa); +@@ -980,6 +993,7 @@ static inline int xa_alloc_cyclic_bh(struct xarray *xa, u32 *id, void *entry, + { + int err; + ++ might_alloc(gfp); + xa_lock_bh(xa); + err = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp); + xa_unlock_bh(xa); +@@ -1013,6 +1027,7 @@ static inline int xa_alloc_cyclic_irq(struct xarray *xa, u32 *id, void *entry, + { + int err; + ++ might_alloc(gfp); + xa_lock_irq(xa); + err = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp); + xa_unlock_irq(xa); +diff --git a/tools/include/linux/sched/mm.h b/tools/include/linux/sched/mm.h +index c8d9f19c1f35..967294b8edcf 100644 +--- a/tools/include/linux/sched/mm.h ++++ b/tools/include/linux/sched/mm.h +@@ -1,4 +1,6 @@ + #ifndef _TOOLS_PERF_LINUX_SCHED_MM_H + #define _TOOLS_PERF_LINUX_SCHED_MM_H + ++#define might_alloc(gfp) do { } while (0) ++ + #endif /* _TOOLS_PERF_LINUX_SCHED_MM_H */ +-- +2.39.5 + -- 2.47.3