]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Mon, 11 Aug 2025 04:39:20 +0000 (00:39 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 11 Aug 2025 04:39:20 +0000 (00:39 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
21 files changed:
queue-5.15/alsa-hda-ca0132-fix-missing-error-handling-in-ca0132.patch [new file with mode: 0644]
queue-5.15/benet-fix-bug-when-creating-vfs.patch [new file with mode: 0644]
queue-5.15/ipv6-reject-malicious-packets-in-ipv6_gso_segment.patch [new file with mode: 0644]
queue-5.15/net-drop-ufo-packets-in-udp_rcv_segment.patch [new file with mode: 0644]
queue-5.15/net-mlx5-correctly-set-gso_segs-when-lro-is-used.patch [new file with mode: 0644]
queue-5.15/net-mlx5e-add-handle-shampo-cqe-support.patch [new file with mode: 0644]
queue-5.15/netpoll-prevent-hanging-napi-when-netcons-gets-enabl.patch [new file with mode: 0644]
queue-5.15/nfs-fix-filehandle-bounds-checking-in-nfs_fh_to_dent.patch [new file with mode: 0644]
queue-5.15/nfs-fixup-allocation-flags-for-nfsiod-s-__gfp_noretr.patch [new file with mode: 0644]
queue-5.15/nfsv4.2-another-fix-for-listxattr.patch [new file with mode: 0644]
queue-5.15/phy-mscc-fix-parsing-of-unicast-frames.patch [new file with mode: 0644]
queue-5.15/pnfs-flexfiles-don-t-attempt-pnfs-on-fatal-ds-errors.patch [new file with mode: 0644]
queue-5.15/pptp-ensure-minimal-skb-length-in-pptp_xmit.patch [new file with mode: 0644]
queue-5.15/pptp-fix-pptp_xmit-error-path.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/smb-client-let-recv_done-cleanup-before-notifying-th.patch [new file with mode: 0644]
queue-5.15/smb-server-let-recv_done-avoid-touching-data_transfe.patch [new file with mode: 0644]
queue-5.15/smb-server-let-recv_done-consistently-call-put_recvm.patch [new file with mode: 0644]
queue-5.15/smb-server-make-sure-we-call-ib_dma_unmap_single-onl.patch [new file with mode: 0644]
queue-5.15/smb-server-remove-separate-empty_recvmsg_queue.patch [new file with mode: 0644]
queue-5.15/xarray-add-calls-to-might_alloc.patch [new file with mode: 0644]

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 (file)
index 0000000..ab930a8
--- /dev/null
@@ -0,0 +1,47 @@
+From 932c6523c597abbbb1c1ecdf93899771d1f07327 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <tiwai@suse.de>
+
+[ 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 <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d44926d
--- /dev/null
@@ -0,0 +1,61 @@
+From e43bffc1f98a33b287909c33ad2f2e4f81a8cee9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Aug 2025 12:13:37 +0200
+Subject: benet: fix BUG when creating VFs
+
+From: Michal Schmidt <mschmidt@redhat.com>
+
+[ 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:
+  <TASK>
+  __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 <mschmidt@redhat.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20250801101338.72502-1-mschmidt@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1129fc2
--- /dev/null
@@ -0,0 +1,103 @@
+From c53b0a0a5d0f0197ad1effd382f1ec61e6450706 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Jul 2025 13:17:38 +0000
+Subject: ipv6: reject malicious packets in ipv6_gso_segment()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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:
+ <TASK>
+  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 <edumazet@google.com>
+Reviewed-by: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20250730131738.3385939-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..3772354
--- /dev/null
@@ -0,0 +1,122 @@
+From 9348e97d96da420e4b9d376318cdfe822b87461e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Jul 2025 18:14:58 +0800
+Subject: net: drop UFO packets in udp_rcv_segment()
+
+From: Wang Liang <wangliang74@huawei.com>
+
+[ 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:
+   <TASK>
+   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
+   </TASK>
+
+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 <willemdebruijn.kernel@gmail.com>
+Signed-off-by: Wang Liang <wangliang74@huawei.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20250730101458.3470788-1-wangliang74@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..3ada681
--- /dev/null
@@ -0,0 +1,59 @@
+From b65bec5b3641bb30d8fe92ae0c81f30922488a6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Jul 2025 11:34:00 -0700
+Subject: net/mlx5: Correctly set gso_segs when LRO is used
+
+From: Christoph Paasch <cpaasch@openai.com>
+
+[ 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 <gal@nvidia.com>
+Closes: https://lore.kernel.org/netdev/6583783f-f0fb-4fb1-a415-feec8155bc69@nvidia.com/
+Signed-off-by: Christoph Paasch <cpaasch@openai.com>
+Reviewed-by: Gal Pressman <gal@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250729-mlx5_gso_segs-v1-1-b48c480c1c12@openai.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..409bbdf
--- /dev/null
@@ -0,0 +1,410 @@
+From 5a2b15eac40c87f48365ca3beba0e2110a6b8a68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2020 15:45:38 +0300
+Subject: net/mlx5e: Add handle SHAMPO cqe support
+
+From: Khalid Manaa <khalidm@nvidia.com>
+
+[ 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 <khalidm@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Stable-dep-of: 77bf1c55b2ac ("net/mlx5: Correctly set gso_segs when LRO is used")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2f3c108
--- /dev/null
@@ -0,0 +1,95 @@
+From 50364824a79c144cadd66da297418e748f70486d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Jul 2025 18:08:46 -0700
+Subject: netpoll: prevent hanging NAPI when netcons gets enabled
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ 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 <pabeni@redhat.com>
+Link: https://lore.kernel.org/c5a93ed1-9abe-4880-a3bb-8d1678018b1d@redhat.com
+Acked-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Link: https://patch.msgid.link/20250726010846.1105875-1-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1b04567
--- /dev/null
@@ -0,0 +1,51 @@
+From 48dfbfa122323c30b1757ebd606f695122cff7e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jul 2025 09:24:58 -0400
+Subject: NFS: Fix filehandle bounds checking in nfs_fh_to_dentry()
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+[ Upstream commit ef93a685e01a281b5e2a25ce4e3428cf9371a205 ]
+
+The function needs to check the minimal filehandle length before it can
+access the embedded filehandle.
+
+Reported-by: zhangjian <zhangjian496@huawei.com>
+Fixes: 20fa19027286 ("nfs: add export operations")
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1a3a76b
--- /dev/null
@@ -0,0 +1,55 @@
+From 1a654646acaf6755670ac52483b661f78bc0f0af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Jul 2025 21:47:43 -0400
+Subject: NFS: Fixup allocation flags for nfsiod's __GFP_NORETRY
+
+From: Benjamin Coddington <bcodding@redhat.com>
+
+[ 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 <trondmy@kernel.org>
+Fixes: 0bae835b63c5 ("NFS: Avoid writeback threads getting stuck in mempool_alloc()")
+Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
+Reviewed-by: Laurence Oberman <loberman@redhat.com>
+Tested-by: Laurence Oberman <loberman@redhat.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Link: https://lore.kernel.org/r/f83ac1155a4bc670f2663959a7a068571e06afd9.1752111622.git.bcodding@redhat.com
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2a7f027
--- /dev/null
@@ -0,0 +1,53 @@
+From ab4bf135f34ecc0e9296527f1d97e63ce4eb64ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Jul 2025 16:56:41 -0400
+Subject: NFSv4.2: another fix for listxattr
+
+From: Olga Kornievskaia <okorniev@redhat.com>
+
+[ 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 <okorniev@redhat.com>
+Link: https://lore.kernel.org/r/20250722205641.79394-1-okorniev@redhat.com
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..13f0ed1
--- /dev/null
@@ -0,0 +1,53 @@
+From cbfd55cd49ddff99337d47772b3a34e87054f68c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Jul 2025 16:03:07 +0200
+Subject: phy: mscc: Fix parsing of unicast frames
+
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+
+[ 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 <horatiu.vultur@microchip.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250726140307.3039694-1-horatiu.vultur@microchip.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..26fe845
--- /dev/null
@@ -0,0 +1,176 @@
+From a84cf8c10a084b2b595a990f59a29a10649897c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Jun 2025 09:17:51 +0200
+Subject: pNFS/flexfiles: don't attempt pnfs on fatal DS errors
+
+From: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
+
+[ 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 <tigran.mkrtchyan@desy.de>
+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 <trond.myklebust@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..df44e95
--- /dev/null
@@ -0,0 +1,92 @@
+From 5d04210c5a1cb6811401193cd56ce89b037cb70f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Jul 2025 08:02:07 +0000
+Subject: pptp: ensure minimal skb length in pptp_xmit()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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 <edumazet@google.com>
+Reviewed-by: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
+Link: https://patch.msgid.link/20250729080207.1863408-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b6bdc48
--- /dev/null
@@ -0,0 +1,84 @@
+From f0119df1dbbdb8b812235fcf22b6b8968daa7897 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Aug 2025 14:21:46 +0000
+Subject: pptp: fix pptp_xmit() error path
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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:
+ <TASK>
+ 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 <edumazet@google.com>
+Link: https://patch.msgid.link/20250807142146.2877060-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
index 2db3d1d5ffd654cdaa75c0e7390e79948fa8c618..878713db0ddb80ac624dd97150d6edf6318f1d44 100644 (file)
@@ -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 (file)
index 0000000..56863f8
--- /dev/null
@@ -0,0 +1,79 @@
+From 490d7970baa5ebe456c77d9ded7fc291b84b36d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Aug 2025 14:10:15 +0200
+Subject: smb: client: let recv_done() cleanup before notifying the callers.
+
+From: Stefan Metzmacher <metze@samba.org>
+
+[ 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 <smfrench@gmail.com>
+Cc: Tom Talpey <tom@talpey.com>
+Cc: Long Li <longli@microsoft.com>
+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 <metze@samba.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2e87575
--- /dev/null
@@ -0,0 +1,67 @@
+From b16a9ab179b099ef765b5a149bdf003b253cddec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <metze@samba.org>
+
+[ 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 <linkinjeon@kernel.org>
+Cc: Steve French <smfrench@gmail.com>
+Cc: Tom Talpey <tom@talpey.com>
+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 <metze@samba.org>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..7ecd029
--- /dev/null
@@ -0,0 +1,105 @@
+From ed6fd10a44ecb6cd8e8e3db63da023606dcd2bad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <metze@samba.org>
+
+[ 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 <linkinjeon@kernel.org>
+Cc: Steve French <smfrench@gmail.com>
+Cc: Tom Talpey <tom@talpey.com>
+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 <metze@samba.org>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b8622f1
--- /dev/null
@@ -0,0 +1,68 @@
+From 5e2b9de3e04488516620da2f9079123d62bddcdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <metze@samba.org>
+
+[ 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 <linkinjeon@kernel.org>
+Cc: Steve French <smfrench@gmail.com>
+Cc: Tom Talpey <tom@talpey.com>
+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 <metze@samba.org>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..85ba59f
--- /dev/null
@@ -0,0 +1,169 @@
+From 5c6cdbaad503b024a57f5c2e4ea2a26af71db74c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Aug 2025 14:15:50 +0200
+Subject: smb: server: remove separate empty_recvmsg_queue
+
+From: Stefan Metzmacher <metze@samba.org>
+
+[ 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 <smfrench@gmail.com>
+Cc: Tom Talpey <tom@talpey.com>
+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 <metze@samba.org>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..380fead
--- /dev/null
@@ -0,0 +1,159 @@
+From 09c1abb89784df1bfe21d65522ab50c4707b3550 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Jul 2022 14:51:00 -0400
+Subject: XArray: Add calls to might_alloc()
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit 1dd685c414a7b9fdb3d23aca3aedae84f0b998ae ]
+
+Catch bogus GFP flags deterministically, instead of occasionally
+when we actually have to allocate memory.
+
+Reported-by: Nikolay Borisov <nborisov@suse.com>
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Stable-dep-of: 99765233ab42 ("NFS: Fixup allocation flags for nfsiod's __GFP_NORETRY")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/kconfig.h>
+ #include <linux/kernel.h>
+ #include <linux/rcupdate.h>
++#include <linux/sched/mm.h>
+ #include <linux/spinlock.h>
+ #include <linux/types.h>
+@@ -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
+