]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Apr 2026 12:31:02 +0000 (14:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Apr 2026 12:31:02 +0000 (14:31 +0200)
added patches:
alsa-caiaq-take-a-reference-on-the-usb-device-in-create_card.patch
alsa-hda-realtek-add-quirk-for-legion-s7-15imh.patch
alsa-usb-audio-apply-quirk-for-moondrop-ju-jiu.patch
crypto-ccp-don-t-attempt-to-copy-csr-to-userspace-if-psp-command-failed.patch
crypto-ccp-don-t-attempt-to-copy-id-to-userspace-if-psp-command-failed.patch
crypto-ccp-don-t-attempt-to-copy-pdh-cert-to-userspace-if-psp-command-failed.patch
f2fs-fix-to-avoid-memory-leak-in-f2fs_rename.patch
f2fs-fix-to-avoid-uninit-value-access-in-f2fs_sanity_check_node_footer.patch
f2fs-fix-to-do-sanity-check-on-dcc-discard_cmd_cnt-conditionally.patch
f2fs-fix-uaf-caused-by-decrementing-sbi-nr_pages-in-f2fs_write_end_io.patch
f2fs-fix-use-after-free-of-sbi-in-f2fs_compress_write_end_io.patch
fs-ntfs3-validate-rec-used-in-journal-replay-file-record-check.patch
fuse-abort-on-fatal-signal-during-sync-init.patch
fuse-check-for-large-folio-with-splice_f_move.patch
fuse-fuse_dev_ioctl_clone-should-wait-for-device-file-to-be-initialized.patch
fuse-quiet-down-complaints-in-fuse_conn_limit_write.patch
fuse-reject-oversized-dirents-in-page-cache.patch
ksmbd-fix-out-of-bounds-write-in-smb2_get_ea-ea-alignment.patch
ksmbd-require-minimum-ace-size-in-smb_check_perm_dacl.patch
ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch
ksmbd-use-check_add_overflow-to-prevent-u16-dacl-size-overflow.patch
ksmbd-validate-num_aces-and-harden-ace-walk-in-smb_inherit_dacl.patch
ksmbd-validate-response-sizes-in-ipc_validate_msg.patch
net-packet-fix-toctou-race-on-mmap-d-vnet_hdr-in-tpacket_snd.patch
rxrpc-fix-missing-validation-of-ticket-length-in-non-xdr-key-preparsing.patch
smb-client-fix-oob-read-in-smb2_ioctl_query_info-query_info-path.patch
smb-client-require-a-full-nfs-mode-sid-before-reading-mode-bits.patch
smb-server-fix-active_num_conn-leak-on-transport-allocation-failure.patch
smb-server-fix-max_connections-off-by-one-in-tcp-accept-path.patch
writeback-fix-use-after-free-in-inode_switch_wbs_work_fn.patch

31 files changed:
queue-6.18/alsa-caiaq-take-a-reference-on-the-usb-device-in-create_card.patch [new file with mode: 0644]
queue-6.18/alsa-hda-realtek-add-quirk-for-legion-s7-15imh.patch [new file with mode: 0644]
queue-6.18/alsa-usb-audio-apply-quirk-for-moondrop-ju-jiu.patch [new file with mode: 0644]
queue-6.18/crypto-ccp-don-t-attempt-to-copy-csr-to-userspace-if-psp-command-failed.patch [new file with mode: 0644]
queue-6.18/crypto-ccp-don-t-attempt-to-copy-id-to-userspace-if-psp-command-failed.patch [new file with mode: 0644]
queue-6.18/crypto-ccp-don-t-attempt-to-copy-pdh-cert-to-userspace-if-psp-command-failed.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-to-avoid-memory-leak-in-f2fs_rename.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-to-avoid-uninit-value-access-in-f2fs_sanity_check_node_footer.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-to-do-sanity-check-on-dcc-discard_cmd_cnt-conditionally.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-uaf-caused-by-decrementing-sbi-nr_pages-in-f2fs_write_end_io.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-use-after-free-of-sbi-in-f2fs_compress_write_end_io.patch [new file with mode: 0644]
queue-6.18/fs-ntfs3-validate-rec-used-in-journal-replay-file-record-check.patch [new file with mode: 0644]
queue-6.18/fuse-abort-on-fatal-signal-during-sync-init.patch [new file with mode: 0644]
queue-6.18/fuse-check-for-large-folio-with-splice_f_move.patch [new file with mode: 0644]
queue-6.18/fuse-fuse_dev_ioctl_clone-should-wait-for-device-file-to-be-initialized.patch [new file with mode: 0644]
queue-6.18/fuse-quiet-down-complaints-in-fuse_conn_limit_write.patch [new file with mode: 0644]
queue-6.18/fuse-reject-oversized-dirents-in-page-cache.patch [new file with mode: 0644]
queue-6.18/ksmbd-fix-out-of-bounds-write-in-smb2_get_ea-ea-alignment.patch [new file with mode: 0644]
queue-6.18/ksmbd-require-minimum-ace-size-in-smb_check_perm_dacl.patch [new file with mode: 0644]
queue-6.18/ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch [new file with mode: 0644]
queue-6.18/ksmbd-use-check_add_overflow-to-prevent-u16-dacl-size-overflow.patch [new file with mode: 0644]
queue-6.18/ksmbd-validate-num_aces-and-harden-ace-walk-in-smb_inherit_dacl.patch [new file with mode: 0644]
queue-6.18/ksmbd-validate-response-sizes-in-ipc_validate_msg.patch [new file with mode: 0644]
queue-6.18/net-packet-fix-toctou-race-on-mmap-d-vnet_hdr-in-tpacket_snd.patch [new file with mode: 0644]
queue-6.18/rxrpc-fix-missing-validation-of-ticket-length-in-non-xdr-key-preparsing.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/smb-client-fix-oob-read-in-smb2_ioctl_query_info-query_info-path.patch [new file with mode: 0644]
queue-6.18/smb-client-require-a-full-nfs-mode-sid-before-reading-mode-bits.patch [new file with mode: 0644]
queue-6.18/smb-server-fix-active_num_conn-leak-on-transport-allocation-failure.patch [new file with mode: 0644]
queue-6.18/smb-server-fix-max_connections-off-by-one-in-tcp-accept-path.patch [new file with mode: 0644]
queue-6.18/writeback-fix-use-after-free-in-inode_switch_wbs_work_fn.patch [new file with mode: 0644]

diff --git a/queue-6.18/alsa-caiaq-take-a-reference-on-the-usb-device-in-create_card.patch b/queue-6.18/alsa-caiaq-take-a-reference-on-the-usb-device-in-create_card.patch
new file mode 100644 (file)
index 0000000..7c24550
--- /dev/null
@@ -0,0 +1,57 @@
+From 80bb50e2d459213cccff3111d5ef98ed4238c0d5 Mon Sep 17 00:00:00 2001
+From: Berk Cem Goksel <berkcgoksel@gmail.com>
+Date: Mon, 13 Apr 2026 06:49:41 +0300
+Subject: ALSA: caiaq: take a reference on the USB device in create_card()
+
+From: Berk Cem Goksel <berkcgoksel@gmail.com>
+
+commit 80bb50e2d459213cccff3111d5ef98ed4238c0d5 upstream.
+
+The caiaq driver stores a pointer to the parent USB device in
+cdev->chip.dev but never takes a reference on it. The card's
+private_free callback, snd_usb_caiaq_card_free(), can run
+asynchronously via snd_card_free_when_closed() after the USB
+device has already been disconnected and freed, so any access to
+cdev->chip.dev in that path dereferences a freed usb_device.
+
+On top of the refcounting issue, the current card_free implementation
+calls usb_reset_device(cdev->chip.dev). A reset in a free callback
+is inappropriate: the device is going away, the call takes the
+device lock in a teardown context, and the reset races with the
+disconnect path that the callback is already cleaning up after.
+
+Take a reference on the USB device in create_card() with
+usb_get_dev(), drop it with usb_put_dev() in the free callback,
+and remove the usb_reset_device() call.
+
+Fixes: b04dcbb7f7b1 ("ALSA: caiaq: Use snd_card_free_when_closed() at disconnection")
+Cc: stable@vger.kernel.org
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com>
+Link: https://patch.msgid.link/20260413034941.1131465-3-berkcgoksel@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/caiaq/device.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/usb/caiaq/device.c
++++ b/sound/usb/caiaq/device.c
+@@ -384,7 +384,7 @@ static void card_free(struct snd_card *c
+       snd_usb_caiaq_input_free(cdev);
+ #endif
+       snd_usb_caiaq_audio_free(cdev);
+-      usb_reset_device(cdev->chip.dev);
++      usb_put_dev(cdev->chip.dev);
+ }
+ static int create_card(struct usb_device *usb_dev,
+@@ -410,7 +410,7 @@ static int create_card(struct usb_device
+               return err;
+       cdev = caiaqdev(card);
+-      cdev->chip.dev = usb_dev;
++      cdev->chip.dev = usb_get_dev(usb_dev);
+       cdev->chip.card = card;
+       cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
+                                 le16_to_cpu(usb_dev->descriptor.idProduct));
diff --git a/queue-6.18/alsa-hda-realtek-add-quirk-for-legion-s7-15imh.patch b/queue-6.18/alsa-hda-realtek-add-quirk-for-legion-s7-15imh.patch
new file mode 100644 (file)
index 0000000..f86c79b
--- /dev/null
@@ -0,0 +1,30 @@
+From 67f4c61a73e9b17dc9593bf27badc6785ecadd78 Mon Sep 17 00:00:00 2001
+From: Eric Naim <dnaim@cachyos.org>
+Date: Mon, 13 Apr 2026 23:48:17 +0800
+Subject: ALSA: hda/realtek: Add quirk for Legion S7 15IMH
+
+From: Eric Naim <dnaim@cachyos.org>
+
+commit 67f4c61a73e9b17dc9593bf27badc6785ecadd78 upstream.
+
+Fix speaker output on the Lenovo Legion S7 15IMH05.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Eric Naim <dnaim@cachyos.org>
+Link: https://patch.msgid.link/20260413154818.351597-1-dnaim@cachyos.org
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/hda/codecs/realtek/alc269.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/hda/codecs/realtek/alc269.c
++++ b/sound/hda/codecs/realtek/alc269.c
+@@ -7392,6 +7392,7 @@ static const struct hda_quirk alc269_fix
+       SND_PCI_QUIRK(0x17aa, 0x3801, "Lenovo Yoga9 14IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+       HDA_CODEC_QUIRK(0x17aa, 0x3802, "DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
+       SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga Pro 9 14IRP8", ALC287_FIXUP_TAS2781_I2C),
++      SND_PCI_QUIRK(0x17aa, 0x3811, "Legion S7 15IMH05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
+       SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
+       SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
+       SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
diff --git a/queue-6.18/alsa-usb-audio-apply-quirk-for-moondrop-ju-jiu.patch b/queue-6.18/alsa-usb-audio-apply-quirk-for-moondrop-ju-jiu.patch
new file mode 100644 (file)
index 0000000..e4ed00c
--- /dev/null
@@ -0,0 +1,40 @@
+From 4513d3e0bbc0585b86ccf2631902593ff97e88f5 Mon Sep 17 00:00:00 2001
+From: Cryolitia PukNgae <cryolitia.pukngae@linux.dev>
+Date: Thu, 2 Apr 2026 13:36:57 +0800
+Subject: ALSA: usb-audio: apply quirk for MOONDROP JU Jiu
+
+From: Cryolitia PukNgae <cryolitia.pukngae@linux.dev>
+
+commit 4513d3e0bbc0585b86ccf2631902593ff97e88f5 upstream.
+
+It(ID 31b2:0111 JU Jiu) reports a MIN value -12800 for volume control, but
+will mute when setting it less than -10880.
+
+Thanks to my girlfriend Kagura for reporting this issue.
+
+Cc: Kagura <me@mail.kagurach.uk>
+Cc: stable@vger.kernel.org
+Signed-off-by: Cryolitia PukNgae <cryolitia.pukngae@linux.dev>
+Link: https://patch.msgid.link/20260402-syy-v1-1-068d3bc30ddc@linux.dev
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -1204,6 +1204,13 @@ static void volume_control_quirks(struct
+                       cval->min = -11264; /* Mute under it */
+               }
+               break;
++      case USB_ID(0x31b2, 0x0111): /* MOONDROP JU Jiu */
++              if (!strcmp(kctl->id.name, "PCM Playback Volume")) {
++                      usb_audio_info(chip,
++                                     "set volume quirk for MOONDROP JU Jiu\n");
++                      cval->min = -10880; /* Mute under it */
++              }
++              break;
+       }
+ }
diff --git a/queue-6.18/crypto-ccp-don-t-attempt-to-copy-csr-to-userspace-if-psp-command-failed.patch b/queue-6.18/crypto-ccp-don-t-attempt-to-copy-csr-to-userspace-if-psp-command-failed.patch
new file mode 100644 (file)
index 0000000..1761a0b
--- /dev/null
@@ -0,0 +1,84 @@
+From abe4a6d6f606113251868c2c4a06ba904bb41eed Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Fri, 13 Mar 2026 10:43:16 -0700
+Subject: crypto: ccp: Don't attempt to copy CSR to userspace if PSP command failed
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit abe4a6d6f606113251868c2c4a06ba904bb41eed upstream.
+
+When retrieving the PEK CSR, don't attempt to copy the blob to userspace
+if the firmware command failed.  If the failure was due to an invalid
+length, i.e. the userspace buffer+length was too small, copying the number
+of bytes _firmware_ requires will overflow the kernel-allocated buffer and
+leak data to userspace.
+
+  BUG: KASAN: slab-out-of-bounds in instrument_copy_to_user ../include/linux/instrumented.h:129 [inline]
+  BUG: KASAN: slab-out-of-bounds in _inline_copy_to_user ../include/linux/uaccess.h:205 [inline]
+  BUG: KASAN: slab-out-of-bounds in _copy_to_user+0x66/0xa0 ../lib/usercopy.c:26
+  Read of size 2084 at addr ffff898144612e20 by task syz.9.219/21405
+
+  CPU: 14 UID: 0 PID: 21405 Comm: syz.9.219 Tainted: G     U     O        7.0.0-smp-DEV #28 PREEMPTLAZY
+  Tainted: [U]=USER, [O]=OOT_MODULE
+  Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 12.62.0-0 11/19/2025
+  Call Trace:
+   <TASK>
+   dump_stack_lvl+0xc5/0x110 ../lib/dump_stack.c:120
+   print_address_description ../mm/kasan/report.c:378 [inline]
+   print_report+0xbc/0x260 ../mm/kasan/report.c:482
+   kasan_report+0xa2/0xe0 ../mm/kasan/report.c:595
+   check_region_inline ../mm/kasan/generic.c:-1 [inline]
+   kasan_check_range+0x264/0x2c0 ../mm/kasan/generic.c:200
+   instrument_copy_to_user ../include/linux/instrumented.h:129 [inline]
+   _inline_copy_to_user ../include/linux/uaccess.h:205 [inline]
+   _copy_to_user+0x66/0xa0 ../lib/usercopy.c:26
+   copy_to_user ../include/linux/uaccess.h:236 [inline]
+   sev_ioctl_do_pek_csr+0x31f/0x590 ../drivers/crypto/ccp/sev-dev.c:1872
+   sev_ioctl+0x3a4/0x490 ../drivers/crypto/ccp/sev-dev.c:2562
+   vfs_ioctl ../fs/ioctl.c:51 [inline]
+   __do_sys_ioctl ../fs/ioctl.c:597 [inline]
+   __se_sys_ioctl+0x11d/0x1b0 ../fs/ioctl.c:583
+   do_syscall_x64 ../arch/x86/entry/syscall_64.c:63 [inline]
+   do_syscall_64+0xe0/0x800 ../arch/x86/entry/syscall_64.c:94
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+   </TASK>
+
+WARN if the driver says the command succeeded, but the firmware error code
+says otherwise, as __sev_do_cmd_locked() is expected to return -EIO on any
+firwmware error.
+
+Reported-by: Alexander Potapenko <glider@google.com>
+Reported-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
+Fixes: e799035609e1 ("crypto: ccp: Implement SEV_PEK_CSR ioctl command")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/ccp/sev-dev.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/crypto/ccp/sev-dev.c
++++ b/drivers/crypto/ccp/sev-dev.c
+@@ -1833,7 +1833,10 @@ cmd:
+       ret = __sev_do_cmd_locked(SEV_CMD_PEK_CSR, &data, &argp->error);
+-       /* If we query the CSR length, FW responded with expected data. */
++      /*
++       * Firmware will returns the length of the CSR blob (either the minimum
++       * required length or the actual length written), return it to the user.
++       */
+       input.length = data.len;
+       if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) {
+@@ -1841,6 +1844,9 @@ cmd:
+               goto e_free_blob;
+       }
++      if (ret || WARN_ON_ONCE(argp->error))
++              goto e_free_blob;
++
+       if (blob) {
+               if (copy_to_user(input_address, blob, input.length))
+                       ret = -EFAULT;
diff --git a/queue-6.18/crypto-ccp-don-t-attempt-to-copy-id-to-userspace-if-psp-command-failed.patch b/queue-6.18/crypto-ccp-don-t-attempt-to-copy-id-to-userspace-if-psp-command-failed.patch
new file mode 100644 (file)
index 0000000..9ebd612
--- /dev/null
@@ -0,0 +1,72 @@
+From 4f685dbfa87c546e51d9dc6cab379d20f275e114 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Fri, 13 Mar 2026 10:57:31 -0700
+Subject: crypto: ccp: Don't attempt to copy ID to userspace if PSP command failed
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 4f685dbfa87c546e51d9dc6cab379d20f275e114 upstream.
+
+When retrieving the ID for the CPU, don't attempt to copy the ID blob to
+userspace if the firmware command failed.  If the failure was due to an
+invalid length, i.e. the userspace buffer+length was too small, copying
+the number of bytes _firmware_ requires will overflow the kernel-allocated
+buffer and leak data to userspace.
+
+  BUG: KASAN: slab-out-of-bounds in instrument_copy_to_user ../include/linux/instrumented.h:129 [inline]
+  BUG: KASAN: slab-out-of-bounds in _inline_copy_to_user ../include/linux/uaccess.h:205 [inline]
+  BUG: KASAN: slab-out-of-bounds in _copy_to_user+0x66/0xa0 ../lib/usercopy.c:26
+  Read of size 64 at addr ffff8881867f5960 by task syz.0.906/24388
+
+  CPU: 130 UID: 0 PID: 24388 Comm: syz.0.906 Tainted: G     U     O        7.0.0-smp-DEV #28 PREEMPTLAZY
+  Tainted: [U]=USER, [O]=OOT_MODULE
+  Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 12.62.0-0 11/19/2025
+  Call Trace:
+   <TASK>
+   dump_stack_lvl+0xc5/0x110 ../lib/dump_stack.c:120
+   print_address_description ../mm/kasan/report.c:378 [inline]
+   print_report+0xbc/0x260 ../mm/kasan/report.c:482
+   kasan_report+0xa2/0xe0 ../mm/kasan/report.c:595
+   check_region_inline ../mm/kasan/generic.c:-1 [inline]
+   kasan_check_range+0x264/0x2c0 ../mm/kasan/generic.c:200
+   instrument_copy_to_user ../include/linux/instrumented.h:129 [inline]
+   _inline_copy_to_user ../include/linux/uaccess.h:205 [inline]
+   _copy_to_user+0x66/0xa0 ../lib/usercopy.c:26
+   copy_to_user ../include/linux/uaccess.h:236 [inline]
+   sev_ioctl_do_get_id2+0x361/0x490 ../drivers/crypto/ccp/sev-dev.c:2222
+   sev_ioctl+0x25f/0x490 ../drivers/crypto/ccp/sev-dev.c:2575
+   vfs_ioctl ../fs/ioctl.c:51 [inline]
+   __do_sys_ioctl ../fs/ioctl.c:597 [inline]
+   __se_sys_ioctl+0x11d/0x1b0 ../fs/ioctl.c:583
+   do_syscall_x64 ../arch/x86/entry/syscall_64.c:63 [inline]
+   do_syscall_64+0xe0/0x800 ../arch/x86/entry/syscall_64.c:94
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+   </TASK>
+
+WARN if the driver says the command succeeded, but the firmware error code
+says otherwise, as __sev_do_cmd_locked() is expected to return -EIO on any
+firwmware error.
+
+Reported-by: Alexander Potapenko <glider@google.com>
+Reported-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
+Fixes: d6112ea0cb34 ("crypto: ccp - introduce SEV_GET_ID2 command")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/ccp/sev-dev.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/crypto/ccp/sev-dev.c
++++ b/drivers/crypto/ccp/sev-dev.c
+@@ -2197,6 +2197,9 @@ static int sev_ioctl_do_get_id2(struct s
+               goto e_free;
+       }
++      if (ret || WARN_ON_ONCE(argp->error))
++              goto e_free;
++
+       if (id_blob) {
+               if (copy_to_user(input_address, id_blob, data.len)) {
+                       ret = -EFAULT;
diff --git a/queue-6.18/crypto-ccp-don-t-attempt-to-copy-pdh-cert-to-userspace-if-psp-command-failed.patch b/queue-6.18/crypto-ccp-don-t-attempt-to-copy-pdh-cert-to-userspace-if-psp-command-failed.patch
new file mode 100644 (file)
index 0000000..4b70529
--- /dev/null
@@ -0,0 +1,84 @@
+From e76239fed3cffd6d304d8ca3ce23984fd24f57d3 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Fri, 13 Mar 2026 10:48:53 -0700
+Subject: crypto: ccp: Don't attempt to copy PDH cert to userspace if PSP command failed
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit e76239fed3cffd6d304d8ca3ce23984fd24f57d3 upstream.
+
+When retrieving the PDH cert, don't attempt to copy the blobs to userspace
+if the firmware command failed.  If the failure was due to an invalid
+length, i.e. the userspace buffer+length was too small, copying the number
+of bytes _firmware_ requires will overflow the kernel-allocated buffer and
+leak data to userspace.
+
+  BUG: KASAN: slab-out-of-bounds in instrument_copy_to_user ../include/linux/instrumented.h:129 [inline]
+  BUG: KASAN: slab-out-of-bounds in _inline_copy_to_user ../include/linux/uaccess.h:205 [inline]
+  BUG: KASAN: slab-out-of-bounds in _copy_to_user+0x66/0xa0 ../lib/usercopy.c:26
+  Read of size 2084 at addr ffff8885c4ab8aa0 by task syz.0.186/21033
+
+  CPU: 51 UID: 0 PID: 21033 Comm: syz.0.186 Tainted: G     U     O        7.0.0-smp-DEV #28 PREEMPTLAZY
+  Tainted: [U]=USER, [O]=OOT_MODULE
+  Hardware name: Google, Inc.                                                       Arcadia_IT_80/Arcadia_IT_80, BIOS 34.84.12-0 11/17/2025
+  Call Trace:
+   <TASK>
+   dump_stack_lvl+0xc5/0x110 ../lib/dump_stack.c:120
+   print_address_description ../mm/kasan/report.c:378 [inline]
+   print_report+0xbc/0x260 ../mm/kasan/report.c:482
+   kasan_report+0xa2/0xe0 ../mm/kasan/report.c:595
+   check_region_inline ../mm/kasan/generic.c:-1 [inline]
+   kasan_check_range+0x264/0x2c0 ../mm/kasan/generic.c:200
+   instrument_copy_to_user ../include/linux/instrumented.h:129 [inline]
+   _inline_copy_to_user ../include/linux/uaccess.h:205 [inline]
+   _copy_to_user+0x66/0xa0 ../lib/usercopy.c:26
+   copy_to_user ../include/linux/uaccess.h:236 [inline]
+   sev_ioctl_do_pdh_export+0x3d3/0x7c0 ../drivers/crypto/ccp/sev-dev.c:2347
+   sev_ioctl+0x2a2/0x490 ../drivers/crypto/ccp/sev-dev.c:2568
+   vfs_ioctl ../fs/ioctl.c:51 [inline]
+   __do_sys_ioctl ../fs/ioctl.c:597 [inline]
+   __se_sys_ioctl+0x11d/0x1b0 ../fs/ioctl.c:583
+   do_syscall_x64 ../arch/x86/entry/syscall_64.c:63 [inline]
+   do_syscall_64+0xe0/0x800 ../arch/x86/entry/syscall_64.c:94
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+   </TASK>
+
+WARN if the driver says the command succeeded, but the firmware error code
+says otherwise, as __sev_do_cmd_locked() is expected to return -EIO on any
+firwmware error.
+
+Reported-by: Alexander Potapenko <glider@google.com>
+Reported-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
+Fixes: 76a2b524a4b1 ("crypto: ccp: Implement SEV_PDH_CERT_EXPORT ioctl command")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/ccp/sev-dev.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/crypto/ccp/sev-dev.c
++++ b/drivers/crypto/ccp/sev-dev.c
+@@ -2313,7 +2313,10 @@ cmd:
+       ret = __sev_do_cmd_locked(SEV_CMD_PDH_CERT_EXPORT, &data, &argp->error);
+-      /* If we query the length, FW responded with expected data. */
++      /*
++       * Firmware will return the length of the blobs (either the minimum
++       * required length or the actual length written), return 'em to the user.
++       */
+       input.cert_chain_len = data.cert_chain_len;
+       input.pdh_cert_len = data.pdh_cert_len;
+@@ -2322,6 +2325,9 @@ cmd:
+               goto e_free_cert;
+       }
++      if (ret || WARN_ON_ONCE(argp->error))
++              goto e_free_cert;
++
+       if (pdh_blob) {
+               if (copy_to_user(input_pdh_cert_address,
+                                pdh_blob, input.pdh_cert_len)) {
diff --git a/queue-6.18/f2fs-fix-to-avoid-memory-leak-in-f2fs_rename.patch b/queue-6.18/f2fs-fix-to-avoid-memory-leak-in-f2fs_rename.patch
new file mode 100644 (file)
index 0000000..dc8d83a
--- /dev/null
@@ -0,0 +1,63 @@
+From 3cf11e6f36c170050c12171dd6fd3142711478fc Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao@kernel.org>
+Date: Wed, 4 Mar 2026 16:22:31 +0800
+Subject: f2fs: fix to avoid memory leak in f2fs_rename()
+
+From: Chao Yu <chao@kernel.org>
+
+commit 3cf11e6f36c170050c12171dd6fd3142711478fc upstream.
+
+syzbot reported a f2fs bug as below:
+
+BUG: memory leak
+unreferenced object 0xffff888127f70830 (size 16):
+  comm "syz.0.23", pid 6144, jiffies 4294943712
+  hex dump (first 16 bytes):
+    3c af 57 72 5b e6 8f ad 6e 8e fd 33 42 39 03 ff  <.Wr[...n..3B9..
+  backtrace (crc 925f8a80):
+    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
+    slab_post_alloc_hook mm/slub.c:4520 [inline]
+    slab_alloc_node mm/slub.c:4844 [inline]
+    __do_kmalloc_node mm/slub.c:5237 [inline]
+    __kmalloc_noprof+0x3bd/0x560 mm/slub.c:5250
+    kmalloc_noprof include/linux/slab.h:954 [inline]
+    fscrypt_setup_filename+0x15e/0x3b0 fs/crypto/fname.c:364
+    f2fs_setup_filename+0x52/0xb0 fs/f2fs/dir.c:143
+    f2fs_rename+0x159/0xca0 fs/f2fs/namei.c:961
+    f2fs_rename2+0xd5/0xf20 fs/f2fs/namei.c:1308
+    vfs_rename+0x7ff/0x1250 fs/namei.c:6026
+    filename_renameat2+0x4f4/0x660 fs/namei.c:6144
+    __do_sys_renameat2 fs/namei.c:6173 [inline]
+    __se_sys_renameat2 fs/namei.c:6168 [inline]
+    __x64_sys_renameat2+0x59/0x80 fs/namei.c:6168
+    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+    do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94
+    entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+The root cause is in commit 40b2d55e0452 ("f2fs: fix to create selinux
+label during whiteout initialization"), we added a call to
+f2fs_setup_filename() without a matching call to f2fs_free_filename(),
+fix it.
+
+Fixes: 40b2d55e0452 ("f2fs: fix to create selinux label during whiteout initialization")
+Cc: stable@kernel.org
+Reported-by: syzbot+cf7946ab25b21abc4b66@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-f2fs-devel/69a75fe1.a70a0220.b118c.0014.GAE@google.com
+Suggested-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/namei.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/f2fs/namei.c
++++ b/fs/f2fs/namei.c
+@@ -949,6 +949,7 @@ static int f2fs_rename(struct mnt_idmap
+                       return err;
+               err = f2fs_create_whiteout(idmap, old_dir, &whiteout, &fname);
++              f2fs_free_filename(&fname);
+               if (err)
+                       return err;
+       }
diff --git a/queue-6.18/f2fs-fix-to-avoid-uninit-value-access-in-f2fs_sanity_check_node_footer.patch b/queue-6.18/f2fs-fix-to-avoid-uninit-value-access-in-f2fs_sanity_check_node_footer.patch
new file mode 100644 (file)
index 0000000..415da69
--- /dev/null
@@ -0,0 +1,71 @@
+From 7b9161a605e91d0987e2596a245dc1f21621b23f Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao@kernel.org>
+Date: Mon, 9 Mar 2026 02:22:37 +0000
+Subject: f2fs: fix to avoid uninit-value access in f2fs_sanity_check_node_footer
+
+From: Chao Yu <chao@kernel.org>
+
+commit 7b9161a605e91d0987e2596a245dc1f21621b23f upstream.
+
+syzbot reported a f2fs bug as below:
+
+BUG: KMSAN: uninit-value in f2fs_sanity_check_node_footer+0x374/0xa20 fs/f2fs/node.c:1520
+ f2fs_sanity_check_node_footer+0x374/0xa20 fs/f2fs/node.c:1520
+ f2fs_finish_read_bio+0xe1e/0x1d60 fs/f2fs/data.c:177
+ f2fs_read_end_io+0x6ab/0x2220 fs/f2fs/data.c:-1
+ bio_endio+0x1006/0x1160 block/bio.c:1792
+ submit_bio_noacct+0x533/0x2960 block/blk-core.c:891
+ submit_bio+0x57a/0x620 block/blk-core.c:926
+ blk_crypto_submit_bio include/linux/blk-crypto.h:203 [inline]
+ f2fs_submit_read_bio+0x12c/0x360 fs/f2fs/data.c:557
+ f2fs_submit_page_bio+0xee2/0x1450 fs/f2fs/data.c:775
+ read_node_folio+0x384/0x4b0 fs/f2fs/node.c:1481
+ __get_node_folio+0x5db/0x15d0 fs/f2fs/node.c:1576
+ f2fs_get_inode_folio+0x40/0x50 fs/f2fs/node.c:1623
+ do_read_inode fs/f2fs/inode.c:425 [inline]
+ f2fs_iget+0x1209/0x9380 fs/f2fs/inode.c:596
+ f2fs_fill_super+0x8f5a/0xb2e0 fs/f2fs/super.c:5184
+ get_tree_bdev_flags+0x6e6/0x920 fs/super.c:1694
+ get_tree_bdev+0x38/0x50 fs/super.c:1717
+ f2fs_get_tree+0x35/0x40 fs/f2fs/super.c:5436
+ vfs_get_tree+0xb3/0x5d0 fs/super.c:1754
+ fc_mount fs/namespace.c:1193 [inline]
+ do_new_mount_fc fs/namespace.c:3763 [inline]
+ do_new_mount+0x885/0x1dd0 fs/namespace.c:3839
+ path_mount+0x7a2/0x20b0 fs/namespace.c:4159
+ do_mount fs/namespace.c:4172 [inline]
+ __do_sys_mount fs/namespace.c:4361 [inline]
+ __se_sys_mount+0x704/0x7f0 fs/namespace.c:4338
+ __x64_sys_mount+0xe4/0x150 fs/namespace.c:4338
+ x64_sys_call+0x39f0/0x3ea0 arch/x86/include/generated/asm/syscalls_64.h:166
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x134/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+The root cause is: in f2fs_finish_read_bio(), we may access uninit data
+in folio if we failed to read the data from device into folio, let's add
+a check condition to avoid such issue.
+
+Cc: stable@kernel.org
+Fixes: 50ac3ecd8e05 ("f2fs: fix to do sanity check on node footer in {read,write}_end_io")
+Reported-by: syzbot+9aac813cdc456cdd49f8@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-f2fs-devel/69a9ca26.a70a0220.305d9a.0000.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -152,7 +152,8 @@ static void f2fs_finish_read_bio(struct
+               dec_page_count(F2FS_F_SB(folio), __read_io_type(folio));
+-              if (F2FS_F_SB(folio)->node_inode && is_node_folio(folio) &&
++              if (bio->bi_status == BLK_STS_OK &&
++                      F2FS_F_SB(folio)->node_inode && is_node_folio(folio) &&
+                       f2fs_sanity_check_node_footer(F2FS_F_SB(folio),
+                               folio, folio->index, NODE_TYPE_REGULAR, true))
+                       bio->bi_status = BLK_STS_IOERR;
diff --git a/queue-6.18/f2fs-fix-to-do-sanity-check-on-dcc-discard_cmd_cnt-conditionally.patch b/queue-6.18/f2fs-fix-to-do-sanity-check-on-dcc-discard_cmd_cnt-conditionally.patch
new file mode 100644 (file)
index 0000000..434e808
--- /dev/null
@@ -0,0 +1,153 @@
+From 6af249c996f7d73a3435f9e577956fa259347d18 Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao@kernel.org>
+Date: Wed, 11 Mar 2026 21:35:42 +0800
+Subject: f2fs: fix to do sanity check on dcc->discard_cmd_cnt conditionally
+
+From: Chao Yu <chao@kernel.org>
+
+commit 6af249c996f7d73a3435f9e577956fa259347d18 upstream.
+
+Syzbot reported a f2fs bug as below:
+
+------------[ cut here ]------------
+kernel BUG at fs/f2fs/segment.c:1900!
+Oops: invalid opcode: 0000 [#1] SMP KASAN PTI
+CPU: 1 UID: 0 PID: 6527 Comm: syz.5.110 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
+RIP: 0010:f2fs_issue_discard_timeout+0x59b/0x5a0 fs/f2fs/segment.c:1900
+Code: d9 80 e1 07 80 c1 03 38 c1 0f 8c d6 fe ff ff 48 89 df e8 a8 5e fa fd e9 c9 fe ff ff e8 4e 46 94 fd 90 0f 0b e8 46 46 94 fd 90 <0f> 0b 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3
+RSP: 0018:ffffc9000494f940 EFLAGS: 00010283
+RAX: ffffffff843009ca RBX: 0000000000000001 RCX: 0000000000080000
+RDX: ffffc9001ca78000 RSI: 00000000000029f3 RDI: 00000000000029f4
+RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+R10: dffffc0000000000 R11: ffffed100893a431 R12: 1ffff1100893a430
+R13: 1ffff1100c2b702c R14: dffffc0000000000 R15: ffff8880449d2160
+FS:  00007ffa35fed6c0(0000) GS:ffff88812643d000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f2b68634000 CR3: 0000000039f62000 CR4: 00000000003526f0
+Call Trace:
+ <TASK>
+ __f2fs_remount fs/f2fs/super.c:2960 [inline]
+ f2fs_reconfigure+0x108a/0x1710 fs/f2fs/super.c:5443
+ reconfigure_super+0x227/0x8a0 fs/super.c:1080
+ do_remount fs/namespace.c:3391 [inline]
+ path_mount+0xdc5/0x10e0 fs/namespace.c:4151
+ do_mount fs/namespace.c:4172 [inline]
+ __do_sys_mount fs/namespace.c:4361 [inline]
+ __se_sys_mount+0x31d/0x420 fs/namespace.c:4338
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7ffa37dbda0a
+
+The root cause is there will be race condition in between f2fs_ioc_fitrim()
+and f2fs_remount():
+
+- f2fs_remount                 - f2fs_ioc_fitrim
+ - f2fs_issue_discard_timeout
+  - __issue_discard_cmd
+  - __drop_discard_cmd
+  - __wait_all_discard_cmd
+                                - f2fs_trim_fs
+                                 - f2fs_write_checkpoint
+                                  - f2fs_clear_prefree_segments
+                                   - f2fs_issue_discard
+                                    - __issue_discard_async
+                                     - __queue_discard_cmd
+                                      - __update_discard_tree_range
+                                       - __insert_discard_cmd
+                                        - __create_discard_cmd
+                                        : atomic_inc(&dcc->discard_cmd_cnt);
+  - sanity check on dcc->discard_cmd_cnt (expect discard_cmd_cnt to be zero)
+
+This will only happen when fitrim races w/ remount rw, if we remount to
+readonly filesystem, remount will wait until mnt_pcp.mnt_writers to zero,
+that means fitrim is not in process at that time.
+
+Cc: stable@kernel.org
+Fixes: 2482c4325dfe ("f2fs: detect bug_on in f2fs_wait_discard_bios")
+Reported-by: syzbot+62538b67389ee582837a@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-f2fs-devel/69b07d7c.050a0220.8df7.09a1.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h    |    2 +-
+ fs/f2fs/segment.c |    6 +++---
+ fs/f2fs/super.c   |   11 ++++++++---
+ 3 files changed, 12 insertions(+), 7 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -3930,7 +3930,7 @@ bool f2fs_is_checkpointed_data(struct f2
+ int f2fs_start_discard_thread(struct f2fs_sb_info *sbi);
+ void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi);
+ void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi);
+-bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi);
++bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi, bool need_check);
+ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+                                       struct cp_control *cpc);
+ void f2fs_dirty_to_prefree(struct f2fs_sb_info *sbi);
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -1895,7 +1895,7 @@ void f2fs_stop_discard_thread(struct f2f
+  *
+  * Return true if issued all discard cmd or no discard cmd need issue, otherwise return false.
+  */
+-bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi)
++bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi, bool need_check)
+ {
+       struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+       struct discard_policy dpolicy;
+@@ -1912,7 +1912,7 @@ bool f2fs_issue_discard_timeout(struct f
+       /* just to make sure there is no pending discard commands */
+       __wait_all_discard_cmd(sbi, NULL);
+-      f2fs_bug_on(sbi, atomic_read(&dcc->discard_cmd_cnt));
++      f2fs_bug_on(sbi, need_check && atomic_read(&dcc->discard_cmd_cnt));
+       return !dropped;
+ }
+@@ -2382,7 +2382,7 @@ static void destroy_discard_cmd_control(
+        * Recovery can cache discard commands, so in error path of
+        * fill_super(), it needs to give a chance to handle them.
+        */
+-      f2fs_issue_discard_timeout(sbi);
++      f2fs_issue_discard_timeout(sbi, true);
+       kfree(dcc);
+       SM_I(sbi)->dcc_info = NULL;
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1961,7 +1961,7 @@ static void f2fs_put_super(struct super_
+       }
+       /* be sure to wait for any on-going discard commands */
+-      done = f2fs_issue_discard_timeout(sbi);
++      done = f2fs_issue_discard_timeout(sbi, true);
+       if (f2fs_realtime_discard_enable(sbi) && !sbi->discard_blks && done) {
+               struct cp_control cpc = {
+                       .reason = CP_UMOUNT | CP_TRIMMED,
+@@ -2104,7 +2104,7 @@ static int f2fs_unfreeze(struct super_bl
+        * will recover after removal of snapshot.
+        */
+       if (test_opt(sbi, DISCARD) && !f2fs_hw_support_discard(sbi))
+-              f2fs_issue_discard_timeout(sbi);
++              f2fs_issue_discard_timeout(sbi, true);
+       clear_sbi_flag(F2FS_SB(sb), SBI_IS_FREEZING);
+       return 0;
+@@ -2884,7 +2884,12 @@ static int __f2fs_remount(struct fs_cont
+                       need_stop_discard = true;
+               } else {
+                       f2fs_stop_discard_thread(sbi);
+-                      f2fs_issue_discard_timeout(sbi);
++                      /*
++                       * f2fs_ioc_fitrim() won't race w/ "remount ro"
++                       * so it's safe to check discard_cmd_cnt in
++                       * f2fs_issue_discard_timeout().
++                       */
++                      f2fs_issue_discard_timeout(sbi, flags & SB_RDONLY);
+                       need_restart_discard = true;
+               }
+       }
diff --git a/queue-6.18/f2fs-fix-uaf-caused-by-decrementing-sbi-nr_pages-in-f2fs_write_end_io.patch b/queue-6.18/f2fs-fix-uaf-caused-by-decrementing-sbi-nr_pages-in-f2fs_write_end_io.patch
new file mode 100644 (file)
index 0000000..be6d639
--- /dev/null
@@ -0,0 +1,71 @@
+From 2d9c4a4ed4eef1f82c5b16b037aee8bad819fd53 Mon Sep 17 00:00:00 2001
+From: Yongpeng Yang <yangyongpeng@xiaomi.com>
+Date: Fri, 27 Feb 2026 15:30:52 +0800
+Subject: f2fs: fix UAF caused by decrementing sbi->nr_pages[] in f2fs_write_end_io()
+
+From: Yongpeng Yang <yangyongpeng@xiaomi.com>
+
+commit 2d9c4a4ed4eef1f82c5b16b037aee8bad819fd53 upstream.
+
+The xfstests case "generic/107" and syzbot have both reported a NULL
+pointer dereference.
+
+The concurrent scenario that triggers the panic is as follows:
+
+F2FS_WB_CP_DATA write callback          umount
+                                        - f2fs_write_checkpoint
+                                         - f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA)
+- blk_mq_end_request
+ - bio_endio
+  - f2fs_write_end_io
+   : dec_page_count(sbi, F2FS_WB_CP_DATA)
+   : wake_up(&sbi->cp_wait)
+                                        - kill_f2fs_super
+                                         - kill_block_super
+                                          - f2fs_put_super
+                                           : iput(sbi->node_inode)
+                                           : sbi->node_inode = NULL
+   : f2fs_in_warm_node_list
+    - is_node_folio // sbi->node_inode is NULL and panic
+
+The root cause is that f2fs_put_super() calls iput(sbi->node_inode) and
+sets sbi->node_inode to NULL after sbi->nr_pages[F2FS_WB_CP_DATA] is
+decremented to zero. As a result, f2fs_in_warm_node_list() may
+dereference a NULL node_inode when checking whether a folio belongs to
+the node inode, leading to a panic.
+
+This patch fixes the issue by calling f2fs_in_warm_node_list() before
+decrementing sbi->nr_pages[F2FS_WB_CP_DATA], thus preventing the
+use-after-free condition.
+
+Cc: stable@kernel.org
+Fixes: 50fa53eccf9f ("f2fs: fix to avoid broken of dnode block list")
+Reported-by: syzbot+6e4cb1cac5efc96ea0ca@syzkaller.appspotmail.com
+Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -363,6 +363,8 @@ static void f2fs_write_end_io(struct bio
+                               folio->index, NODE_TYPE_REGULAR, true);
+                       f2fs_bug_on(sbi, folio->index != nid_of_node(folio));
+               }
++              if (f2fs_in_warm_node_list(sbi, folio))
++                      f2fs_del_fsync_node_entry(sbi, folio);
+               dec_page_count(sbi, type);
+@@ -374,8 +376,6 @@ static void f2fs_write_end_io(struct bio
+                               wq_has_sleeper(&sbi->cp_wait))
+                       wake_up(&sbi->cp_wait);
+-              if (f2fs_in_warm_node_list(sbi, folio))
+-                      f2fs_del_fsync_node_entry(sbi, folio);
+               folio_clear_f2fs_gcing(folio);
+               folio_end_writeback(folio);
+       }
diff --git a/queue-6.18/f2fs-fix-use-after-free-of-sbi-in-f2fs_compress_write_end_io.patch b/queue-6.18/f2fs-fix-use-after-free-of-sbi-in-f2fs_compress_write_end_io.patch
new file mode 100644 (file)
index 0000000..a2e8ea2
--- /dev/null
@@ -0,0 +1,78 @@
+From 39d4ee19c1e7d753dd655aebee632271b171f43a Mon Sep 17 00:00:00 2001
+From: George Saad <geoo115@gmail.com>
+Date: Mon, 23 Mar 2026 11:21:23 +0000
+Subject: f2fs: fix use-after-free of sbi in f2fs_compress_write_end_io()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: George Saad <geoo115@gmail.com>
+
+commit 39d4ee19c1e7d753dd655aebee632271b171f43a upstream.
+
+In f2fs_compress_write_end_io(), dec_page_count(sbi, type) can bring
+the F2FS_WB_CP_DATA counter to zero, unblocking
+f2fs_wait_on_all_pages() in f2fs_put_super() on a concurrent unmount
+CPU. The unmount path then proceeds to call
+f2fs_destroy_page_array_cache(sbi), which destroys
+sbi->page_array_slab via kmem_cache_destroy(), and eventually
+kfree(sbi). Meanwhile, the bio completion callback is still executing:
+when it reaches page_array_free(sbi, ...), it dereferences
+sbi->page_array_slab â€” a destroyed slab cache â€” to call
+kmem_cache_free(), causing a use-after-free.
+
+This is the same class of bug as CVE-2026-23234 (which fixed the
+equivalent race in f2fs_write_end_io() in data.c), but in the
+compressed writeback completion path that was not covered by that fix.
+
+Fix this by moving dec_page_count() to after page_array_free(), so
+that all sbi accesses complete before the counter decrement that can
+unblock unmount. For non-last folios (where atomic_dec_return on
+cic->pending_pages is nonzero), dec_page_count is called immediately
+before returning â€” page_array_free is not reached on this path, so
+there is no post-decrement sbi access. For the last folio,
+page_array_free runs while the F2FS_WB_CP_DATA counter is still
+nonzero (this folio has not yet decremented it), keeping sbi alive,
+and dec_page_count runs as the final operation.
+
+Fixes: 4c8ff7095bef ("f2fs: support data compression")
+Cc: stable@vger.kernel.org
+Signed-off-by: George Saad <geoo115@gmail.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/compress.c |   14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/compress.c
++++ b/fs/f2fs/compress.c
+@@ -1489,10 +1489,10 @@ void f2fs_compress_write_end_io(struct b
+       f2fs_compress_free_page(page);
+-      dec_page_count(sbi, type);
+-
+-      if (atomic_dec_return(&cic->pending_pages))
++      if (atomic_dec_return(&cic->pending_pages)) {
++              dec_page_count(sbi, type);
+               return;
++      }
+       for (i = 0; i < cic->nr_rpages; i++) {
+               WARN_ON(!cic->rpages[i]);
+@@ -1502,6 +1502,14 @@ void f2fs_compress_write_end_io(struct b
+       page_array_free(sbi, cic->rpages, cic->nr_rpages);
+       kmem_cache_free(cic_entry_slab, cic);
++
++      /*
++       * Make sure dec_page_count() is the last access to sbi.
++       * Once it drops the F2FS_WB_CP_DATA counter to zero, the
++       * unmount thread can proceed to destroy sbi and
++       * sbi->page_array_slab.
++       */
++      dec_page_count(sbi, type);
+ }
+ static int f2fs_write_raw_pages(struct compress_ctx *cc,
diff --git a/queue-6.18/fs-ntfs3-validate-rec-used-in-journal-replay-file-record-check.patch b/queue-6.18/fs-ntfs3-validate-rec-used-in-journal-replay-file-record-check.patch
new file mode 100644 (file)
index 0000000..f42245b
--- /dev/null
@@ -0,0 +1,78 @@
+From 0ca0485e4b2e837ebb6cbd4f2451aba665a03e4b Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Thu, 9 Apr 2026 16:37:15 +0200
+Subject: fs/ntfs3: validate rec->used in journal-replay file record check
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 0ca0485e4b2e837ebb6cbd4f2451aba665a03e4b upstream.
+
+check_file_record() validates rec->total against the record size but
+never validates rec->used.  The do_action() journal-replay handlers read
+rec->used from disk and use it to compute memmove lengths:
+
+  DeleteAttribute:    memmove(attr, ..., used - asize - roff)
+  CreateAttribute:    memmove(..., attr, used - roff)
+  change_attr_size:   memmove(..., used - PtrOffset(rec, next))
+
+When rec->used is smaller than the offset of a validated attribute, or
+larger than the record size, these subtractions can underflow allowing
+us to copy huge amounts of memory in to a 4kb buffer, generally
+considered a bad idea overall.
+
+This requires a corrupted filesystem, which isn't a threat model the
+kernel really needs to worry about, but checking for such an obvious
+out-of-bounds value is good to keep things robust, especially on journal
+replay
+
+Fix this up by bounding rec->used correctly.
+
+This is much like commit b2bc7c44ed17 ("fs/ntfs3: Fix slab-out-of-bounds
+read in DeleteIndexEntryRoot") which checked different values in this
+same switch statement.
+
+Cc: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal")
+Cc: stable <stable@kernel.org>
+Assisted-by: gregkh_clanker_t1000
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/fslog.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -2789,13 +2789,14 @@ static inline bool check_file_record(con
+       u16 fn = le16_to_cpu(rec->rhdr.fix_num);
+       u16 ao = le16_to_cpu(rec->attr_off);
+       u32 rs = sbi->record_size;
++      u32 used = le32_to_cpu(rec->used);
+       /* Check the file record header for consistency. */
+       if (rec->rhdr.sign != NTFS_FILE_SIGNATURE ||
+           fo > (SECTOR_SIZE - ((rs >> SECTOR_SHIFT) + 1) * sizeof(short)) ||
+           (fn - 1) * SECTOR_SIZE != rs || ao < MFTRECORD_FIXUP_OFFSET_1 ||
+           ao > sbi->record_size - SIZEOF_RESIDENT || !is_rec_inuse(rec) ||
+-          le32_to_cpu(rec->total) != rs) {
++          le32_to_cpu(rec->total) != rs || used > rs || used < ao) {
+               return false;
+       }
+@@ -2807,6 +2808,15 @@ static inline bool check_file_record(con
+               return false;
+       }
++      /*
++       * The do_action() handlers compute memmove lengths as
++       * "rec->used - <offset of validated attr>", which underflows when
++       * rec->used is smaller than the attribute walk reached.  At this
++       * point attr is the ATTR_END marker; rec->used must cover it.
++       */
++      if (used < PtrOffset(rec, attr) + sizeof(attr->type))
++              return false;
++
+       return true;
+ }
diff --git a/queue-6.18/fuse-abort-on-fatal-signal-during-sync-init.patch b/queue-6.18/fuse-abort-on-fatal-signal-during-sync-init.patch
new file mode 100644 (file)
index 0000000..2296ce5
--- /dev/null
@@ -0,0 +1,75 @@
+From 204aa22a686bfee48daca7db620c1e017615f2ff Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Mon, 16 Mar 2026 14:10:00 +0100
+Subject: fuse: abort on fatal signal during sync init
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit 204aa22a686bfee48daca7db620c1e017615f2ff upstream.
+
+When sync init is used and the server exits for some reason (error, crash)
+while processing FUSE_INIT, the filesystem creation will hang.  The reason
+is that while all other threads will exit, the mounting thread (or process)
+will keep the device fd open, which will prevent an abort from happening.
+
+This is a regression from the async mount case, where the mount was done
+first, and the FUSE_INIT processing afterwards, in which case there's no
+such recursive syscall keeping the fd open.
+
+Fixes: dfb84c330794 ("fuse: allow synchronous FUSE_INIT")
+Cc: stable@vger.kernel.org # v6.18
+Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
+Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
+Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dev.c    |    8 +++++++-
+ fs/fuse/fuse_i.h |    1 +
+ fs/fuse/inode.c  |    1 +
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -570,6 +570,11 @@ static void request_wait_answer(struct f
+               if (!err)
+                       return;
++              if (req->args->abort_on_kill) {
++                      fuse_abort_conn(fc);
++                      return;
++              }
++
+               if (test_bit(FR_URING, &req->flags))
+                       removed = fuse_uring_remove_pending_req(req);
+               else
+@@ -676,7 +681,8 @@ ssize_t __fuse_simple_request(struct mnt
+                       fuse_force_creds(req);
+               __set_bit(FR_WAITING, &req->flags);
+-              __set_bit(FR_FORCE, &req->flags);
++              if (!args->abort_on_kill)
++                      __set_bit(FR_FORCE, &req->flags);
+       } else {
+               WARN_ON(args->nocreds);
+               req = fuse_get_req(idmap, fm, false);
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -333,6 +333,7 @@ struct fuse_args {
+       bool is_ext:1;
+       bool is_pinned:1;
+       bool invalidate_vmap:1;
++      bool abort_on_kill:1;
+       struct fuse_in_arg in_args[4];
+       struct fuse_arg out_args[2];
+       void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -1548,6 +1548,7 @@ int fuse_send_init(struct fuse_mount *fm
+       int err;
+       if (fm->fc->sync_init) {
++              ia->args.abort_on_kill = true;
+               err = fuse_simple_request(fm, &ia->args);
+               /* Ignore size of init reply */
+               if (err > 0)
diff --git a/queue-6.18/fuse-check-for-large-folio-with-splice_f_move.patch b/queue-6.18/fuse-check-for-large-folio-with-splice_f_move.patch
new file mode 100644 (file)
index 0000000..8426ed5
--- /dev/null
@@ -0,0 +1,40 @@
+From 59ba47b6be9cd0146ef9a55c6e32e337e11e7625 Mon Sep 17 00:00:00 2001
+From: Bernd Schubert <bschubert@ddn.com>
+Date: Sun, 11 Jan 2026 12:48:07 +0100
+Subject: fuse: Check for large folio with SPLICE_F_MOVE
+
+From: Bernd Schubert <bschubert@ddn.com>
+
+commit 59ba47b6be9cd0146ef9a55c6e32e337e11e7625 upstream.
+
+xfstest generic/074 and generic/075 complain result in kernel
+warning messages / page dumps.
+This is easily reproducible (on 6.19) with
+CONFIG_TRANSPARENT_HUGEPAGE_SHMEM_HUGE_ALWAYS=y
+CONFIG_TRANSPARENT_HUGEPAGE_TMPFS_HUGE_ALWAYS=y
+
+This just adds a test for large folios fuse_try_move_folio
+with the same page copy fallback, but to avoid the warnings
+from fuse_check_folio().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Bernd Schubert <bschubert@ddn.com>
+Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dev.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -1017,6 +1017,9 @@ static int fuse_try_move_folio(struct fu
+       folio_clear_uptodate(newfolio);
+       folio_clear_mappedtodisk(newfolio);
++      if (folio_test_large(newfolio))
++              goto out_fallback_unlock;
++
+       if (fuse_check_folio(newfolio) != 0)
+               goto out_fallback_unlock;
diff --git a/queue-6.18/fuse-fuse_dev_ioctl_clone-should-wait-for-device-file-to-be-initialized.patch b/queue-6.18/fuse-fuse_dev_ioctl_clone-should-wait-for-device-file-to-be-initialized.patch
new file mode 100644 (file)
index 0000000..3ca9391
--- /dev/null
@@ -0,0 +1,60 @@
+From da6fcc6dbddbef80e603d2f0c1554a9f2ac03742 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Thu, 2 Apr 2026 20:19:55 +0200
+Subject: fuse: fuse_dev_ioctl_clone() should wait for device file to be initialized
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit da6fcc6dbddbef80e603d2f0c1554a9f2ac03742 upstream.
+
+Use fuse_get_dev() not __fuse_get_dev() on the old fd, since in the case of
+synchronous INIT the caller will want to wait for the device file to be
+available for cloning, just like I/O wants to wait instead of returning an
+error.
+
+Fixes: dfb84c330794 ("fuse: allow synchronous FUSE_INIT")
+Cc: stable@vger.kernel.org # v6.18
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dev.c |   19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -2599,9 +2599,8 @@ static int fuse_device_clone(struct fuse
+ static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
+ {
+-      int res;
+       int oldfd;
+-      struct fuse_dev *fud = NULL;
++      struct fuse_dev *fud;
+       if (get_user(oldfd, argp))
+               return -EFAULT;
+@@ -2614,17 +2613,15 @@ static long fuse_dev_ioctl_clone(struct
+        * Check against file->f_op because CUSE
+        * uses the same ioctl handler.
+        */
+-      if (fd_file(f)->f_op == file->f_op)
+-              fud = __fuse_get_dev(fd_file(f));
++      if (fd_file(f)->f_op != file->f_op)
++              return -EINVAL;
+-      res = -EINVAL;
+-      if (fud) {
+-              mutex_lock(&fuse_mutex);
+-              res = fuse_device_clone(fud->fc, file);
+-              mutex_unlock(&fuse_mutex);
+-      }
++      fud = fuse_get_dev(fd_file(f));
++      if (IS_ERR(fud))
++              return PTR_ERR(fud);
+-      return res;
++      guard(mutex)(&fuse_mutex);
++      return fuse_device_clone(fud->fc, file);
+ }
+ static long fuse_dev_ioctl_backing_open(struct file *file,
diff --git a/queue-6.18/fuse-quiet-down-complaints-in-fuse_conn_limit_write.patch b/queue-6.18/fuse-quiet-down-complaints-in-fuse_conn_limit_write.patch
new file mode 100644 (file)
index 0000000..cd67b78
--- /dev/null
@@ -0,0 +1,67 @@
+From 129a45f9755a89f573c6a513a6b9e3d234ce89b0 Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Mon, 23 Feb 2026 15:06:50 -0800
+Subject: fuse: quiet down complaints in fuse_conn_limit_write
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit 129a45f9755a89f573c6a513a6b9e3d234ce89b0 upstream.
+
+gcc 15 complains about an uninitialized variable val that is passed by
+reference into fuse_conn_limit_write:
+
+ control.c: In function â€˜fuse_conn_congestion_threshold_write’:
+ include/asm-generic/rwonce.h:55:37: warning: â€˜val’ may be used uninitialized [-Wmaybe-uninitialized]
+    55 |         *(volatile typeof(x) *)&(x) = (val);                            \
+       |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
+ include/asm-generic/rwonce.h:61:9: note: in expansion of macro â€˜__WRITE_ONCE’
+    61 |         __WRITE_ONCE(x, val);                                           \
+       |         ^~~~~~~~~~~~
+ control.c:178:9: note: in expansion of macro â€˜WRITE_ONCE’
+   178 |         WRITE_ONCE(fc->congestion_threshold, val);
+       |         ^~~~~~~~~~
+ control.c:166:18: note: â€˜val’ was declared here
+   166 |         unsigned val;
+       |                  ^~~
+
+Unfortunately there's enough macro spew involved in kstrtoul_from_user
+that I think gcc gives up on its analysis and sprays the above warning.
+AFAICT it's not actually a bug, but we could just zero-initialize the
+variable to enable using -Wmaybe-uninitialized to find real problems.
+
+Previously we would use some weird uninitialized_var annotation to quiet
+down the warnings, so clearly this code has been like this for quite
+some time.
+
+Cc: stable@vger.kernel.org # v5.9
+Fixes: 3f649ab728cda8 ("treewide: Remove uninitialized_var() usage")
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/control.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/fuse/control.c
++++ b/fs/fuse/control.c
+@@ -121,7 +121,7 @@ static ssize_t fuse_conn_max_background_
+                                             const char __user *buf,
+                                             size_t count, loff_t *ppos)
+ {
+-      unsigned val;
++      unsigned int val = 0;
+       ssize_t ret;
+       ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
+@@ -163,7 +163,7 @@ static ssize_t fuse_conn_congestion_thre
+                                                   const char __user *buf,
+                                                   size_t count, loff_t *ppos)
+ {
+-      unsigned val;
++      unsigned int val = 0;
+       struct fuse_conn *fc;
+       ssize_t ret;
diff --git a/queue-6.18/fuse-reject-oversized-dirents-in-page-cache.patch b/queue-6.18/fuse-reject-oversized-dirents-in-page-cache.patch
new file mode 100644 (file)
index 0000000..0999686
--- /dev/null
@@ -0,0 +1,50 @@
+From 51a8de6c50bf947c8f534cd73da4c8f0a13e7bed Mon Sep 17 00:00:00 2001
+From: Samuel Page <sam@bynar.io>
+Date: Mon, 20 Apr 2026 11:01:37 +0200
+Subject: fuse: reject oversized dirents in page cache
+
+From: Samuel Page <sam@bynar.io>
+
+commit 51a8de6c50bf947c8f534cd73da4c8f0a13e7bed upstream.
+
+fuse_add_dirent_to_cache() computes a serialized dirent size from the
+server-controlled namelen field and copies the dirent into a single
+page-cache page. The existing logic only checks whether the dirent fits
+in the remaining space of the current page and advances to a fresh page
+if not. It never checks whether the dirent itself exceeds PAGE_SIZE.
+
+As a result, a malicious FUSE server can return a dirent with
+namelen=4095, producing a serialized record size of 4120 bytes. On 4 KiB
+page systems this causes memcpy() to overflow the cache page by 24 bytes
+into the following kernel page.
+
+Reject dirents that cannot fit in a single page before copying them into
+the readdir cache.
+
+Fixes: 69e34551152a ("fuse: allow caching readdir")
+Cc: stable@vger.kernel.org # v6.16+
+Assisted-by: Bynario AI
+Signed-off-by: Samuel Page <sam@bynar.io>
+Reported-by: Qi Tang <tpluszz77@gmail.com>
+Reported-by: Zijun Hu <nightu@northwestern.edu>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Link: https://patch.msgid.link/20260420090139.662772-1-mszeredi@redhat.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/readdir.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/fuse/readdir.c
++++ b/fs/fuse/readdir.c
+@@ -41,6 +41,10 @@ static void fuse_add_dirent_to_cache(str
+       unsigned int offset;
+       void *addr;
++      /* Dirent doesn't fit in readdir cache page?  Skip caching. */
++      if (reclen > PAGE_SIZE)
++              return;
++
+       spin_lock(&fi->rdc.lock);
+       /*
+        * Is cache already completed?  Or this entry does not go at the end of
diff --git a/queue-6.18/ksmbd-fix-out-of-bounds-write-in-smb2_get_ea-ea-alignment.patch b/queue-6.18/ksmbd-fix-out-of-bounds-write-in-smb2_get_ea-ea-alignment.patch
new file mode 100644 (file)
index 0000000..2669274
--- /dev/null
@@ -0,0 +1,52 @@
+From 30010c952077a1c89ecdd71fc4d574c75a8f5617 Mon Sep 17 00:00:00 2001
+From: Tristan Madani <tristan@talencesecurity.com>
+Date: Fri, 17 Apr 2026 19:33:17 +0000
+Subject: ksmbd: fix out-of-bounds write in smb2_get_ea() EA alignment
+
+From: Tristan Madani <tristan@talencesecurity.com>
+
+commit 30010c952077a1c89ecdd71fc4d574c75a8f5617 upstream.
+
+smb2_get_ea() applies 4-byte alignment padding via memset() after
+writing each EA entry. The bounds check on buf_free_len is performed
+before the value memcpy, but the alignment memset fires unconditionally
+afterward with no check on remaining space.
+
+When the EA value exactly fills the remaining buffer (buf_free_len == 0
+after value subtraction), the alignment memset writes 1-3 NUL bytes
+past the buf_free_len boundary. In compound requests where the response
+buffer is shared across commands, the first command (e.g., READ) can
+consume most of the buffer, leaving a tight remainder for the QUERY_INFO
+EA response. The alignment memset then overwrites past the physical
+kvmalloc allocation into adjacent kernel heap memory.
+
+Add a bounds check before the alignment memset to ensure buf_free_len
+can accommodate the padding bytes.
+
+This is the same bug pattern fixed by commit beef2634f81f ("ksmbd: fix
+potencial OOB in get_file_all_info() for compound requests") and
+commit fda9522ed6af ("ksmbd: fix OOB write in QUERY_INFO for compound
+requests"), both of which added bounds checks before unconditional
+writes in QUERY_INFO response handlers.
+
+Cc: stable@vger.kernel.org
+Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound")
+Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smb2pdu.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -4831,6 +4831,8 @@ static int smb2_get_ea(struct ksmbd_work
+               /* align next xattr entry at 4 byte bundary */
+               alignment_bytes = ((next_offset + 3) & ~3) - next_offset;
+               if (alignment_bytes) {
++                      if (buf_free_len < alignment_bytes)
++                              break;
+                       memset(ptr, '\0', alignment_bytes);
+                       ptr += alignment_bytes;
+                       next_offset += alignment_bytes;
diff --git a/queue-6.18/ksmbd-require-minimum-ace-size-in-smb_check_perm_dacl.patch b/queue-6.18/ksmbd-require-minimum-ace-size-in-smb_check_perm_dacl.patch
new file mode 100644 (file)
index 0000000..55c65b8
--- /dev/null
@@ -0,0 +1,102 @@
+From d07b26f39246a82399661936dd0c853983cfade7 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Tue, 14 Apr 2026 15:15:33 -0400
+Subject: ksmbd: require minimum ACE size in smb_check_perm_dacl()
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit d07b26f39246a82399661936dd0c853983cfade7 upstream.
+
+Both ACE-walk loops in smb_check_perm_dacl() only guard against an
+under-sized remaining buffer, not against an ACE whose declared
+`ace->size` is smaller than the struct it claims to describe:
+
+  if (offsetof(struct smb_ace, access_req) > aces_size)
+      break;
+  ace_size = le16_to_cpu(ace->size);
+  if (ace_size > aces_size)
+      break;
+
+The first check only requires the 4-byte ACE header to be in bounds;
+it does not require access_req (4 bytes at offset 4) to be readable.
+An attacker who has set a crafted DACL on a file they own can declare
+ace->size == 4 with aces_size == 4, pass both checks, and then
+
+  granted |= le32_to_cpu(ace->access_req);               /* upper loop */
+  compare_sids(&sid, &ace->sid);                         /* lower loop */
+
+reads access_req at offset 4 (OOB by up to 4 bytes) and ace->sid at
+offset 8 (OOB by up to CIFS_SID_BASE_SIZE + SID_MAX_SUB_AUTHORITIES
+* 4 bytes).
+
+Tighten both loops to require
+
+  ace_size >= offsetof(struct smb_ace, sid) + CIFS_SID_BASE_SIZE
+
+which is the smallest valid on-wire ACE layout (4-byte header +
+4-byte access_req + 8-byte sid base with zero sub-auths).  Also
+reject ACEs whose sid.num_subauth exceeds SID_MAX_SUB_AUTHORITIES
+before letting compare_sids() dereference sub_auth[] entries.
+
+parse_sec_desc() already enforces an equivalent check (lines 441-448);
+smb_check_perm_dacl() simply grew weaker validation over time.
+
+Reachability: authenticated SMB client with permission to set an ACL
+on a file.  On a subsequent CREATE against that file, the kernel
+walks the stored DACL via smb_check_perm_dacl() and triggers the
+OOB read.  Not pre-auth, and the OOB read is not reflected to the
+attacker, but KASAN reports and kernel state corruption are
+possible.
+
+Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Assisted-by: Codex:gpt-5-4
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smbacl.c |   17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/fs/smb/server/smbacl.c
++++ b/fs/smb/server/smbacl.c
+@@ -1342,10 +1342,13 @@ int smb_check_perm_dacl(struct ksmbd_con
+               ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+               aces_size = acl_size - sizeof(struct smb_acl);
+               for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) {
+-                      if (offsetof(struct smb_ace, access_req) > aces_size)
++                      if (offsetof(struct smb_ace, sid) +
++                          aces_size < CIFS_SID_BASE_SIZE)
+                               break;
+                       ace_size = le16_to_cpu(ace->size);
+-                      if (ace_size > aces_size)
++                      if (ace_size > aces_size ||
++                          ace_size < offsetof(struct smb_ace, sid) +
++                                     CIFS_SID_BASE_SIZE)
+                               break;
+                       aces_size -= ace_size;
+                       granted |= le32_to_cpu(ace->access_req);
+@@ -1363,13 +1366,19 @@ int smb_check_perm_dacl(struct ksmbd_con
+       ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+       aces_size = acl_size - sizeof(struct smb_acl);
+       for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) {
+-              if (offsetof(struct smb_ace, access_req) > aces_size)
++              if (offsetof(struct smb_ace, sid) +
++                  aces_size < CIFS_SID_BASE_SIZE)
+                       break;
+               ace_size = le16_to_cpu(ace->size);
+-              if (ace_size > aces_size)
++              if (ace_size > aces_size ||
++                  ace_size < offsetof(struct smb_ace, sid) +
++                             CIFS_SID_BASE_SIZE)
+                       break;
+               aces_size -= ace_size;
++              if (ace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES)
++                      break;
++
+               if (!compare_sids(&sid, &ace->sid) ||
+                   !compare_sids(&sid_unix_NFS_mode, &ace->sid)) {
+                       found = 1;
diff --git a/queue-6.18/ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch b/queue-6.18/ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch
new file mode 100644 (file)
index 0000000..86f41ca
--- /dev/null
@@ -0,0 +1,66 @@
+From def036ef87f8641c1c525d5ae17438d7a1006491 Mon Sep 17 00:00:00 2001
+From: DaeMyung Kang <charsyam@gmail.com>
+Date: Sun, 19 Apr 2026 02:28:44 +0900
+Subject: ksmbd: reset rcount per connection in ksmbd_conn_wait_idle_sess_id()
+
+From: DaeMyung Kang <charsyam@gmail.com>
+
+commit def036ef87f8641c1c525d5ae17438d7a1006491 upstream.
+
+rcount is intended to be connection-specific: 2 for curr_conn, 1 for
+every other connection sharing the same session.  However, it is
+initialised only once before the hash iteration and is never reset.
+After the loop visits curr_conn, later sibling connections are also
+checked against rcount == 2, so a sibling with req_running == 1 is
+incorrectly treated as idle.  This makes the outcome depend on the
+hash iteration order: whether a given sibling is checked against the
+loose (< 2) or the strict (< 1) threshold is decided by whether it
+happens to be visited before or after curr_conn.
+
+The function's contract is "wait until every connection sharing this
+session is idle" so that destroy_previous_session() can safely tear
+the session down.  The latched rcount violates that contract and
+reopens the teardown race window the wait logic was meant to close:
+destroy_previous_session() may proceed before sibling channels have
+actually quiesced, overlapping session teardown with in-flight work
+on those connections.
+
+Recompute rcount inside the loop so each connection is compared
+against its own threshold regardless of iteration order.
+
+This is a code-inspection fix for an iteration-order-dependent logic
+error; a targeted reproducer would require SMB3 multichannel with
+in-flight work on a sibling channel landing after curr_conn in hash
+order, which is not something that can be triggered reliably.
+
+Fixes: 76e98a158b20 ("ksmbd: fix race condition between destroy_previous_session() and smb2 operations()")
+Cc: stable@vger.kernel.org
+Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/connection.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/fs/smb/server/connection.c
++++ b/fs/smb/server/connection.c
+@@ -180,7 +180,7 @@ int ksmbd_conn_wait_idle_sess_id(struct
+ {
+       struct ksmbd_conn *conn;
+       int rc, retry_count = 0, max_timeout = 120;
+-      int rcount = 1, bkt;
++      int rcount, bkt;
+ retry_idle:
+       if (retry_count >= max_timeout)
+@@ -189,8 +189,7 @@ retry_idle:
+       down_read(&conn_list_lock);
+       hash_for_each(conn_list, bkt, conn, hlist) {
+               if (conn->binding || xa_load(&conn->sessions, sess_id)) {
+-                      if (conn == curr_conn)
+-                              rcount = 2;
++                      rcount = (conn == curr_conn) ? 2 : 1;
+                       if (atomic_read(&conn->req_running) >= rcount) {
+                               rc = wait_event_timeout(conn->req_running_q,
+                                       atomic_read(&conn->req_running) < rcount,
diff --git a/queue-6.18/ksmbd-use-check_add_overflow-to-prevent-u16-dacl-size-overflow.patch b/queue-6.18/ksmbd-use-check_add_overflow-to-prevent-u16-dacl-size-overflow.patch
new file mode 100644 (file)
index 0000000..4cd3d4e
--- /dev/null
@@ -0,0 +1,86 @@
+From 299f962c0b02d048fb45d248b4da493d03f3175d Mon Sep 17 00:00:00 2001
+From: Tristan Madani <tristan@talencesecurity.com>
+Date: Fri, 17 Apr 2026 19:54:57 +0000
+Subject: ksmbd: use check_add_overflow() to prevent u16 DACL size overflow
+
+From: Tristan Madani <tristan@talencesecurity.com>
+
+commit 299f962c0b02d048fb45d248b4da493d03f3175d upstream.
+
+set_posix_acl_entries_dacl() and set_ntacl_dacl() accumulate ACE sizes
+in u16 variables. When a file has many POSIX ACL entries, the
+accumulated size can wrap past 65535, causing the pointer arithmetic
+(char *)pndace + *size to land within already-written ACEs. Subsequent
+writes then overwrite earlier entries, and pndacl->size gets a
+truncated value.
+
+Use check_add_overflow() at each accumulation point to detect the
+wrap before it corrupts the buffer, consistent with existing
+check_mul_overflow() usage elsewhere in smbacl.c.
+
+Cc: stable@vger.kernel.org
+Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
+Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smbacl.c |   16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/fs/smb/server/smbacl.c
++++ b/fs/smb/server/smbacl.c
+@@ -596,6 +596,7 @@ static void set_posix_acl_entries_dacl(s
+       struct smb_sid *sid;
+       struct smb_ace *ntace;
+       int i, j;
++      u16 ace_sz;
+       if (!fattr->cf_acls)
+               goto posix_default_acl;
+@@ -640,8 +641,10 @@ static void set_posix_acl_entries_dacl(s
+                       flags = 0x03;
+               ntace = (struct smb_ace *)((char *)pndace + *size);
+-              *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
++              ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
+                               pace->e_perm, 0777);
++              if (check_add_overflow(*size, ace_sz, size))
++                      break;
+               (*num_aces)++;
+               if (pace->e_tag == ACL_USER)
+                       ntace->access_req |=
+@@ -650,8 +653,10 @@ static void set_posix_acl_entries_dacl(s
+               if (S_ISDIR(fattr->cf_mode) &&
+                   (pace->e_tag == ACL_USER || pace->e_tag == ACL_GROUP)) {
+                       ntace = (struct smb_ace *)((char *)pndace + *size);
+-                      *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
++                      ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
+                                       0x03, pace->e_perm, 0777);
++                      if (check_add_overflow(*size, ace_sz, size))
++                              break;
+                       (*num_aces)++;
+                       if (pace->e_tag == ACL_USER)
+                               ntace->access_req |=
+@@ -691,8 +696,10 @@ posix_default_acl:
+               }
+               ntace = (struct smb_ace *)((char *)pndace + *size);
+-              *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
++              ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
+                               pace->e_perm, 0777);
++              if (check_add_overflow(*size, ace_sz, size))
++                      break;
+               (*num_aces)++;
+               if (pace->e_tag == ACL_USER)
+                       ntace->access_req |=
+@@ -728,7 +735,8 @@ static void set_ntacl_dacl(struct mnt_id
+                               break;
+                       memcpy((char *)pndace + size, ntace, nt_ace_size);
+-                      size += nt_ace_size;
++                      if (check_add_overflow(size, nt_ace_size, &size))
++                              break;
+                       aces_size -= nt_ace_size;
+                       ntace = (struct smb_ace *)((char *)ntace + nt_ace_size);
+                       num_aces++;
diff --git a/queue-6.18/ksmbd-validate-num_aces-and-harden-ace-walk-in-smb_inherit_dacl.patch b/queue-6.18/ksmbd-validate-num_aces-and-harden-ace-walk-in-smb_inherit_dacl.patch
new file mode 100644 (file)
index 0000000..f5b8fa7
--- /dev/null
@@ -0,0 +1,139 @@
+From 3e4e2ea2a781018ed5d75f969e3e5606beb66e48 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Fri, 17 Apr 2026 14:45:57 -0400
+Subject: ksmbd: validate num_aces and harden ACE walk in smb_inherit_dacl()
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 3e4e2ea2a781018ed5d75f969e3e5606beb66e48 upstream.
+
+smb_inherit_dacl() trusts the on-disk num_aces value from the parent
+directory's DACL xattr and uses it to size a heap allocation:
+
+  aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, ...);
+
+num_aces is a u16 read from le16_to_cpu(parent_pdacl->num_aces)
+without checking that it is consistent with the declared pdacl_size.
+An authenticated client whose parent directory's security.NTACL is
+tampered (e.g. via offline xattr corruption or a concurrent path that
+bypasses parse_dacl()) can present num_aces = 65535 with minimal
+actual ACE data.  This causes a ~8 MB allocation (not kzalloc, so
+uninitialized) that the subsequent loop only partially populates, and
+may also overflow the three-way size_t multiply on 32-bit kernels.
+
+Additionally, the ACE walk loop uses the weaker
+offsetof(struct smb_ace, access_req) minimum size check rather than
+the minimum valid on-wire ACE size, and does not reject ACEs whose
+declared size is below the minimum.
+
+Reproduced on UML + KASAN + LOCKDEP against the real ksmbd code path.
+A legitimate mount.cifs client creates a parent directory over SMB
+(ksmbd writes a valid security.NTACL xattr), then the NTACL blob on
+the backing filesystem is rewritten to set num_aces = 0xFFFF while
+keeping the posix_acl_hash bytes intact so ksmbd_vfs_get_sd_xattr()'s
+hash check still passes.  A subsequent SMB2 CREATE of a child under
+that parent drives smb2_open() into smb_inherit_dacl() (share has
+"vfs objects = acl_xattr" set), which fails the page allocator:
+
+  WARNING: mm/page_alloc.c:5226 at __alloc_frozen_pages_noprof+0x46c/0x9c0
+  Workqueue: ksmbd-io handle_ksmbd_work
+   __alloc_frozen_pages_noprof+0x46c/0x9c0
+   ___kmalloc_large_node+0x68/0x130
+   __kmalloc_large_node_noprof+0x24/0x70
+   __kmalloc_noprof+0x4c9/0x690
+   smb_inherit_dacl+0x394/0x2430
+   smb2_open+0x595d/0xabe0
+   handle_ksmbd_work+0x3d3/0x1140
+
+With the patch applied the added guard rejects the tampered value
+with -EINVAL before any large allocation runs, smb2_open() falls back
+to smb2_create_sd_buffer(), and the child is created with a default
+SD.  No warning, no splat.
+
+Fix by:
+
+  1. Validating num_aces against pdacl_size using the same formula
+     applied in parse_dacl().
+
+  2. Replacing the raw kmalloc(sizeof * num_aces * 2) with
+     kmalloc_array(num_aces * 2, sizeof(...)) for overflow-safe
+     allocation.
+
+  3. Tightening the per-ACE loop guard to require the minimum valid
+     ACE size (offsetof(smb_ace, sid) + CIFS_SID_BASE_SIZE) and
+     rejecting under-sized ACEs, matching the hardening in
+     smb_check_perm_dacl() and parse_dacl().
+
+v1 -> v2:
+  - Replace the synthetic test-module splat in the changelog with a
+    real-path UML + KASAN reproduction driven through mount.cifs and
+    SMB2 CREATE; Namjae flagged the kcifs3_test_inherit_dacl_old name
+    in v1 since it does not exist in ksmbd.
+  - Drop the commit-hash citation from the code comment per Namjae's
+    review; keep the parse_dacl() pointer.
+
+Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smbacl.c |   28 +++++++++++++++++++++++-----
+ 1 file changed, 23 insertions(+), 5 deletions(-)
+
+--- a/fs/smb/server/smbacl.c
++++ b/fs/smb/server/smbacl.c
+@@ -1106,8 +1106,24 @@ int smb_inherit_dacl(struct ksmbd_conn *
+               goto free_parent_pntsd;
+       }
+-      aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2,
+-                          KSMBD_DEFAULT_GFP);
++      aces_size = pdacl_size - sizeof(struct smb_acl);
++
++      /*
++       * Validate num_aces against the DACL payload before allocating.
++       * Each ACE must be at least as large as its fixed-size header
++       * (up to the SID base), so num_aces cannot exceed the payload
++       * divided by the minimum ACE size.  This mirrors the existing
++       * check in parse_dacl().
++       */
++      if (num_aces > aces_size / (offsetof(struct smb_ace, sid) +
++                                  offsetof(struct smb_sid, sub_auth) +
++                                  sizeof(__le16))) {
++              rc = -EINVAL;
++              goto free_parent_pntsd;
++      }
++
++      aces_base = kmalloc_array(num_aces * 2, sizeof(struct smb_ace),
++                                KSMBD_DEFAULT_GFP);
+       if (!aces_base) {
+               rc = -ENOMEM;
+               goto free_parent_pntsd;
+@@ -1116,7 +1132,6 @@ int smb_inherit_dacl(struct ksmbd_conn *
+       aces = (struct smb_ace *)aces_base;
+       parent_aces = (struct smb_ace *)((char *)parent_pdacl +
+                       sizeof(struct smb_acl));
+-      aces_size = acl_len - sizeof(struct smb_acl);
+       if (pntsd_type & DACL_AUTO_INHERITED)
+               inherited_flags = INHERITED_ACE;
+@@ -1124,11 +1139,14 @@ int smb_inherit_dacl(struct ksmbd_conn *
+       for (i = 0; i < num_aces; i++) {
+               int pace_size;
+-              if (offsetof(struct smb_ace, access_req) > aces_size)
++              if (aces_size < offsetof(struct smb_ace, sid) +
++                  CIFS_SID_BASE_SIZE)
+                       break;
+               pace_size = le16_to_cpu(parent_aces->size);
+-              if (pace_size > aces_size)
++              if (pace_size > aces_size ||
++                  pace_size < offsetof(struct smb_ace, sid) +
++                              CIFS_SID_BASE_SIZE)
+                       break;
+               aces_size -= pace_size;
diff --git a/queue-6.18/ksmbd-validate-response-sizes-in-ipc_validate_msg.patch b/queue-6.18/ksmbd-validate-response-sizes-in-ipc_validate_msg.patch
new file mode 100644 (file)
index 0000000..eea7523
--- /dev/null
@@ -0,0 +1,122 @@
+From d6a6aa81eac2c9bff66dc6e191179cb69a14426b Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Wed, 15 Apr 2026 07:25:00 -0400
+Subject: ksmbd: validate response sizes in ipc_validate_msg()
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit d6a6aa81eac2c9bff66dc6e191179cb69a14426b upstream.
+
+ipc_validate_msg() computes the expected message size for each
+response type by adding (or multiplying) attacker-controlled fields
+from the daemon response to a fixed struct size in unsigned int
+arithmetic.  Three cases can overflow:
+
+  KSMBD_EVENT_RPC_REQUEST:
+      msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
+  KSMBD_EVENT_SHARE_CONFIG_REQUEST:
+      msg_sz = sizeof(struct ksmbd_share_config_response) +
+               resp->payload_sz;
+  KSMBD_EVENT_LOGIN_REQUEST_EXT:
+      msg_sz = sizeof(struct ksmbd_login_response_ext) +
+               resp->ngroups * sizeof(gid_t);
+
+resp->payload_sz is __u32 and resp->ngroups is __s32.  Each addition
+can wrap in unsigned int; the multiplication by sizeof(gid_t) mixes
+signed and size_t, so a negative ngroups is converted to SIZE_MAX
+before the multiply.  A wrapped value of msg_sz that happens to
+equal entry->msg_sz bypasses the size check on the next line, and
+downstream consumers (smb2pdu.c:6742 memcpy using rpc_resp->payload_sz,
+kmemdup in ksmbd_alloc_user using resp_ext->ngroups) then trust the
+unverified length.
+
+Use check_add_overflow() on the RPC_REQUEST and SHARE_CONFIG_REQUEST
+paths to detect integer overflow without constraining functional
+payload size; userspace ksmbd-tools grows NDR responses in 4096-byte
+chunks for calls like NetShareEnumAll, so a hard transport cap is
+unworkable on the response side.  For LOGIN_REQUEST_EXT, reject
+resp->ngroups outside the signed [0, NGROUPS_MAX] range up front and
+report the error from ipc_validate_msg() so it fires at the IPC
+boundary; with that bound the subsequent multiplication and addition
+stay well below UINT_MAX.  The now-redundant ngroups check and
+pr_err in ksmbd_alloc_user() are removed.
+
+This is the response-side analogue of aab98e2dbd64 ("ksmbd: fix
+integer overflows on 32 bit systems"), which hardened the request
+side.
+
+Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
+Fixes: a77e0e02af1c ("ksmbd: add support for supplementary groups")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Assisted-by: Codex:gpt-5-4
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/mgmt/user_config.c |    6 ------
+ fs/smb/server/transport_ipc.c    |   16 +++++++++++++---
+ 2 files changed, 13 insertions(+), 9 deletions(-)
+
+--- a/fs/smb/server/mgmt/user_config.c
++++ b/fs/smb/server/mgmt/user_config.c
+@@ -56,12 +56,6 @@ struct ksmbd_user *ksmbd_alloc_user(stru
+               goto err_free;
+       if (resp_ext) {
+-              if (resp_ext->ngroups > NGROUPS_MAX) {
+-                      pr_err("ngroups(%u) from login response exceeds max groups(%d)\n",
+-                                      resp_ext->ngroups, NGROUPS_MAX);
+-                      goto err_free;
+-              }
+-
+               user->sgid = kmemdup(resp_ext->____payload,
+                                    resp_ext->ngroups * sizeof(gid_t),
+                                    KSMBD_DEFAULT_GFP);
+--- a/fs/smb/server/transport_ipc.c
++++ b/fs/smb/server/transport_ipc.c
+@@ -13,6 +13,7 @@
+ #include <net/genetlink.h>
+ #include <linux/socket.h>
+ #include <linux/workqueue.h>
++#include <linux/overflow.h>
+ #include "vfs_cache.h"
+ #include "transport_ipc.h"
+@@ -497,7 +498,9 @@ static int ipc_validate_msg(struct ipc_m
+       {
+               struct ksmbd_rpc_command *resp = entry->response;
+-              msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
++              if (check_add_overflow(sizeof(struct ksmbd_rpc_command),
++                                     resp->payload_sz, &msg_sz))
++                      return -EINVAL;
+               break;
+       }
+       case KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST:
+@@ -516,8 +519,9 @@ static int ipc_validate_msg(struct ipc_m
+                       if (resp->payload_sz < resp->veto_list_sz)
+                               return -EINVAL;
+-                      msg_sz = sizeof(struct ksmbd_share_config_response) +
+-                                      resp->payload_sz;
++                      if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
++                                             resp->payload_sz, &msg_sz))
++                              return -EINVAL;
+               }
+               break;
+       }
+@@ -526,6 +530,12 @@ static int ipc_validate_msg(struct ipc_m
+               struct ksmbd_login_response_ext *resp = entry->response;
+               if (resp->ngroups) {
++                      if (resp->ngroups < 0 ||
++                          resp->ngroups > NGROUPS_MAX) {
++                              pr_err("ngroups(%d) from login response exceeds max groups(%d)\n",
++                                     resp->ngroups, NGROUPS_MAX);
++                              return -EINVAL;
++                      }
+                       msg_sz = sizeof(struct ksmbd_login_response_ext) +
+                                       resp->ngroups * sizeof(gid_t);
+               }
diff --git a/queue-6.18/net-packet-fix-toctou-race-on-mmap-d-vnet_hdr-in-tpacket_snd.patch b/queue-6.18/net-packet-fix-toctou-race-on-mmap-d-vnet_hdr-in-tpacket_snd.patch
new file mode 100644 (file)
index 0000000..3f4908f
--- /dev/null
@@ -0,0 +1,89 @@
+From 2c054e17d9d41f1020376806c7f750834ced4dc5 Mon Sep 17 00:00:00 2001
+From: Bingquan Chen <patzilla007@gmail.com>
+Date: Sat, 18 Apr 2026 19:20:06 +0800
+Subject: net/packet: fix TOCTOU race on mmap'd vnet_hdr in tpacket_snd()
+
+From: Bingquan Chen <patzilla007@gmail.com>
+
+commit 2c054e17d9d41f1020376806c7f750834ced4dc5 upstream.
+
+In tpacket_snd(), when PACKET_VNET_HDR is enabled, vnet_hdr points
+directly into the mmap'd TX ring buffer shared with userspace. The
+kernel validates the header via __packet_snd_vnet_parse() but then
+re-reads all fields later in virtio_net_hdr_to_skb(). A concurrent
+userspace thread can modify the vnet_hdr fields between validation
+and use, bypassing all safety checks.
+
+The non-TPACKET path (packet_snd()) already correctly copies vnet_hdr
+to a stack-local variable. All other vnet_hdr consumers in the kernel
+(tun.c, tap.c, virtio_net.c) also use stack copies. The TPACKET TX
+path is the only caller of virtio_net_hdr_to_skb() that reads directly
+from user-controlled shared memory.
+
+Fix this by copying vnet_hdr from the mmap'd ring buffer to a
+stack-local variable before validation and use, consistent with the
+approach used in packet_snd() and all other callers.
+
+Fixes: 1d036d25e560 ("packet: tpacket_snd gso and checksum offload")
+Signed-off-by: Bingquan Chen <patzilla007@gmail.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260418112006.78823-1-patzilla007@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/packet/af_packet.c |   21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -2717,7 +2717,8 @@ static int tpacket_snd(struct packet_soc
+ {
+       struct sk_buff *skb = NULL;
+       struct net_device *dev;
+-      struct virtio_net_hdr *vnet_hdr = NULL;
++      struct virtio_net_hdr vnet_hdr;
++      bool has_vnet_hdr = false;
+       struct sockcm_cookie sockc;
+       __be16 proto;
+       int err, reserve = 0;
+@@ -2818,16 +2819,20 @@ static int tpacket_snd(struct packet_soc
+               hlen = LL_RESERVED_SPACE(dev);
+               tlen = dev->needed_tailroom;
+               if (vnet_hdr_sz) {
+-                      vnet_hdr = data;
+                       data += vnet_hdr_sz;
+                       tp_len -= vnet_hdr_sz;
+-                      if (tp_len < 0 ||
+-                          __packet_snd_vnet_parse(vnet_hdr, tp_len)) {
++                      if (tp_len < 0) {
++                              tp_len = -EINVAL;
++                              goto tpacket_error;
++                      }
++                      memcpy(&vnet_hdr, data - vnet_hdr_sz, sizeof(vnet_hdr));
++                      if (__packet_snd_vnet_parse(&vnet_hdr, tp_len)) {
+                               tp_len = -EINVAL;
+                               goto tpacket_error;
+                       }
+                       copylen = __virtio16_to_cpu(vio_le(),
+-                                                  vnet_hdr->hdr_len);
++                                                  vnet_hdr.hdr_len);
++                      has_vnet_hdr = true;
+               }
+               copylen = max_t(int, copylen, dev->hard_header_len);
+               skb = sock_alloc_send_skb(&po->sk,
+@@ -2864,12 +2869,12 @@ tpacket_error:
+                       }
+               }
+-              if (vnet_hdr_sz) {
+-                      if (virtio_net_hdr_to_skb(skb, vnet_hdr, vio_le())) {
++              if (has_vnet_hdr) {
++                      if (virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le())) {
+                               tp_len = -EINVAL;
+                               goto tpacket_error;
+                       }
+-                      virtio_net_hdr_set_proto(skb, vnet_hdr);
++                      virtio_net_hdr_set_proto(skb, &vnet_hdr);
+               }
+               skb->destructor = tpacket_destruct_skb;
diff --git a/queue-6.18/rxrpc-fix-missing-validation-of-ticket-length-in-non-xdr-key-preparsing.patch b/queue-6.18/rxrpc-fix-missing-validation-of-ticket-length-in-non-xdr-key-preparsing.patch
new file mode 100644 (file)
index 0000000..2e9b0b7
--- /dev/null
@@ -0,0 +1,56 @@
+From ac33733b10b484d666f97688561670afd5861383 Mon Sep 17 00:00:00 2001
+From: Anderson Nascimento <anderson@allelesecurity.com>
+Date: Wed, 22 Apr 2026 17:14:35 +0100
+Subject: rxrpc: Fix missing validation of ticket length in non-XDR key preparsing
+
+From: Anderson Nascimento <anderson@allelesecurity.com>
+
+commit ac33733b10b484d666f97688561670afd5861383 upstream.
+
+In rxrpc_preparse(), there are two paths for parsing key payloads: the
+XDR path (for large payloads) and the non-XDR path (for payloads <= 28
+bytes). While the XDR path (rxrpc_preparse_xdr_rxkad()) correctly
+validates the ticket length against AFSTOKEN_RK_TIX_MAX, the non-XDR
+path fails to do so.
+
+This allows an unprivileged user to provide a very large ticket length.
+When this key is later read via rxrpc_read(), the total
+token size (toksize) calculation results in a value that exceeds
+AFSTOKEN_LENGTH_MAX, triggering a WARN_ON().
+
+[ 2001.302904] WARNING: CPU: 2 PID: 2108 at net/rxrpc/key.c:778 rxrpc_read+0x109/0x5c0 [rxrpc]
+
+Fix this by adding a check in the non-XDR parsing path of rxrpc_preparse()
+to ensure the ticket length does not exceed AFSTOKEN_RK_TIX_MAX,
+bringing it into parity with the XDR parsing logic.
+
+Fixes: 8a7a3eb4ddbe ("KEYS: RxRPC: Use key preparsing")
+Fixes: 84924aac08a4 ("rxrpc: Fix checker warning")
+Reported-by: Anderson Nascimento <anderson@allelesecurity.com>
+Signed-off-by: Anderson Nascimento <anderson@allelesecurity.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+cc: Jeffrey Altman <jaltman@auristor.com>
+cc: Simon Horman <horms@kernel.org>
+cc: linux-afs@lists.infradead.org
+cc: stable@kernel.org
+Link: https://patch.msgid.link/20260422161438.2593376-7-dhowells@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rxrpc/key.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/rxrpc/key.c
++++ b/net/rxrpc/key.c
+@@ -502,6 +502,10 @@ static int rxrpc_preparse(struct key_pre
+       if (v1->security_index != RXRPC_SECURITY_RXKAD)
+               goto error;
++      ret = -EKEYREJECTED;
++      if (v1->ticket_length > AFSTOKEN_RK_TIX_MAX)
++              goto error;
++
+       plen = sizeof(*token->kad) + v1->ticket_length;
+       prep->quotalen += plen + sizeof(*token);
index ed933c5558f523afac3ab78ed2380849c212255a..b88a529ce42f59f5291db598a8f61fc7822de671 100644 (file)
@@ -23,3 +23,33 @@ lib-crypto-tests-introduce-crypto_lib_enable_all_for_kunit.patch
 kunit-configs-enable-all-crypto-library-tests-in-all_tests.config.patch
 lib-crypto-tests-drop-the-default-to-crypto_selftests.patch
 scripts-dtc-remove-unused-dts_version-in-dtc-lexer.l.patch
+fs-ntfs3-validate-rec-used-in-journal-replay-file-record-check.patch
+f2fs-fix-to-do-sanity-check-on-dcc-discard_cmd_cnt-conditionally.patch
+f2fs-fix-uaf-caused-by-decrementing-sbi-nr_pages-in-f2fs_write_end_io.patch
+f2fs-fix-to-avoid-memory-leak-in-f2fs_rename.patch
+f2fs-fix-to-avoid-uninit-value-access-in-f2fs_sanity_check_node_footer.patch
+fuse-reject-oversized-dirents-in-page-cache.patch
+fuse-abort-on-fatal-signal-during-sync-init.patch
+fuse-check-for-large-folio-with-splice_f_move.patch
+fuse-quiet-down-complaints-in-fuse_conn_limit_write.patch
+fuse-fuse_dev_ioctl_clone-should-wait-for-device-file-to-be-initialized.patch
+ksmbd-require-minimum-ace-size-in-smb_check_perm_dacl.patch
+smb-server-fix-active_num_conn-leak-on-transport-allocation-failure.patch
+smb-server-fix-max_connections-off-by-one-in-tcp-accept-path.patch
+smb-client-require-a-full-nfs-mode-sid-before-reading-mode-bits.patch
+smb-client-fix-oob-read-in-smb2_ioctl_query_info-query_info-path.patch
+ksmbd-validate-response-sizes-in-ipc_validate_msg.patch
+ksmbd-validate-num_aces-and-harden-ace-walk-in-smb_inherit_dacl.patch
+ksmbd-fix-out-of-bounds-write-in-smb2_get_ea-ea-alignment.patch
+ksmbd-use-check_add_overflow-to-prevent-u16-dacl-size-overflow.patch
+ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch
+writeback-fix-use-after-free-in-inode_switch_wbs_work_fn.patch
+f2fs-fix-use-after-free-of-sbi-in-f2fs_compress_write_end_io.patch
+alsa-usb-audio-apply-quirk-for-moondrop-ju-jiu.patch
+alsa-hda-realtek-add-quirk-for-legion-s7-15imh.patch
+alsa-caiaq-take-a-reference-on-the-usb-device-in-create_card.patch
+net-packet-fix-toctou-race-on-mmap-d-vnet_hdr-in-tpacket_snd.patch
+crypto-ccp-don-t-attempt-to-copy-csr-to-userspace-if-psp-command-failed.patch
+crypto-ccp-don-t-attempt-to-copy-pdh-cert-to-userspace-if-psp-command-failed.patch
+crypto-ccp-don-t-attempt-to-copy-id-to-userspace-if-psp-command-failed.patch
+rxrpc-fix-missing-validation-of-ticket-length-in-non-xdr-key-preparsing.patch
diff --git a/queue-6.18/smb-client-fix-oob-read-in-smb2_ioctl_query_info-query_info-path.patch b/queue-6.18/smb-client-fix-oob-read-in-smb2_ioctl_query_info-query_info-path.patch
new file mode 100644 (file)
index 0000000..e7b4df2
--- /dev/null
@@ -0,0 +1,51 @@
+From a58c5af19ff0d6f44f6e9fe31e33a2c92223f77e Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Sun, 19 Apr 2026 19:35:19 -0400
+Subject: smb: client: fix OOB read in smb2_ioctl_query_info QUERY_INFO path
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit a58c5af19ff0d6f44f6e9fe31e33a2c92223f77e upstream.
+
+smb2_ioctl_query_info() has two response-copy branches: PASSTHRU_FSCTL
+and the default QUERY_INFO path.  The QUERY_INFO branch clamps
+qi.input_buffer_length to the server-reported OutputBufferLength and then
+copies qi.input_buffer_length bytes from qi_rsp->Buffer to userspace, but
+it never verifies that the flexible-array payload actually fits within
+rsp_iov[1].iov_len.
+
+A malicious server can return OutputBufferLength larger than the actual
+QUERY_INFO response, causing copy_to_user() to walk past the response
+buffer and expose adjacent kernel heap to userspace.
+
+Guard the QUERY_INFO copy with a bounds check on the actual Buffer
+payload.  Use struct_size(qi_rsp, Buffer, qi.input_buffer_length)
+rather than an open-coded addition so the guard cannot overflow on
+32-bit builds.
+
+Fixes: f5778c398713 ("SMB3: Allow SMB3 FSCTL queries to be sent to server from tools")
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-6
+Assisted-by: Codex:gpt-5-4
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/smb2ops.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -1775,6 +1775,12 @@ replay_again:
+               qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
+               if (le32_to_cpu(qi_rsp->OutputBufferLength) < qi.input_buffer_length)
+                       qi.input_buffer_length = le32_to_cpu(qi_rsp->OutputBufferLength);
++              if (qi.input_buffer_length > 0 &&
++                  struct_size(qi_rsp, Buffer, qi.input_buffer_length) >
++                  rsp_iov[1].iov_len) {
++                      rc = -EFAULT;
++                      goto out;
++              }
+               if (copy_to_user(&pqi->input_buffer_length,
+                                &qi.input_buffer_length,
+                                sizeof(qi.input_buffer_length))) {
diff --git a/queue-6.18/smb-client-require-a-full-nfs-mode-sid-before-reading-mode-bits.patch b/queue-6.18/smb-client-require-a-full-nfs-mode-sid-before-reading-mode-bits.patch
new file mode 100644 (file)
index 0000000..7ebcb16
--- /dev/null
@@ -0,0 +1,42 @@
+From 2757ad3e4b6f9e0fed4c7739594e702abc5cab21 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 20 Apr 2026 09:50:58 -0400
+Subject: smb: client: require a full NFS mode SID before reading mode bits
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 2757ad3e4b6f9e0fed4c7739594e702abc5cab21 upstream.
+
+parse_dacl() treats an ACE SID matching sid_unix_NFS_mode as an NFS
+mode SID and reads sid.sub_auth[2] to recover the mode bits.
+
+That assumes the ACE carries three subauthorities, but compare_sids()
+only compares min(a, b) subauthorities.  A malicious server can return
+an ACE with num_subauth = 2 and sub_auth[] = {88, 3}, which still
+matches sid_unix_NFS_mode and then drives the sub_auth[2] read four
+bytes past the end of the ACE.
+
+Require num_subauth >= 3 before treating the ACE as an NFS mode SID.
+This keeps the fix local to the special-SID mode path without changing
+compare_sids() semantics for the rest of cifsacl.
+
+Fixes: e2f8fbfb8d09 ("cifs: get mode bits from special sid on stat")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/cifsacl.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/smb/client/cifsacl.c
++++ b/fs/smb/client/cifsacl.c
+@@ -831,6 +831,7 @@ static void parse_dacl(struct smb_acl *p
+                       dump_ace(ppace[i], end_of_acl);
+ #endif
+                       if (mode_from_special_sid &&
++                          ppace[i]->sid.num_subauth >= 3 &&
+                           (compare_sids(&(ppace[i]->sid),
+                                         &sid_unix_NFS_mode) == 0)) {
+                               /*
diff --git a/queue-6.18/smb-server-fix-active_num_conn-leak-on-transport-allocation-failure.patch b/queue-6.18/smb-server-fix-active_num_conn-leak-on-transport-allocation-failure.patch
new file mode 100644 (file)
index 0000000..a2a7894
--- /dev/null
@@ -0,0 +1,68 @@
+From 6551300dc452ac16a855a83dbd1e74899542d3b3 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Tue, 14 Apr 2026 18:54:38 -0400
+Subject: smb: server: fix active_num_conn leak on transport allocation failure
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 6551300dc452ac16a855a83dbd1e74899542d3b3 upstream.
+
+Commit 77ffbcac4e56 ("smb: server: fix leak of active_num_conn in
+ksmbd_tcp_new_connection()") addressed the kthread_run() failure
+path.  The earlier alloc_transport() == NULL path in the same
+function has the same leak, is reachable pre-authentication via any
+TCP connect to port 445, and was empirically reproduced on UML
+(ARCH=um, v7.0-rc7): a small number of forced allocation failures
+were sufficient to put ksmbd into a state where every subsequent
+connection attempt was rejected for the remainder of the boot.
+
+ksmbd_kthread_fn() increments active_num_conn before calling
+ksmbd_tcp_new_connection() and discards the return value, so when
+alloc_transport() returns NULL the socket is released and -ENOMEM
+returned without decrementing the counter.  Each such failure
+permanently consumes one slot from the max_connections pool; once
+cumulative failures reach the cap, atomic_inc_return() hits the
+threshold on every subsequent accept and every new connection is
+rejected.  The counter is only reset by module reload.
+
+An unauthenticated remote attacker can drive the server toward the
+memory pressure that makes alloc_transport() fail by holding open
+connections with large RFC1002 lengths up to MAX_STREAM_PROT_LEN
+(0x00FFFFFF); natural transient allocation failures on a loaded
+host produce the same drift more slowly.
+
+Mirror the existing rollback pattern in ksmbd_kthread_fn(): on the
+alloc_transport() failure path, decrement active_num_conn gated on
+server_conf.max_connections.
+
+Repro details: with the patch reverted, forced alloc_transport()
+NULL returns leaked counter slots and subsequent connection
+attempts -- including legitimate connects issued after the
+forced-fail window had closed -- were all rejected with "Limit the
+maximum number of connections".  With this patch applied, the same
+connect sequence produces no rejections and the counter cycles
+cleanly between zero and one on every accept.
+
+Fixes: 0d0d4680db22 ("ksmbd: add max connections parameter")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Assisted-by: Codex:gpt-5-4
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/transport_tcp.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/smb/server/transport_tcp.c
++++ b/fs/smb/server/transport_tcp.c
+@@ -197,6 +197,8 @@ static int ksmbd_tcp_new_connection(stru
+       t = alloc_transport(client_sk);
+       if (!t) {
+               sock_release(client_sk);
++              if (server_conf.max_connections)
++                      atomic_dec(&active_num_conn);
+               return -ENOMEM;
+       }
diff --git a/queue-6.18/smb-server-fix-max_connections-off-by-one-in-tcp-accept-path.patch b/queue-6.18/smb-server-fix-max_connections-off-by-one-in-tcp-accept-path.patch
new file mode 100644 (file)
index 0000000..7239da3
--- /dev/null
@@ -0,0 +1,52 @@
+From ce23158bfe584bd90d1918f279fdf9de57802012 Mon Sep 17 00:00:00 2001
+From: DaeMyung Kang <charsyam@gmail.com>
+Date: Fri, 17 Apr 2026 06:17:35 +0900
+Subject: smb: server: fix max_connections off-by-one in tcp accept path
+
+From: DaeMyung Kang <charsyam@gmail.com>
+
+commit ce23158bfe584bd90d1918f279fdf9de57802012 upstream.
+
+The global max_connections check in ksmbd's TCP accept path counts
+the newly accepted connection with atomic_inc_return(), but then
+rejects the connection when the result is greater than or equal to
+server_conf.max_connections.
+
+That makes the effective limit one smaller than configured. For
+example:
+
+- max_connections=1 rejects the first connection
+- max_connections=2 allows only one connection
+
+The per-IP limit in the same function uses <= correctly because it
+counts only pre-existing connections. The global limit instead checks
+the post-increment total, so it should reject only when that total
+exceeds the configured maximum.
+
+Fix this by changing the comparison from >= to >, so exactly
+max_connections simultaneous connections are allowed and the next one
+is rejected. This matches the documented meaning of max_connections
+in fs/smb/server/ksmbd_netlink.h as the "Number of maximum simultaneous
+connections".
+
+Fixes: 0d0d4680db22 ("ksmbd: add max connections parameter")
+Cc: stable@vger.kernel.org
+Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/transport_tcp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/smb/server/transport_tcp.c
++++ b/fs/smb/server/transport_tcp.c
+@@ -301,7 +301,7 @@ static int ksmbd_kthread_fn(void *p)
+ skip_max_ip_conns_limit:
+               if (server_conf.max_connections &&
+-                  atomic_inc_return(&active_num_conn) >= server_conf.max_connections) {
++                  atomic_inc_return(&active_num_conn) > server_conf.max_connections) {
+                       pr_info_ratelimited("Limit the maximum number of connections(%u)\n",
+                                           atomic_read(&active_num_conn));
+                       atomic_dec(&active_num_conn);
diff --git a/queue-6.18/writeback-fix-use-after-free-in-inode_switch_wbs_work_fn.patch b/queue-6.18/writeback-fix-use-after-free-in-inode_switch_wbs_work_fn.patch
new file mode 100644 (file)
index 0000000..88d6ad4
--- /dev/null
@@ -0,0 +1,104 @@
+From 6689f01d6740cf358932b3e97ee968c6099800d9 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Mon, 13 Apr 2026 11:36:19 +0200
+Subject: writeback: Fix use after free in inode_switch_wbs_work_fn()
+
+From: Jan Kara <jack@suse.cz>
+
+commit 6689f01d6740cf358932b3e97ee968c6099800d9 upstream.
+
+inode_switch_wbs_work_fn() has a loop like:
+
+  wb_get(new_wb);
+  while (1) {
+    list = llist_del_all(&new_wb->switch_wbs_ctxs);
+    /* Nothing to do? */
+    if (!list)
+      break;
+    ... process the items ...
+  }
+
+Now adding of items to the list looks like:
+
+wb_queue_isw()
+  if (llist_add(&isw->list, &wb->switch_wbs_ctxs))
+    queue_work(isw_wq, &wb->switch_work);
+
+Because inode_switch_wbs_work_fn() loops when processing isw items, it
+can happen that wb->switch_work is pending while wb->switch_wbs_ctxs is
+empty. This is a problem because in that case wb can get freed (no isw
+items -> no wb reference) while the work is still pending causing
+use-after-free issues.
+
+We cannot just fix this by cancelling work when freeing wb because that
+could still trigger problematic 0 -> 1 transitions on wb refcount due to
+wb_get() in inode_switch_wbs_work_fn(). It could be all handled with
+more careful code but that seems unnecessarily complex so let's avoid
+that until it is proven that the looping actually brings practical
+benefit. Just remove the loop from inode_switch_wbs_work_fn() instead.
+That way when wb_queue_isw() queues work, we are guaranteed we have
+added the first item to wb->switch_wbs_ctxs and nobody is going to
+remove it (and drop the wb reference it holds) until the queued work
+runs.
+
+Fixes: e1b849cfa6b6 ("writeback: Avoid contention on wb->list_lock when switching inodes")
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20260413093618.17244-2-jack@suse.cz
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fs-writeback.c |   36 +++++++++++++++++++-----------------
+ 1 file changed, 19 insertions(+), 17 deletions(-)
+
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -558,28 +558,30 @@ void inode_switch_wbs_work_fn(struct wor
+       struct inode_switch_wbs_context *isw, *next_isw;
+       struct llist_node *list;
++      list = llist_del_all(&new_wb->switch_wbs_ctxs);
+       /*
+-       * Grab out reference to wb so that it cannot get freed under us
++       * Nothing to do? That would be a problem as references held by isw
++       * items protect wb from freeing...
++       */
++      if (WARN_ON_ONCE(!list))
++              return;
++
++      /*
++       * Grab our reference to wb so that it cannot get freed under us
+        * after we process all the isw items.
+        */
+       wb_get(new_wb);
+-      while (1) {
+-              list = llist_del_all(&new_wb->switch_wbs_ctxs);
+-              /* Nothing to do? */
+-              if (!list)
+-                      break;
+-              /*
+-               * In addition to synchronizing among switchers, I_WB_SWITCH
+-               * tells the RCU protected stat update paths to grab the i_page
+-               * lock so that stat transfer can synchronize against them.
+-               * Let's continue after I_WB_SWITCH is guaranteed to be
+-               * visible.
+-               */
+-              synchronize_rcu();
++      /*
++       * In addition to synchronizing among switchers, I_WB_SWITCH
++       * tells the RCU protected stat update paths to grab the i_page
++       * lock so that stat transfer can synchronize against them.
++       * Let's continue after I_WB_SWITCH is guaranteed to be
++       * visible.
++       */
++      synchronize_rcu();
+-              llist_for_each_entry_safe(isw, next_isw, list, list)
+-                      process_inode_switch_wbs(new_wb, isw);
+-      }
++      llist_for_each_entry_safe(isw, next_isw, list, list)
++              process_inode_switch_wbs(new_wb, isw);
+       wb_put(new_wb);
+ }