]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 May 2026 08:17:06 +0000 (10:17 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 May 2026 08:17:06 +0000 (10:17 +0200)
added patches:
alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch
alsa-pcm-don-t-setup-bogus-iov_iter-for-silencing.patch
alsa-ua101-reject-too-short-usb-descriptors.patch
bluetooth-bnep-fix-uaf-read-of-dev-name.patch
bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch
bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch
bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch
bluetooth-l2cap-ecred_reconfigure-send-packed-pdu-not-stack-pointer.patch
bluetooth-mgmt-validate-add-extended-advertising-data-length.patch
bluetooth-serialize-accept_q-access.patch
drivers-base-memory-fix-memory-block-reference-leak-in-poison-accounting.patch
efi-allocate-runtime-workqueue-before-acpi-init.patch
hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch
io_uring-waitid-clear-waitid-info-before-copying-it-to-userspace.patch
ipv6-ioam-refresh-hdr-pointer-before-ioam6_event.patch
ksmbd-fix-null-pointer-dereference-in-compare_guid_key.patch
ksmbd-fix-sid-memory-leak-in-set_posix_acl_entries_dacl-on-overflow.patch
ksmbd-validate-sid-in-parent-security-descriptor-during-acl-inheritance.patch
mm-damon-sysfs-schemes-call-missing-mem_cgroup_iter_break.patch
mm-memory_hotplug-fix-memory-block-reference-leak-on-remove.patch
net-bcmgenet-keep-rbuf-eee-pm-disabled.patch
net-ifb-report-ethtool-stats-over-num_tx_queues.patch
net-pse-pd-fix-sign-on-enoent-check-in-of_load_pse_pis.patch
net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch
netfilter-ip6t_hbh-reject-oversized-option-lists.patch
netfilter-ipset-stop-hash-range-iteration-at-end.patch
netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch
netfilter-nft_inner-fix-ipv6-inner_thoff-desync.patch
phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch
selftests-mm-run_vmtests.sh-fix-destructive-tests-invocation.patch
smb-client-protect-tc_count-increment-in-smb2_find_smb_sess_tcon_unlocked.patch
smb-client-require-net-admin-for-cifs-swn-netlink.patch
smb-client-use-data_len-for-smb2-read-encrypted-folioq-copy.patch
smb-server-promote-s_del_on_cls-to-s_del_pending-when-close.patch
sysfs-don-t-remove-existing-directory-on-update-failure.patch

36 files changed:
queue-6.12/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch [new file with mode: 0644]
queue-6.12/alsa-pcm-don-t-setup-bogus-iov_iter-for-silencing.patch [new file with mode: 0644]
queue-6.12/alsa-ua101-reject-too-short-usb-descriptors.patch [new file with mode: 0644]
queue-6.12/bluetooth-bnep-fix-uaf-read-of-dev-name.patch [new file with mode: 0644]
queue-6.12/bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch [new file with mode: 0644]
queue-6.12/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch [new file with mode: 0644]
queue-6.12/bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch [new file with mode: 0644]
queue-6.12/bluetooth-l2cap-ecred_reconfigure-send-packed-pdu-not-stack-pointer.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-validate-add-extended-advertising-data-length.patch [new file with mode: 0644]
queue-6.12/bluetooth-serialize-accept_q-access.patch [new file with mode: 0644]
queue-6.12/drivers-base-memory-fix-memory-block-reference-leak-in-poison-accounting.patch [new file with mode: 0644]
queue-6.12/efi-allocate-runtime-workqueue-before-acpi-init.patch [new file with mode: 0644]
queue-6.12/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch [new file with mode: 0644]
queue-6.12/io_uring-waitid-clear-waitid-info-before-copying-it-to-userspace.patch [new file with mode: 0644]
queue-6.12/ipv6-ioam-refresh-hdr-pointer-before-ioam6_event.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-null-pointer-dereference-in-compare_guid_key.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-sid-memory-leak-in-set_posix_acl_entries_dacl-on-overflow.patch [new file with mode: 0644]
queue-6.12/ksmbd-validate-sid-in-parent-security-descriptor-during-acl-inheritance.patch [new file with mode: 0644]
queue-6.12/mm-damon-sysfs-schemes-call-missing-mem_cgroup_iter_break.patch [new file with mode: 0644]
queue-6.12/mm-memory_hotplug-fix-memory-block-reference-leak-on-remove.patch [new file with mode: 0644]
queue-6.12/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch [new file with mode: 0644]
queue-6.12/net-ifb-report-ethtool-stats-over-num_tx_queues.patch [new file with mode: 0644]
queue-6.12/net-pse-pd-fix-sign-on-enoent-check-in-of_load_pse_pis.patch [new file with mode: 0644]
queue-6.12/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch [new file with mode: 0644]
queue-6.12/netfilter-ip6t_hbh-reject-oversized-option-lists.patch [new file with mode: 0644]
queue-6.12/netfilter-ipset-stop-hash-range-iteration-at-end.patch [new file with mode: 0644]
queue-6.12/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch [new file with mode: 0644]
queue-6.12/netfilter-nft_inner-fix-ipv6-inner_thoff-desync.patch [new file with mode: 0644]
queue-6.12/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch [new file with mode: 0644]
queue-6.12/selftests-mm-run_vmtests.sh-fix-destructive-tests-invocation.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/smb-client-protect-tc_count-increment-in-smb2_find_smb_sess_tcon_unlocked.patch [new file with mode: 0644]
queue-6.12/smb-client-require-net-admin-for-cifs-swn-netlink.patch [new file with mode: 0644]
queue-6.12/smb-client-use-data_len-for-smb2-read-encrypted-folioq-copy.patch [new file with mode: 0644]
queue-6.12/smb-server-promote-s_del_on_cls-to-s_del_pending-when-close.patch [new file with mode: 0644]
queue-6.12/sysfs-don-t-remove-existing-directory-on-update-failure.patch [new file with mode: 0644]

diff --git a/queue-6.12/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch b/queue-6.12/alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch
new file mode 100644 (file)
index 0000000..c6877a4
--- /dev/null
@@ -0,0 +1,37 @@
+From 7b7d6572145c1dab2dd9bfb550b188e5f0ff3c3f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 15 May 2026 10:55:58 +0200
+Subject: ALSA: asihpi: Fix potential OOB array access at reading cache
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 7b7d6572145c1dab2dd9bfb550b188e5f0ff3c3f upstream.
+
+find_control() to retrieve a cached info accesses the array with the
+given index blindly, which may lead to an OOB array access.
+Add a sanity check for avoiding it.
+
+Link: https://sashiko.dev/#/patchset/20260511230121.28606-1-rosenp%40gmail.com
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20260515085606.242284-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/asihpi/hpicmn.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/sound/pci/asihpi/hpicmn.c
++++ b/sound/pci/asihpi/hpicmn.c
+@@ -276,6 +276,12 @@ static short find_control(u16 control_in
+               return 0;
+       }
++      if (control_index >= p_cache->control_count) {
++              HPI_DEBUG_LOG(VERBOSE, "control_index out of bounce %d\n",
++                      control_index);
++              return 0;
++      }
++
+       *pI = p_cache->p_info[control_index];
+       if (!*pI) {
+               HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
diff --git a/queue-6.12/alsa-pcm-don-t-setup-bogus-iov_iter-for-silencing.patch b/queue-6.12/alsa-pcm-don-t-setup-bogus-iov_iter-for-silencing.patch
new file mode 100644 (file)
index 0000000..770c541
--- /dev/null
@@ -0,0 +1,42 @@
+From e4d3386b74fba8e01280484b67ee481ece00201e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 17 May 2026 18:51:20 +0200
+Subject: ALSA: pcm: Don't setup bogus iov_iter for silencing
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit e4d3386b74fba8e01280484b67ee481ece00201e upstream.
+
+At transition to the iov_iter for PCM data transfer, we blindly
+applied the iov_iter setup also for silencing (i.e. data = NULL), and
+it leads to a calculation of bogus iov_iter.  Fortunately this didn't
+cause troubles on most of architectures but it goes wrong on RISC-V
+now, causing a NULL dereference.
+
+Handle the NULL data case to treat the silencing in interleaved_copy()
+for addressing the bug above.  noninterleaved_copy() has already the
+NULL data handling, so it doesn't need changes.
+
+Reported-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
+Closes: https://lore.kernel.org/20260515051516.3103036-1-xujiakai24@mails.ucas.ac.cn
+Fixes: cf393babb37a ("ALSA: pcm: Add copy ops with iov_iter")
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20260517165121.31399-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/pcm_lib.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2138,6 +2138,9 @@ static int interleaved_copy(struct snd_p
+       off = frames_to_bytes(runtime, off);
+       frames = frames_to_bytes(runtime, frames);
++      if (!data)
++              return fill_silence(substream, 0, hwoff, NULL, frames);
++
+       return do_transfer(substream, 0, hwoff, data + off, frames, transfer,
+                          in_kernel);
+ }
diff --git a/queue-6.12/alsa-ua101-reject-too-short-usb-descriptors.patch b/queue-6.12/alsa-ua101-reject-too-short-usb-descriptors.patch
new file mode 100644 (file)
index 0000000..25c4270
--- /dev/null
@@ -0,0 +1,45 @@
+From b59d5c51bb328a60749b4dd5fe7e649bfb4089b4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Tue, 19 May 2026 00:32:15 -0300
+Subject: ALSA: ua101: Reject too-short USB descriptors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit b59d5c51bb328a60749b4dd5fe7e649bfb4089b4 upstream.
+
+find_format_descriptor() walks the class-specific interface extras by
+advancing with bLength. It rejects descriptors that extend past the
+remaining buffer, but it does not reject descriptor lengths smaller than
+a USB descriptor header.
+
+Reject too-short descriptors before using bLength to advance the local
+scan. This keeps the UA-101 parser robust against malformed descriptor
+data and matches the usual USB descriptor walking rules.
+
+Fixes: 63978ab3e3e9 ("sound: add Edirol UA-101 support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-alsa-ua101-desc-len-v1-1-4307d1a5e054@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/misc/ua101.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/sound/usb/misc/ua101.c
++++ b/sound/usb/misc/ua101.c
+@@ -914,8 +914,9 @@ find_format_descriptor(struct usb_interf
+               struct uac_format_type_i_discrete_descriptor *desc;
+               desc = (struct uac_format_type_i_discrete_descriptor *)extra;
+-              if (desc->bLength > extralen) {
+-                      dev_err(&interface->dev, "descriptor overflow\n");
++              if (desc->bLength < sizeof(struct usb_descriptor_header) ||
++                  desc->bLength > extralen) {
++                      dev_err(&interface->dev, "invalid descriptor length\n");
+                       return NULL;
+               }
+               if (desc->bLength == UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1) &&
diff --git a/queue-6.12/bluetooth-bnep-fix-uaf-read-of-dev-name.patch b/queue-6.12/bluetooth-bnep-fix-uaf-read-of-dev-name.patch
new file mode 100644 (file)
index 0000000..6a21f24
--- /dev/null
@@ -0,0 +1,40 @@
+From 59e932ded949fa6f0340bf7c6d7818f962fa4fd2 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Tue, 12 May 2026 22:15:39 +0200
+Subject: Bluetooth: bnep: Fix UAF read of dev->name
+
+From: Jann Horn <jannh@google.com>
+
+commit 59e932ded949fa6f0340bf7c6d7818f962fa4fd2 upstream.
+
+bnep_add_connection() needs to keep holding the bnep_session_sem while
+reading dev->name (just like bnep_get_connlist() does); otherwise the
+bnep_session() thread can concurrently free the net_device, which can for
+example be triggered by a concurrent bnep_del_connection().
+
+(This UAF is fairly uninteresting from a security perspective;
+calling bnep_add_connection() requires passing a capable(CAP_NET_ADMIN)
+check. It also requires completely tearing down a netdev during a fairly
+tight race window.)
+
+Cc: stable@vger.kernel.org
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jann Horn <jannh@google.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/bnep/core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/bluetooth/bnep/core.c
++++ b/net/bluetooth/bnep/core.c
+@@ -638,8 +638,8 @@ int bnep_add_connection(struct bnep_conn
+               goto failed;
+       }
+-      up_write(&bnep_session_sem);
+       strcpy(req->device, dev->name);
++      up_write(&bnep_session_sem);
+       return 0;
+ failed:
diff --git a/queue-6.12/bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch b/queue-6.12/bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch
new file mode 100644 (file)
index 0000000..65a8e10
--- /dev/null
@@ -0,0 +1,236 @@
+From ab1513597c6cf17cd1ad2a21e3b045421b48e022 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Safa=20Karaku=C5=9F?= <safa.karakus@secunnix.com>
+Date: Sat, 16 May 2026 21:15:04 +0300
+Subject: Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Safa Karakuş <safa.karakus@secunnix.com>
+
+commit ab1513597c6cf17cd1ad2a21e3b045421b48e022 upstream.
+
+bt_accept_dequeue() unlinks a not-yet-accepted child from the parent
+accept queue and release_sock()s it before returning, so the returned
+sk has no caller reference and is unlocked.
+
+l2cap_sock_cleanup_listen() walks these children on listening-socket
+close.  A concurrent HCI disconnect drives hci_rx_work ->
+l2cap_conn_del() which runs l2cap_chan_del() + l2cap_sock_kill() and
+frees the child sk and its l2cap_chan; cleanup_listen() then uses both:
+
+  BUG: KASAN: slab-use-after-free in l2cap_sock_kill
+    l2cap_sock_kill / l2cap_sock_cleanup_listen / __x64_sys_close
+  Freed by: l2cap_conn_del -> l2cap_sock_close_cb -> l2cap_sock_kill
+
+This is distinct from the two fixes already in this area: commit
+e83f5e24da741 ("Bluetooth: serialize accept_q access") serialises the
+accept_q list/poll and takes temporary refs inside bt_accept_dequeue(),
+and CVE-2025-39860 serialises the userspace close()/accept() race by
+calling cleanup_listen() under lock_sock() in l2cap_sock_release().
+Neither covers l2cap_conn_del() running from hci_rx_work, so this UAF
+still reproduces on current bluetooth/master.
+
+Take the reference at the source: bt_accept_dequeue() does sock_hold()
+while sk is still locked, before release_sock(); callers sock_put().
+cleanup_listen() pins the chan with l2cap_chan_hold_unless_zero() under
+a brief child sk lock (serialising vs l2cap_sock_teardown_cb()), drops
+it before l2cap_chan_lock(), and skips a duplicate l2cap_sock_kill() on
+SOCK_DEAD.  conn->lock is not taken here: cleanup_listen() runs under
+the parent sk lock and that would invert
+conn->lock -> chan->lock -> sk_lock (lockdep).
+
+KASAN/SMP: an unprivileged listen/close vs HCI-disconnect race produced
+12 use-after-free reports per run before this change; 0, and no lockdep
+report, over 1600+ raced iterations after it on bluetooth/master.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Cc: stable@vger.kernel.org
+Reported-by: Siwei Zhang <oss@fourdim.xyz>
+Reviewed-by: Siwei Zhang <oss@fourdim.xyz>
+Signed-off-by: Safa Karakuş <safa.karakus@secunnix.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/af_bluetooth.c |   10 ++++++++
+ net/bluetooth/iso.c          |    9 ++++++-
+ net/bluetooth/l2cap_sock.c   |   51 +++++++++++++++++++++++++++++++++++++------
+ net/bluetooth/rfcomm/sock.c  |    9 ++++++-
+ net/bluetooth/sco.c          |    9 ++++++-
+ 5 files changed, 78 insertions(+), 10 deletions(-)
+
+--- a/net/bluetooth/af_bluetooth.c
++++ b/net/bluetooth/af_bluetooth.c
+@@ -306,6 +306,16 @@ restart:
+                       if (newsock)
+                               sock_graft(sk, newsock);
++                      /* Hand the caller a reference taken while sk is
++                       * still locked.  bt_accept_unlink() just dropped
++                       * the accept-queue reference; without this hold a
++                       * concurrent teardown (e.g. l2cap_conn_del() ->
++                       * l2cap_sock_kill()) could free sk between
++                       * release_sock() and the caller using it.  Every
++                       * caller drops this with sock_put() when done.
++                       */
++                      sock_hold(sk);
++
+                       release_sock(sk);
+                       return sk;
+               }
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -722,6 +722,8 @@ static void iso_sock_cleanup_listen(stru
+       while ((sk = bt_accept_dequeue(parent, NULL))) {
+               iso_sock_close(sk);
+               iso_sock_kill(sk);
++              /* Drop the reference handed back by bt_accept_dequeue(). */
++              sock_put(sk);
+       }
+       /* If listening socket has a hcon, properly disconnect it */
+@@ -1263,8 +1265,13 @@ static int iso_sock_accept(struct socket
+               }
+               ch = bt_accept_dequeue(sk, newsock);
+-              if (ch)
++              if (ch) {
++                      /* Drop the bridging ref from bt_accept_dequeue();
++                       * the grafted socket keeps ch alive from here.
++                       */
++                      sock_put(ch);
+                       break;
++              }
+               if (!timeo) {
+                       err = -EAGAIN;
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -349,8 +349,13 @@ static int l2cap_sock_accept(struct sock
+               }
+               nsk = bt_accept_dequeue(sk, newsock);
+-              if (nsk)
++              if (nsk) {
++                      /* Drop the bridging ref from bt_accept_dequeue();
++                       * the grafted socket keeps nsk alive from here.
++                       */
++                      sock_put(nsk);
+                       break;
++              }
+               if (!timeo) {
+                       err = -EAGAIN;
+@@ -1444,22 +1449,54 @@ static void l2cap_sock_cleanup_listen(st
+       BT_DBG("parent %p state %s", parent,
+              state_to_string(parent->sk_state));
+-      /* Close not yet accepted channels */
++      /* Close not yet accepted channels.
++       *
++       * bt_accept_dequeue() now returns sk with an extra reference held
++       * (taken while sk was still locked) so a concurrent l2cap_conn_del()
++       * -> l2cap_sock_kill() cannot free sk under us.
++       *
++       * cleanup_listen() runs under the parent sk lock, so unlike
++       * l2cap_sock_shutdown() we must NOT take conn->lock here: that would
++       * establish sk_lock -> conn->lock and invert the established
++       * conn->lock -> chan->lock -> sk_lock order (lockdep deadlock).
++       *
++       * Instead, briefly take the child sk lock to fetch and pin its chan.
++       * l2cap_conn_del() reaches the chan free only via
++       * l2cap_chan_del() -> l2cap_sock_teardown_cb(), which itself takes
++       * the child sk lock; holding it across l2cap_chan_hold_unless_zero()
++       * therefore guarantees the chan cannot be freed while we read and
++       * pin it (hold_unless_zero() additionally skips a chan already past
++       * its last reference).  We then drop the sk lock before taking
++       * chan->lock, so sk and chan locks are never held together.
++       */
+       while ((sk = bt_accept_dequeue(parent, NULL))) {
+-              struct l2cap_chan *chan = l2cap_pi(sk)->chan;
++              struct l2cap_chan *chan;
++
++              lock_sock_nested(sk, L2CAP_NESTING_NORMAL);
++              chan = l2cap_chan_hold_unless_zero(l2cap_pi(sk)->chan);
++              release_sock(sk);
++              if (!chan) {
++                      /* l2cap_conn_del() already tearing this child down */
++                      sock_put(sk);
++                      continue;
++              }
+               BT_DBG("child chan %p state %s", chan,
+                      state_to_string(chan->state));
+-              l2cap_chan_hold(chan);
+               l2cap_chan_lock(chan);
+-
+               __clear_chan_timer(chan);
+               l2cap_chan_close(chan, ECONNRESET);
+-              l2cap_sock_kill(sk);
+-
++              /* l2cap_conn_del() may already have killed this socket
++               * (it sets SOCK_DEAD); skip the duplicate to avoid a
++               * double sock_put()/l2cap_chan_put().
++               */
++              if (!sock_flag(sk, SOCK_DEAD))
++                      l2cap_sock_kill(sk);
+               l2cap_chan_unlock(chan);
++
+               l2cap_chan_put(chan);
++              sock_put(sk);
+       }
+ }
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -180,6 +180,8 @@ static void rfcomm_sock_cleanup_listen(s
+       while ((sk = bt_accept_dequeue(parent, NULL))) {
+               rfcomm_sock_close(sk);
+               rfcomm_sock_kill(sk);
++              /* Drop the reference handed back by bt_accept_dequeue(). */
++              sock_put(sk);
+       }
+       parent->sk_state  = BT_CLOSED;
+@@ -496,8 +498,13 @@ static int rfcomm_sock_accept(struct soc
+               }
+               nsk = bt_accept_dequeue(sk, newsock);
+-              if (nsk)
++              if (nsk) {
++                      /* Drop the bridging ref from bt_accept_dequeue();
++                       * the grafted socket keeps nsk alive from here.
++                       */
++                      sock_put(nsk);
+                       break;
++              }
+               if (!timeo) {
+                       err = -EAGAIN;
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -433,6 +433,8 @@ static void sco_sock_cleanup_listen(stru
+       while ((sk = bt_accept_dequeue(parent, NULL))) {
+               sco_sock_close(sk);
+               sco_sock_kill(sk);
++              /* Drop the reference handed back by bt_accept_dequeue(). */
++              sock_put(sk);
+       }
+       parent->sk_state  = BT_CLOSED;
+@@ -705,8 +707,13 @@ static int sco_sock_accept(struct socket
+               }
+               ch = bt_accept_dequeue(sk, newsock);
+-              if (ch)
++              if (ch) {
++                      /* Drop the bridging ref from bt_accept_dequeue();
++                       * the grafted socket keeps ch alive from here.
++                       */
++                      sock_put(ch);
+                       break;
++              }
+               if (!timeo) {
+                       err = -EAGAIN;
diff --git a/queue-6.12/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch b/queue-6.12/bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch
new file mode 100644 (file)
index 0000000..929d324
--- /dev/null
@@ -0,0 +1,173 @@
+From c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b Mon Sep 17 00:00:00 2001
+From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Date: Mon, 18 May 2026 10:49:49 +0800
+Subject: Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
+
+From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+
+commit c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b upstream.
+
+Vulnerabilities leading to Use-After-Free (UAF) and Null Pointer
+Dereference (NPD) conditions were observed in the lifecycle management
+of hci_uart.
+
+The primary issue arises because the workqueues (init_ready and
+write_work) are only flushed/cancelled if the HCI_UART_PROTO_READY
+flag is set during TTY close. If a hangup occurs before setup completes,
+hci_uart_tty_close() skips the teardown of these workqueues and
+proceeds to free the `hu` struct. When the scheduled work executes
+later, it blindly dereferences the freed `hu` struct.
+
+Furthermore, several data races and UAFs were identified in the teardown
+sequence:
+1. Calling hci_uart_flush() from hci_uart_close() without effectively
+   disabling write_work causes a race condition where both can concurrently
+   double-free hu->tx_skb. This happens because protocol timers can
+   concurrently invoke hci_uart_tx_wakeup() and requeue write_work.
+2. Calling hci_free_dev(hdev) before hu->proto->close(hu) causes a UAF
+   when vendor specific protocol close callbacks dereference hu->hdev.
+3. In the initialization error paths, failing to take the proto_lock
+   write lock before clearing PROTO_READY leads to races with active
+   readers. Additionally, hci_uart_tty_receive() accesses hu->hdev
+   outside the read lock, leading to UAFs if the initialization error
+   path frees hdev concurrently.
+
+Fix these synchronization and lifecycle issues by:
+1. Re-ordering hci_uart_tty_close() to clear HCI_UART_PROTO_READY first,
+   followed immediately by a cancel_work_sync(&hu->write_work). Clearing
+   the flag locks out concurrent protocol timers from successfully invoking
+   hci_uart_tx_wakeup(), effectively rendering the cancellation permanent
+   and preventing the tx_skb double-free.
+2. Note: Clearing PROTO_READY early causes hci_uart_close() to skip
+   hu->proto->flush(). This is perfectly safe in the tty_close path
+   because hu->proto->close() executes shortly after, which intrinsically
+   purges all protocol SKB queues and tears down the state.
+3. Relocating hu->proto->close(hu) strictly prior to hci_free_dev(hdev)
+   across all close and error paths to prevent vendor-level UAFs.
+4. Moving the hdev->stat.byte_rx increment in hci_uart_tty_receive()
+   inside the proto_lock read-side critical section to safely synchronize
+   with device unregistration.
+5. Adding cancel_work_sync(&hu->write_work) to hci_uart_close() to safely
+   flush the workqueue before hci_uart_flush() is invoked via the HCI core.
+6. Utilizing cancel_work_sync() instead of disable_work_sync() across
+   all paths to prevent permanently breaking user-space retry capabilities.
+
+Fixes: 3b799254cf6f ("Bluetooth: hci_uart: Cancel init work before unregistering")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bluetooth/hci_ldisc.c |   48 +++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 40 insertions(+), 8 deletions(-)
+
+--- a/drivers/bluetooth/hci_ldisc.c
++++ b/drivers/bluetooth/hci_ldisc.c
+@@ -194,7 +194,15 @@ void hci_uart_init_work(struct work_stru
+       err = hci_register_dev(hu->hdev);
+       if (err < 0) {
+               BT_ERR("Can't register HCI device");
++
++              percpu_down_write(&hu->proto_lock);
+               clear_bit(HCI_UART_PROTO_READY, &hu->flags);
++              percpu_up_write(&hu->proto_lock);
++
++              /* Safely cancel work after clearing flags */
++              cancel_work_sync(&hu->write_work);
++
++              /* Close protocol before freeing hdev */
+               hu->proto->close(hu);
+               hdev = hu->hdev;
+               hu->hdev = NULL;
+@@ -263,8 +271,12 @@ static int hci_uart_open(struct hci_dev
+ /* Close device */
+ static int hci_uart_close(struct hci_dev *hdev)
+ {
++      struct hci_uart *hu = hci_get_drvdata(hdev);
++
+       BT_DBG("hdev %p", hdev);
++      cancel_work_sync(&hu->write_work);
++
+       hci_uart_flush(hdev);
+       hdev->flush = NULL;
+       return 0;
+@@ -531,6 +543,7 @@ static void hci_uart_tty_close(struct tt
+ {
+       struct hci_uart *hu = tty->disc_data;
+       struct hci_dev *hdev;
++      bool proto_ready;
+       BT_DBG("tty %p", tty);
+@@ -540,24 +553,38 @@ static void hci_uart_tty_close(struct tt
+       if (!hu)
+               return;
+-      hdev = hu->hdev;
+-      if (hdev)
+-              hci_uart_close(hdev);
++      /* Wait for init_ready to finish to prevent registration races */
++      cancel_work_sync(&hu->init_ready);
+-      if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
++      proto_ready = test_bit(HCI_UART_PROTO_READY, &hu->flags);
++      if (proto_ready) {
+               percpu_down_write(&hu->proto_lock);
+               clear_bit(HCI_UART_PROTO_READY, &hu->flags);
+               percpu_up_write(&hu->proto_lock);
++      }
+-              cancel_work_sync(&hu->init_ready);
+-              cancel_work_sync(&hu->write_work);
++      /*
++       * Unconditionally cancel write_work AFTER clearing PROTO_READY.
++       * This ensures that concurrent protocol timers cannot requeue
++       * write_work via hci_uart_tx_wakeup(), permanently preventing
++       * double-free races and UAFs.
++       */
++      cancel_work_sync(&hu->write_work);
++
++      hdev = hu->hdev;
++      if (hdev)
++              hci_uart_close(hdev); /* proto->flush is safely skipped */
++      if (proto_ready) {
+               if (hdev) {
+                       if (test_bit(HCI_UART_REGISTERED, &hu->flags))
+                               hci_unregister_dev(hdev);
+-                      hci_free_dev(hdev);
+               }
++              /* Close protocol before freeing hdev (intrinsically purges queues) */
+               hu->proto->close(hu);
++
++              if (hdev)
++                      hci_free_dev(hdev);
+       }
+       clear_bit(HCI_UART_PROTO_SET, &hu->flags);
+@@ -625,11 +652,12 @@ static void hci_uart_tty_receive(struct
+        * tty caller
+        */
+       hu->proto->recv(hu, data, count);
+-      percpu_up_read(&hu->proto_lock);
+       if (hu->hdev)
+               hu->hdev->stat.byte_rx += count;
++      percpu_up_read(&hu->proto_lock);
++
+       tty_unthrottle(tty);
+ }
+@@ -695,6 +723,10 @@ static int hci_uart_register_dev(struct
+               percpu_down_write(&hu->proto_lock);
+               clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
+               percpu_up_write(&hu->proto_lock);
++              /* Cancel work after clearing flags */
++              cancel_work_sync(&hu->write_work);
++
++              /* Close protocol before freeing hdev */
+               hu->proto->close(hu);
+               hu->hdev = NULL;
+               hci_free_dev(hdev);
diff --git a/queue-6.12/bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch b/queue-6.12/bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch
new file mode 100644 (file)
index 0000000..6e94a89
--- /dev/null
@@ -0,0 +1,47 @@
+From 84c24fb151fc1179355296d7ff29129ac7c42129 Mon Sep 17 00:00:00 2001
+From: David Carlier <devnexen@gmail.com>
+Date: Fri, 15 May 2026 07:25:25 +0100
+Subject: Bluetooth: ISO: drop ISO_END frames received without prior ISO_START
+
+From: David Carlier <devnexen@gmail.com>
+
+commit 84c24fb151fc1179355296d7ff29129ac7c42129 upstream.
+
+ISO data PDUs carry a packet-boundary flag indicating START, CONT, END
+or SINGLE. The ISO_CONT branch of iso_recv() guards against a missing
+ISO_START by checking conn->rx_len before touching conn->rx_skb, but
+ISO_END does not.
+
+If a peer sends an ISO_END as the first packet on a fresh ISO
+connection, conn->rx_skb is still NULL and conn->rx_len is zero, so
+skb_put(conn->rx_skb, ...) dereferences NULL and oopses. For BIS,
+where receivers sync to a broadcaster without pairing, any broadcaster
+on the air can trigger this.
+
+Mirror the ISO_CONT check at the top of ISO_END so a stray end fragment
+is logged and dropped instead of crashing the host.
+
+Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: David Carlier <devnexen@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/iso.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -2319,6 +2319,11 @@ void iso_recv(struct hci_conn *hcon, str
+               break;
+       case ISO_END:
++              if (!conn->rx_len) {
++                      BT_ERR("Unexpected end frame (len %d)", skb->len);
++                      goto drop;
++              }
++
+               skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
+                                         skb->len);
+               conn->rx_len -= skb->len;
diff --git a/queue-6.12/bluetooth-l2cap-ecred_reconfigure-send-packed-pdu-not-stack-pointer.patch b/queue-6.12/bluetooth-l2cap-ecred_reconfigure-send-packed-pdu-not-stack-pointer.patch
new file mode 100644 (file)
index 0000000..bfddf1c
--- /dev/null
@@ -0,0 +1,84 @@
+From 3374ef8cf99368a40f7efd51a2a375a4c5dc6f0d Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 11 May 2026 08:26:41 -0400
+Subject: Bluetooth: L2CAP: ecred_reconfigure: send packed pdu, not stack pointer
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 3374ef8cf99368a40f7efd51a2a375a4c5dc6f0d upstream.
+
+Commit 1c08108f3014 ("Bluetooth: L2CAP: Avoid -Wflex-array-member-not-at-end
+warnings") converted the on-stack request PDU in l2cap_ecred_reconfigure()
+from an explicit packed struct to DEFINE_RAW_FLEX(), but did not adjust the
+size and source-pointer arguments to l2cap_send_cmd():
+
+  -    struct {
+  -            struct l2cap_ecred_reconf_req req;
+  -            __le16 scid;
+  -    } pdu;
+  +    DEFINE_RAW_FLEX(struct l2cap_ecred_reconf_req, pdu, scid, 1);
+       ...
+       l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
+                      sizeof(pdu), &pdu);
+
+After the conversion, DEFINE_RAW_FLEX() expands to declare an anonymous
+union pdu_u plus a local pointer "pdu" pointing at it. Therefore:
+
+  - sizeof(pdu) is now sizeof(struct l2cap_ecred_reconf_req *) = 8 on
+    64-bit (4 on 32-bit), not the 6 bytes of (mtu, mps, scid[1]).
+  - &pdu is the address of the local pointer's stack storage, not the
+    address of the request payload.
+
+l2cap_send_cmd() forwards (data, count) to l2cap_build_cmd(), which calls
+skb_put_data(skb, data, count). The L2CAP_ECRED_RECONFIGURE_REQ packet
+body therefore contains 8 bytes copied from the kernel stack starting at
+&pdu -- the 8 bytes overlap the pdu pointer's value, leaking a kernel
+stack address to the paired Bluetooth peer. The intended (mtu, mps, scid)
+fields are not transmitted at all, so the peer rejects the request as
+malformed and the L2CAP_ECRED_RECONFIGURE feature itself has been broken
+for the local-side initiator since the introducing commit landed.
+
+The sibling site l2cap_ecred_conn_req() in the same commit was converted
+correctly (sizeof(*pdu) + len, pdu); only this site was missed.
+
+Restore the original semantics: pass the full flex-struct size via
+struct_size(pdu, scid, 1) and the pdu pointer (the struct address) as
+the source.
+
+Validated on a stock 7.0-based host kernel via the real call path:
+setsockopt(SOL_BLUETOOTH, BT_RCVMTU, ...) on a BT_CONNECTED
+L2CAP_MODE_EXT_FLOWCTL socket emits an L2CAP_ECRED_RECONFIGURE_REQ
+whose body is 8 bytes (the on-stack pdu local's value) rather than
+the expected 6. Three captures from fresh socket / fresh hciemu peer
+on the same host -- low bytes vary per call, high 0xffff confirms a
+kernel virtual address (KASLR-randomised stack slot, not a fixed
+string):
+
+  RECONF_REQ body (ident=0x02 len=8): 42 fb 54 af 0e ca ff ff
+  RECONF_REQ body (ident=0x02 len=8): 52 3d 2e af 0e ca ff ff
+  RECONF_REQ body (ident=0x02 len=8): b2 fc 5b af 0e ca ff ff
+
+After this patch the body is 6 bytes carrying the expected
+little-endian (mtu, mps, scid).
+
+Cc: stable@vger.kernel.org
+Fixes: 1c08108f3014 ("Bluetooth: L2CAP: Avoid -Wflex-array-member-not-at-end warnings")
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/l2cap_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -7199,7 +7199,7 @@ static void l2cap_ecred_reconfigure(stru
+       chan->ident = l2cap_get_ident(conn);
+       l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
+-                     sizeof(pdu), &pdu);
++                     struct_size(pdu, scid, 1), pdu);
+ }
+ int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
diff --git a/queue-6.12/bluetooth-mgmt-validate-add-extended-advertising-data-length.patch b/queue-6.12/bluetooth-mgmt-validate-add-extended-advertising-data-length.patch
new file mode 100644 (file)
index 0000000..68bc5c0
--- /dev/null
@@ -0,0 +1,54 @@
+From d3f7d17960ed50df3a6709c5158caff989c8c905 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Fri, 15 May 2026 10:38:19 -0400
+Subject: Bluetooth: MGMT: validate Add Extended Advertising Data length
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit d3f7d17960ed50df3a6709c5158caff989c8c905 upstream.
+
+MGMT_OP_ADD_EXT_ADV_DATA is registered as a variable-length command,
+with MGMT_ADD_EXT_ADV_DATA_SIZE as the fixed header size.  The handler
+then uses cp->adv_data_len and cp->scan_rsp_len to validate and copy
+cp->data, but it never checks that those bytes are part of the mgmt
+command payload.
+
+A short command can therefore make add_ext_adv_data() pass an
+out-of-bounds pointer into tlv_data_is_valid().  If the bytes beyond
+the command buffer are addressable, they can also be copied into the
+advertising instance as scan response data, where the caller can read
+them back via MGMT_OP_GET_ADV_INSTANCE.  The trigger requires
+CAP_NET_ADMIN in the initial user namespace; KASAN reports an 8-byte
+slab-out-of-bounds read.
+
+Reject commands whose length does not match the fixed header plus both
+advertising data lengths before parsing cp->data.
+
+Fixes: 12410572833a ("Bluetooth: Break add adv into two mgmt commands")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/mgmt.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -9193,9 +9193,15 @@ static int add_ext_adv_data(struct sock
+       struct adv_info *adv_instance;
+       int err = 0;
+       struct mgmt_pending_cmd *cmd;
++      u16 expected_len;
+       BT_DBG("%s", hdev->name);
++      expected_len = struct_size(cp, data, cp->adv_data_len + cp->scan_rsp_len);
++      if (expected_len != data_len)
++              return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
++                                     MGMT_STATUS_INVALID_PARAMS);
++
+       hci_dev_lock(hdev);
+       adv_instance = hci_find_adv_instance(hdev, cp->instance);
diff --git a/queue-6.12/bluetooth-serialize-accept_q-access.patch b/queue-6.12/bluetooth-serialize-accept_q-access.patch
new file mode 100644 (file)
index 0000000..1042b0f
--- /dev/null
@@ -0,0 +1,218 @@
+From e83f5e24da741fa9405aeeff00b08c5ee7c37b88 Mon Sep 17 00:00:00 2001
+From: Jiexun Wang <wangjiexun2025@gmail.com>
+Date: Wed, 6 May 2026 19:43:30 +0800
+Subject: Bluetooth: serialize accept_q access
+
+From: Jiexun Wang <wangjiexun2025@gmail.com>
+
+commit e83f5e24da741fa9405aeeff00b08c5ee7c37b88 upstream.
+
+bt_sock_poll() walks the accept queue without synchronization, while
+child teardown can unlink the same socket and drop its last reference.
+The unsynchronized accept queue walk has existed since the initial
+Bluetooth import.
+
+Protect accept_q with a dedicated lock for queue updates and polling.
+Also rework bt_accept_dequeue() to take temporary child references under
+the queue lock before dropping it and locking the child socket.
+
+Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reported-by: Jann Horn <jannh@google.com>
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
+Reviewed-by: Jann Horn <jannh@google.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/bluetooth.h |    1 
+ net/bluetooth/af_bluetooth.c      |   87 ++++++++++++++++++++++++++++----------
+ 2 files changed, 66 insertions(+), 22 deletions(-)
+
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -380,6 +380,7 @@ void baswap(bdaddr_t *dst, const bdaddr_
+ struct bt_sock {
+       struct sock sk;
+       struct list_head accept_q;
++      spinlock_t accept_q_lock; /* protects accept_q */
+       struct sock *parent;
+       unsigned long flags;
+       void (*skb_msg_name)(struct sk_buff *, void *, int *);
+--- a/net/bluetooth/af_bluetooth.c
++++ b/net/bluetooth/af_bluetooth.c
+@@ -151,6 +151,7 @@ struct sock *bt_sock_alloc(struct net *n
+       sock_init_data(sock, sk);
+       INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
++      spin_lock_init(&bt_sk(sk)->accept_q_lock);
+       sock_reset_flag(sk, SOCK_ZAPPED);
+@@ -211,6 +212,7 @@ void bt_accept_enqueue(struct sock *pare
+ {
+       const struct cred *old_cred;
+       struct pid *old_pid;
++      struct bt_sock *par = bt_sk(parent);
+       BT_DBG("parent %p, sk %p", parent, sk);
+@@ -221,9 +223,13 @@ void bt_accept_enqueue(struct sock *pare
+       else
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+-      list_add_tail(&bt_sk(sk)->accept_q, &bt_sk(parent)->accept_q);
+       bt_sk(sk)->parent = parent;
++      spin_lock_bh(&par->accept_q_lock);
++      list_add_tail(&bt_sk(sk)->accept_q, &par->accept_q);
++      sk_acceptq_added(parent);
++      spin_unlock_bh(&par->accept_q_lock);
++
+       /* Copy credentials from parent since for incoming connections the
+        * socket is allocated by the kernel.
+        */
+@@ -241,8 +247,6 @@ void bt_accept_enqueue(struct sock *pare
+               bh_unlock_sock(sk);
+       else
+               release_sock(sk);
+-
+-      sk_acceptq_added(parent);
+ }
+ EXPORT_SYMBOL(bt_accept_enqueue);
+@@ -251,45 +255,72 @@ EXPORT_SYMBOL(bt_accept_enqueue);
+  */
+ void bt_accept_unlink(struct sock *sk)
+ {
++      struct sock *parent = bt_sk(sk)->parent;
++
+       BT_DBG("sk %p state %d", sk, sk->sk_state);
++      spin_lock_bh(&bt_sk(parent)->accept_q_lock);
+       list_del_init(&bt_sk(sk)->accept_q);
+-      sk_acceptq_removed(bt_sk(sk)->parent);
++      sk_acceptq_removed(parent);
++      spin_unlock_bh(&bt_sk(parent)->accept_q_lock);
+       bt_sk(sk)->parent = NULL;
+       sock_put(sk);
+ }
+ EXPORT_SYMBOL(bt_accept_unlink);
++static struct sock *bt_accept_get(struct sock *parent, struct sock *sk)
++{
++      struct bt_sock *bt = bt_sk(parent);
++      struct sock *next = NULL;
++
++      /* accept_q is modified from child teardown paths too, so take a
++       * temporary reference before dropping the queue lock.
++       */
++      spin_lock_bh(&bt->accept_q_lock);
++
++      if (sk) {
++              if (bt_sk(sk)->parent != parent)
++                      goto out;
++
++              if (!list_is_last(&bt_sk(sk)->accept_q, &bt->accept_q)) {
++                      next = &list_next_entry(bt_sk(sk), accept_q)->sk;
++                      sock_hold(next);
++              }
++      } else if (!list_empty(&bt->accept_q)) {
++              next = &list_first_entry(&bt->accept_q,
++                                       struct bt_sock, accept_q)->sk;
++              sock_hold(next);
++      }
++
++out:
++      spin_unlock_bh(&bt->accept_q_lock);
++      return next;
++}
++
+ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
+ {
+-      struct bt_sock *s, *n;
+-      struct sock *sk;
++      struct sock *sk, *next;
+       BT_DBG("parent %p", parent);
+ restart:
+-      list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) {
+-              sk = (struct sock *)s;
+-
++      for (sk = bt_accept_get(parent, NULL); sk; sk = next) {
+               /* Prevent early freeing of sk due to unlink and sock_kill */
+-              sock_hold(sk);
+               lock_sock(sk);
+               /* Check sk has not already been unlinked via
+                * bt_accept_unlink() due to serialisation caused by sk locking
+                */
+-              if (!bt_sk(sk)->parent) {
++              if (bt_sk(sk)->parent != parent) {
+                       BT_DBG("sk %p, already unlinked", sk);
+                       release_sock(sk);
+                       sock_put(sk);
+-                      /* Restart the loop as sk is no longer in the list
+-                       * and also avoid a potential infinite loop because
+-                       * list_for_each_entry_safe() is not thread safe.
+-                       */
+                       goto restart;
+               }
++              next = bt_accept_get(parent, sk);
++
+               /* sk is safely in the parent list so reduce reference count */
+               sock_put(sk);
+@@ -317,6 +348,8 @@ restart:
+                       sock_hold(sk);
+                       release_sock(sk);
++                      if (next)
++                              sock_put(next);
+                       return sk;
+               }
+@@ -518,18 +551,28 @@ EXPORT_SYMBOL(bt_sock_stream_recvmsg);
+ static inline __poll_t bt_accept_poll(struct sock *parent)
+ {
+-      struct bt_sock *s, *n;
++      struct bt_sock *bt = bt_sk(parent);
++      struct bt_sock *s;
+       struct sock *sk;
++      __poll_t mask = 0;
++
++      spin_lock_bh(&bt->accept_q_lock);
++      list_for_each_entry(s, &bt->accept_q, accept_q) {
++              int state;
+-      list_for_each_entry_safe(s, n, &bt_sk(parent)->accept_q, accept_q) {
+               sk = (struct sock *)s;
+-              if (sk->sk_state == BT_CONNECTED ||
+-                  (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags) &&
+-                   sk->sk_state == BT_CONNECT2))
+-                      return EPOLLIN | EPOLLRDNORM;
++              state = READ_ONCE(sk->sk_state);
++
++              if (state == BT_CONNECTED ||
++                  (test_bit(BT_SK_DEFER_SETUP, &bt->flags) &&
++                   state == BT_CONNECT2)) {
++                      mask = EPOLLIN | EPOLLRDNORM;
++                      break;
++              }
+       }
++      spin_unlock_bh(&bt->accept_q_lock);
+-      return 0;
++      return mask;
+ }
+ __poll_t bt_sock_poll(struct file *file, struct socket *sock,
diff --git a/queue-6.12/drivers-base-memory-fix-memory-block-reference-leak-in-poison-accounting.patch b/queue-6.12/drivers-base-memory-fix-memory-block-reference-leak-in-poison-accounting.patch
new file mode 100644 (file)
index 0000000..748d79f
--- /dev/null
@@ -0,0 +1,62 @@
+From 03a2cc1756a0570f887d624cd6c535ea0cbd4951 Mon Sep 17 00:00:00 2001
+From: Muchun Song <songmuchun@bytedance.com>
+Date: Tue, 28 Apr 2026 16:52:18 +0800
+Subject: drivers/base/memory: fix memory block reference leak in poison accounting
+
+From: Muchun Song <songmuchun@bytedance.com>
+
+commit 03a2cc1756a0570f887d624cd6c535ea0cbd4951 upstream.
+
+memblk_nr_poison_inc() and memblk_nr_poison_sub() look up a memory block
+via find_memory_block_by_id(), which acquires a reference to the memory
+block device.
+
+Both helpers use the returned memory block without dropping that
+reference, leaking the device reference on each successful lookup.  Drop
+the reference after updating nr_hwpoison.
+
+Link: https://lore.kernel.org/20260428085219.1316047-3-songmuchun@bytedance.com
+Fixes: 5033091de814 ("mm/hwpoison: introduce per-memory_block hwpoison counter")
+Signed-off-by: Muchun Song <songmuchun@bytedance.com>
+Reviewed-by: Miaohe Lin <linmiaohe@huawei.com>
+Acked-by: Oscar Salvador <osalvador@suse.de>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Cc: Danilo Krummrich <dakr@kernel.org>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "Huang, Ying" <huang.ying.caritas@gmail.com>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: "Rafael J. Wysocki" <rafael@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/memory.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -1232,8 +1232,10 @@ void memblk_nr_poison_inc(unsigned long
+       const unsigned long block_id = pfn_to_block_id(pfn);
+       struct memory_block *mem = find_memory_block_by_id(block_id);
+-      if (mem)
++      if (mem) {
+               atomic_long_inc(&mem->nr_hwpoison);
++              put_device(&mem->dev);
++      }
+ }
+ void memblk_nr_poison_sub(unsigned long pfn, long i)
+@@ -1241,8 +1243,10 @@ void memblk_nr_poison_sub(unsigned long
+       const unsigned long block_id = pfn_to_block_id(pfn);
+       struct memory_block *mem = find_memory_block_by_id(block_id);
+-      if (mem)
++      if (mem) {
+               atomic_long_sub(i, &mem->nr_hwpoison);
++              put_device(&mem->dev);
++      }
+ }
+ static unsigned long memblk_nr_poison(struct memory_block *mem)
diff --git a/queue-6.12/efi-allocate-runtime-workqueue-before-acpi-init.patch b/queue-6.12/efi-allocate-runtime-workqueue-before-acpi-init.patch
new file mode 100644 (file)
index 0000000..81dae6b
--- /dev/null
@@ -0,0 +1,88 @@
+From 13c6da02e767152c9ac4330962247a5e47011035 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 19 May 2026 10:03:00 +0200
+Subject: efi: Allocate runtime workqueue before ACPI init
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+commit 13c6da02e767152c9ac4330962247a5e47011035 upstream.
+
+Since commit
+
+  5894cf571e14 ("acpi/prmt: Use EFI runtime sandbox to invoke PRM handlers")
+
+ACPI PRM calls are delegated to a workqueue which runs in a kernel
+thread, making it easier to detect and mitigate faulting memory accesses
+performed by the firmware.
+
+Rafael reports that such PRM accesses may occur before efisubsys_init()
+executes, which is where the workqueue is allocated, leading to NULL
+pointer dereferences. Since acpi_init() [which triggers the early PRM
+accesses] executes as a subsys_initcall() as well, and has its own
+dependencies that may be sensitive to initcall ordering, deferring
+acpi_init() is not an option.
+
+So instead, split off the workqueue allocation into its own postcore
+initcall, as this is the only missing piece to allow EFI runtime calls
+to be made. This ensures that EFI runtime call (including PRM calls) are
+accessible to all code running at subsys_initcall() level.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 5894cf571e14 ("acpi/prmt: Use EFI runtime sandbox to invoke PRM handlers")
+Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/firmware/efi/efi.c |   28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -387,21 +387,11 @@ static void __init efi_debugfs_init(void
+ static inline void efi_debugfs_init(void) {}
+ #endif
+-/*
+- * We register the efi subsystem with the firmware subsystem and the
+- * efivars subsystem with the efi subsystem, if the system was booted with
+- * EFI.
+- */
+-static int __init efisubsys_init(void)
++static int __init efipostcore_init(void)
+ {
+-      int error;
+-
+       if (!efi_enabled(EFI_RUNTIME_SERVICES))
+               efi.runtime_supported_mask = 0;
+-      if (!efi_enabled(EFI_BOOT))
+-              return 0;
+-
+       if (efi.runtime_supported_mask) {
+               /*
+                * Since we process only one efi_runtime_service() at a time, an
+@@ -413,9 +403,23 @@ static int __init efisubsys_init(void)
+                       pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
+                       clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+                       efi.runtime_supported_mask = 0;
+-                      return 0;
+               }
+       }
++      return 0;
++}
++postcore_initcall(efipostcore_init);
++
++/*
++ * We register the efi subsystem with the firmware subsystem and the
++ * efivars subsystem with the efi subsystem, if the system was booted with
++ * EFI.
++ */
++static int __init efisubsys_init(void)
++{
++      int error;
++
++      if (!efi_enabled(EFI_BOOT))
++              return 0;
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_TIME_SERVICES))
+               platform_device_register_simple("rtc-efi", 0, NULL, 0);
diff --git a/queue-6.12/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch b/queue-6.12/hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch
new file mode 100644 (file)
index 0000000..a5192d3
--- /dev/null
@@ -0,0 +1,51 @@
+From eee213daa1e1b402eb631bcd1b8c5aa340a6b081 Mon Sep 17 00:00:00 2001
+From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+Date: Fri, 15 May 2026 15:11:48 -0700
+Subject: hwmon: (pmbus/adm1266) widen blackbox-info buffer to I2C_SMBUS_BLOCK_MAX
+
+From: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+
+commit eee213daa1e1b402eb631bcd1b8c5aa340a6b081 upstream.
+
+adm1266_nvmem_read_blackbox() declares a 5-byte stack buffer and
+passes it to i2c_smbus_read_block_data() to retrieve the 4-byte
+BLACKBOX_INFO response.  i2c_smbus_read_block_data() does not honour
+caller buffer sizes -- it memcpy()s data.block[0] bytes from the
+SMBus transaction (where data.block[0] is the length byte returned by
+the slave device, up to I2C_SMBUS_BLOCK_MAX = 32):
+
+       memcpy(values, &data.block[1], data.block[0]);
+
+If the device returns any block length above 5, the call overflows
+the caller's 5-byte stack buffer before the post-call
+
+       if (ret != 4)
+               return -EIO;
+
+check has a chance to reject the response.
+
+Widen the local buffer to I2C_SMBUS_BLOCK_MAX so the helper has room
+for any well-formed SMBus block response, matching the convention used
+by the other i2c_smbus_read_block_data() callers in this driver.
+
+Fixes: 15609d189302 ("hwmon: (pmbus/adm1266) read blackbox")
+Cc: stable@vger.kernel.org
+Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
+Link: https://lore.kernel.org/r/20260515-adm1266-fixes-v1-2-1c1ea1349cfe@nexthop.ai
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwmon/pmbus/adm1266.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hwmon/pmbus/adm1266.c
++++ b/drivers/hwmon/pmbus/adm1266.c
+@@ -349,7 +349,7 @@ static int adm1266_nvmem_read_blackbox(s
+ {
+       int record_count;
+       char index;
+-      u8 buf[5];
++      u8 buf[I2C_SMBUS_BLOCK_MAX];
+       int ret;
+       ret = i2c_smbus_read_block_data(data->client, ADM1266_BLACKBOX_INFO, buf);
diff --git a/queue-6.12/io_uring-waitid-clear-waitid-info-before-copying-it-to-userspace.patch b/queue-6.12/io_uring-waitid-clear-waitid-info-before-copying-it-to-userspace.patch
new file mode 100644 (file)
index 0000000..2891d44
--- /dev/null
@@ -0,0 +1,41 @@
+From 93d93f5f8da791e98159795c6ef683f45bd95d13 Mon Sep 17 00:00:00 2001
+From: Heechan Kang <gganji11@naver.com>
+Date: Sun, 17 May 2026 03:47:09 +0900
+Subject: io_uring/waitid: clear waitid info before copying it to userspace
+
+From: Heechan Kang <gganji11@naver.com>
+
+commit 93d93f5f8da791e98159795c6ef683f45bd95d13 upstream.
+
+IORING_OP_WAITID stores its result fields in struct io_waitid::info and
+later copies them to userspace siginfo. The prep path initializes the
+request arguments, but it does not initialize info itself.
+
+If the wait operation completes without reporting a child event, the common
+wait code can return without writing wo_info. In that case io_waitid_finish()
+still copies iw->info to userspace, exposing stale bytes from the reused
+io_kiocb command storage.
+
+Clear the result storage during prep so the io_uring path matches the
+regular waitid syscall, which uses a zero-initialized struct waitid_info.
+
+Fixes: f31ecf671ddc ("io_uring: add IORING_OP_WAITID support")
+Cc: stable@vger.kernel.org # 6.7+
+Signed-off-by: Heechan Kang <gganji11@naver.com>
+Link: https://patch.msgid.link/20260516184709.852814-1-gganji11@naver.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/waitid.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/io_uring/waitid.c
++++ b/io_uring/waitid.c
+@@ -294,6 +294,7 @@ int io_waitid_prep(struct io_kiocb *req,
+       iw->upid = READ_ONCE(sqe->fd);
+       iw->options = READ_ONCE(sqe->file_index);
+       iw->infop = u64_to_user_ptr(READ_ONCE(sqe->addr2));
++      memset(&iw->info, 0, sizeof(iw->info));
+       return 0;
+ }
diff --git a/queue-6.12/ipv6-ioam-refresh-hdr-pointer-before-ioam6_event.patch b/queue-6.12/ipv6-ioam-refresh-hdr-pointer-before-ioam6_event.patch
new file mode 100644 (file)
index 0000000..065524d
--- /dev/null
@@ -0,0 +1,62 @@
+From e46e6bc97fb1f339730ff1ba74267fbf48e7a422 Mon Sep 17 00:00:00 2001
+From: Justin Iurman <justin.iurman@gmail.com>
+Date: Wed, 20 May 2026 14:42:42 +0200
+Subject: ipv6: ioam: refresh hdr pointer before ioam6_event()
+
+From: Justin Iurman <justin.iurman@gmail.com>
+
+commit e46e6bc97fb1f339730ff1ba74267fbf48e7a422 upstream.
+
+Reported by Sashiko:
+
+In ipv6_hop_ioam(), the hdr pointer is initialized to point into the
+skb's linear data buffer. Later, the code calls skb_ensure_writable(),
+which might reallocate the buffer:
+
+       if (skb_ensure_writable(skb, optoff + 2 + hdr->opt_len))
+               goto drop;
+
+       /* Trace pointer may have changed */
+       trace = (struct ioam6_trace_hdr *)(skb_network_header(skb)
+                                          + optoff + sizeof(*hdr));
+
+       ioam6_fill_trace_data(skb, ns, trace, true);
+
+       ioam6_event(IOAM6_EVENT_TRACE, dev_net(skb->dev),
+                   GFP_ATOMIC, (void *)trace, hdr->opt_len - 2);
+
+If the skb is cloned or lacks sufficient linear headroom,
+skb_ensure_writable() will invoke pskb_expand_head(), which reallocates
+the skb's data buffer and frees the old one, invalidating pointers to
+it. While the code recalculates the trace pointer immediately after the
+call to skb_ensure_writable(), it fails to recalculate the hdr pointer.
+
+This patch fixes the above by recalculating the hdr pointer before
+passing hdr->opt_len to ioam6_event(), so that we avoid any UaF.
+
+Fixes: f655c78d6225 ("net: exthdrs: ioam6: send trace event")
+Cc: stable@vger.kernel.org
+Signed-off-by: Justin Iurman <justin.iurman@gmail.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260520124242.32320-1-justin.iurman@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/exthdrs.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -957,9 +957,9 @@ static bool ipv6_hop_ioam(struct sk_buff
+               if (skb_ensure_writable(skb, optoff + 2 + hdr->opt_len))
+                       goto drop;
+-              /* Trace pointer may have changed */
+-              trace = (struct ioam6_trace_hdr *)(skb_network_header(skb)
+-                                                 + optoff + sizeof(*hdr));
++              /* Trace and hdr pointers may have changed */
++              hdr = (struct ioam6_hdr *)(skb_network_header(skb) + optoff);
++              trace = (struct ioam6_trace_hdr *)((u8 *)hdr + sizeof(*hdr));
+               ioam6_fill_trace_data(skb, ns, trace, true);
diff --git a/queue-6.12/ksmbd-fix-null-pointer-dereference-in-compare_guid_key.patch b/queue-6.12/ksmbd-fix-null-pointer-dereference-in-compare_guid_key.patch
new file mode 100644 (file)
index 0000000..a542a53
--- /dev/null
@@ -0,0 +1,73 @@
+From 4b83cbc4c15f09b000cc06f033f64b0824b6dc87 Mon Sep 17 00:00:00 2001
+From: Jeremy Laratro <research@aradex.io>
+Date: Wed, 13 May 2026 08:26:16 +0900
+Subject: ksmbd: fix null pointer dereference in compare_guid_key()
+
+From: Jeremy Laratro <research@aradex.io>
+
+commit 4b83cbc4c15f09b000cc06f033f64b0824b6dc87 upstream.
+
+session_fd_check() walks the per-inode m_op_list during durable-handle
+session teardown and sets op->conn = NULL for every opinfo whose conn
+matched the closing session's connection. The matching opinfo, however,
+stays linked in its per-ClientGuid lease_table_list entry's lb->lease_list
+because destroy_lease_table() only runs on full TCP-connection teardown,
+not on SESSION_LOGOFF.
+
+If the same TCP connection then negotiates a fresh session with the
+same ClientGuid (ClientGuid is bound to NEGOTIATE, not the session, and
+is unchanged across LOGOFF + SETUP) and issues a SMB2 CREATE with a
+lease context on a different inode, find_same_lease_key() walks
+lb->lease_list, reaches the stale opinfo, and calls compare_guid_key(),
+which unconditionally dereferences opinfo->conn->ClientGUID. The conn
+pointer is NULL and the kernel panics.
+
+Reproducer requires only a successful SMB2 SESSION_SETUP and a share
+configured with 'durable handles = yes'. KASAN report on mainline
+70390501d194:
+
+  general protection fault, probably for non-canonical address
+  0xdffffc0000000069: 0000 [#1] SMP KASAN PTI
+  KASAN: null-ptr-deref in range [0x0000000000000348-0x000000000000034f]
+  Workqueue: ksmbd-io handle_ksmbd_work
+  RIP: 0010:bcmp+0x5b/0x230
+  Call Trace:
+   compare_guid_key+0x4b/0xd0
+   find_same_lease_key+0x324/0x690
+   smb2_open+0x6aea/0x8e60
+   handle_ksmbd_work+0x796/0xee0
+   ...
+
+Faulting address 0x348 is the offset of ClientGUID within struct
+ksmbd_conn, confirming opinfo->conn was NULL.
+
+Read opinfo->conn once and bail out if it has been cleared by a
+concurrent session_fd_check(). A half-detached opinfo cannot be the
+owner of an active lease, so returning 0 is the correct match result.
+
+Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jeremy Laratro <research@aradex.io>
+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/oplock.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -484,8 +484,12 @@ static inline int compare_guid_key(struc
+                                  const char *guid1, const char *key1)
+ {
+       const char *guid2, *key2;
++      struct ksmbd_conn *conn;
+-      guid2 = opinfo->conn->ClientGUID;
++      conn = READ_ONCE(opinfo->conn);
++      if (!conn)
++              return 0;
++      guid2 = conn->ClientGUID;
+       key2 = opinfo->o_lease->lease_key;
+       if (!memcmp(guid1, guid2, SMB2_CLIENT_GUID_SIZE) &&
+           !memcmp(key1, key2, SMB2_LEASE_KEY_SIZE))
diff --git a/queue-6.12/ksmbd-fix-sid-memory-leak-in-set_posix_acl_entries_dacl-on-overflow.patch b/queue-6.12/ksmbd-fix-sid-memory-leak-in-set_posix_acl_entries_dacl-on-overflow.patch
new file mode 100644 (file)
index 0000000..367b366
--- /dev/null
@@ -0,0 +1,76 @@
+From af92ee994cc7f7e83a41c2025f32257a2f82a7ef Mon Sep 17 00:00:00 2001
+From: Ferry Meng <mengferry@linux.alibaba.com>
+Date: Mon, 11 May 2026 21:18:16 +0800
+Subject: ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow
+
+From: Ferry Meng <mengferry@linux.alibaba.com>
+
+commit af92ee994cc7f7e83a41c2025f32257a2f82a7ef upstream.
+
+Commit 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16
+DACL size overflow") added check_add_overflow() guards that break out
+of the ACE-building loops in set_posix_acl_entries_dacl() when the
+accumulated DACL size would wrap past 65535.
+
+However, each iteration allocates a struct smb_sid via kmalloc_obj()
+at the top of the loop and relies on the kfree(sid) call at the end
+of the loop body (the 'pass_same_sid' label in the first loop, and
+the explicit kfree at the tail of the second loop) to release it.
+The newly introduced 'break' statements bypass those kfree() calls,
+leaking the sid buffer every time an overflow is detected.
+
+A malicious or malformed file with enough POSIX ACL entries to trip
+the overflow check will leak one or more struct smb_sid allocations
+on every request that touches the file's DACL, providing a trivial
+kernel memory exhaustion vector.
+
+Free sid before breaking out of the loops to plug the leak.
+
+Fixes: 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ferry Meng <mengferry@linux.alibaba.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 |   12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/fs/smb/server/smbacl.c
++++ b/fs/smb/server/smbacl.c
+@@ -643,8 +643,10 @@ static void set_posix_acl_entries_dacl(s
+               ntace = (struct smb_ace *)((char *)pndace + *size);
+               ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
+                               pace->e_perm, 0777);
+-              if (check_add_overflow(*size, ace_sz, size))
++              if (check_add_overflow(*size, ace_sz, size)) {
++                      kfree(sid);
+                       break;
++              }
+               (*num_aces)++;
+               if (pace->e_tag == ACL_USER)
+                       ntace->access_req |=
+@@ -655,8 +657,10 @@ static void set_posix_acl_entries_dacl(s
+                       ntace = (struct smb_ace *)((char *)pndace + *size);
+                       ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
+                                       0x03, pace->e_perm, 0777);
+-                      if (check_add_overflow(*size, ace_sz, size))
++                      if (check_add_overflow(*size, ace_sz, size)) {
++                              kfree(sid);
+                               break;
++                      }
+                       (*num_aces)++;
+                       if (pace->e_tag == ACL_USER)
+                               ntace->access_req |=
+@@ -698,8 +702,10 @@ posix_default_acl:
+               ntace = (struct smb_ace *)((char *)pndace + *size);
+               ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
+                               pace->e_perm, 0777);
+-              if (check_add_overflow(*size, ace_sz, size))
++              if (check_add_overflow(*size, ace_sz, size)) {
++                      kfree(sid);
+                       break;
++              }
+               (*num_aces)++;
+               if (pace->e_tag == ACL_USER)
+                       ntace->access_req |=
diff --git a/queue-6.12/ksmbd-validate-sid-in-parent-security-descriptor-during-acl-inheritance.patch b/queue-6.12/ksmbd-validate-sid-in-parent-security-descriptor-during-acl-inheritance.patch
new file mode 100644 (file)
index 0000000..23fa849
--- /dev/null
@@ -0,0 +1,130 @@
+From 69f030cf95488ae1186c72ac8c66fd279664ea7f Mon Sep 17 00:00:00 2001
+From: Junyi Liu <moss80199@gmail.com>
+Date: Tue, 19 May 2026 16:12:04 +0900
+Subject: ksmbd: validate SID in parent security descriptor during ACL inheritance
+
+From: Junyi Liu <moss80199@gmail.com>
+
+commit 69f030cf95488ae1186c72ac8c66fd279664ea7f upstream.
+
+Introduce smb_validate_ntsd_sid() helper to safely validate Owner SID
+and Group SID inside the NT Security Descriptor (smb_ntsd) retrieved
+from the parent directory.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Junyi Liu <moss80199@gmail.com>
+Signed-off-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 |   66 +++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 50 insertions(+), 16 deletions(-)
+
+--- a/fs/smb/server/smbacl.c
++++ b/fs/smb/server/smbacl.c
+@@ -1096,6 +1096,40 @@ static int smb_append_inherited_ace(stru
+       return 0;
+ }
++static int smb_validate_ntsd_sid(struct smb_ntsd *pntsd, size_t pntsd_size,
++                                unsigned int sid_offset, struct smb_sid **sid,
++                                size_t *sid_size)
++{
++      size_t sid_end;
++
++      *sid = NULL;
++      *sid_size = 0;
++
++      if (!sid_offset)
++              return 0;
++
++      if (sid_offset < sizeof(struct smb_ntsd) ||
++          check_add_overflow(sid_offset, (size_t)CIFS_SID_BASE_SIZE,
++                             &sid_end) ||
++          sid_end > pntsd_size)
++              return -EINVAL;
++
++      *sid = (struct smb_sid *)((char *)pntsd + sid_offset);
++      if ((*sid)->num_subauth > SID_MAX_SUB_AUTHORITIES)
++              return -EINVAL;
++
++      if (check_add_overflow((size_t)CIFS_SID_BASE_SIZE,
++                             sizeof(__le32) * (size_t)(*sid)->num_subauth,
++                             &sid_end))
++              return -EINVAL;
++
++      if (sid_offset > pntsd_size || sid_end > pntsd_size - sid_offset)
++              return -EINVAL;
++
++      *sid_size = sid_end;
++      return 0;
++}
++
+ int smb_inherit_dacl(struct ksmbd_conn *conn,
+                    const struct path *path,
+                    unsigned int uid, unsigned int gid)
+@@ -1108,28 +1142,28 @@ int smb_inherit_dacl(struct ksmbd_conn *
+       struct dentry *parent = path->dentry->d_parent;
+       struct mnt_idmap *idmap = mnt_idmap(path->mnt);
+       int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size;
+-      int rc = 0, pntsd_type, pntsd_size, acl_len, aces_size;
++      int rc = 0, pntsd_type, ppntsd_size, acl_len, aces_size;
+       unsigned int dacloffset;
+       size_t dacl_struct_end;
+       u16 num_aces, ace_cnt = 0;
+       char *aces_base;
+       bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
+-      pntsd_size = ksmbd_vfs_get_sd_xattr(conn, idmap,
++      ppntsd_size = ksmbd_vfs_get_sd_xattr(conn, idmap,
+                                           parent, &parent_pntsd);
+-      if (pntsd_size <= 0)
++      if (ppntsd_size <= 0)
+               return -ENOENT;
+       dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
+       if (!dacloffset ||
+           check_add_overflow(dacloffset, sizeof(struct smb_acl), &dacl_struct_end) ||
+-          dacl_struct_end > (size_t)pntsd_size) {
++          dacl_struct_end > (size_t)ppntsd_size) {
+               rc = -EINVAL;
+               goto free_parent_pntsd;
+       }
+       parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
+-      acl_len = pntsd_size - dacloffset;
++      acl_len = ppntsd_size - dacloffset;
+       num_aces = le16_to_cpu(parent_pdacl->num_aces);
+       pntsd_type = le16_to_cpu(parent_pntsd->type);
+       pdacl_size = le16_to_cpu(parent_pdacl->size);
+@@ -1243,19 +1277,19 @@ pass:
+               struct smb_ntsd *pntsd;
+               struct smb_acl *pdacl;
+               struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
+-              int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
++              size_t powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
+               size_t pntsd_alloc_size;
+-              if (parent_pntsd->osidoffset) {
+-                      powner_sid = (struct smb_sid *)((char *)parent_pntsd +
+-                                      le32_to_cpu(parent_pntsd->osidoffset));
+-                      powner_sid_size = 1 + 1 + 6 + (powner_sid->num_subauth * 4);
+-              }
+-              if (parent_pntsd->gsidoffset) {
+-                      pgroup_sid = (struct smb_sid *)((char *)parent_pntsd +
+-                                      le32_to_cpu(parent_pntsd->gsidoffset));
+-                      pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
+-              }
++              rc = smb_validate_ntsd_sid(parent_pntsd, ppntsd_size,
++                                         le32_to_cpu(parent_pntsd->osidoffset),
++                                         &powner_sid, &powner_sid_size);
++              if (rc)
++                      goto free_aces_base;
++              rc = smb_validate_ntsd_sid(parent_pntsd, ppntsd_size,
++                                         le32_to_cpu(parent_pntsd->gsidoffset),
++                                         &pgroup_sid, &pgroup_sid_size);
++              if (rc)
++                      goto free_aces_base;
+               if (check_add_overflow(sizeof(struct smb_ntsd),
+                                      (size_t)powner_sid_size,
diff --git a/queue-6.12/mm-damon-sysfs-schemes-call-missing-mem_cgroup_iter_break.patch b/queue-6.12/mm-damon-sysfs-schemes-call-missing-mem_cgroup_iter_break.patch
new file mode 100644 (file)
index 0000000..85eaefd
--- /dev/null
@@ -0,0 +1,36 @@
+From d4e7b5c4cc353f154d5ab8bb2e1ce7714d77a6e9 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Sun, 26 Apr 2026 10:36:12 -0700
+Subject: mm/damon/sysfs-schemes: call missing mem_cgroup_iter_break()
+
+From: SeongJae Park <sj@kernel.org>
+
+commit d4e7b5c4cc353f154d5ab8bb2e1ce7714d77a6e9 upstream.
+
+damon_sysfs_memcg_path_to_id() breaks mem_cgroup_iter() loop without
+calling mem_cgroup_iter_break().  This leaks the cgroup reference.  Fix
+the issue by calling mem_cgroup_iter_break() before the break.
+
+The issue was discovered [1] by Sashiko.
+
+Link: https://lore.kernel.org/20260426173625.86521-1-sj@kernel.org
+Link: https://lore.kernel.org/20260423004148.74722-1-sj@kernel.org [1]
+Fixes: 29cbb9a13f05 ("mm/damon/sysfs-schemes: implement scheme filters")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.3.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/sysfs-schemes.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/mm/damon/sysfs-schemes.c
++++ b/mm/damon/sysfs-schemes.c
+@@ -1913,6 +1913,7 @@ static int damon_sysfs_memcg_path_to_id(
+               if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
+                       *id = mem_cgroup_id(memcg);
+                       found = true;
++                      mem_cgroup_iter_break(NULL, memcg);
+                       break;
+               }
+       }
diff --git a/queue-6.12/mm-memory_hotplug-fix-memory-block-reference-leak-on-remove.patch b/queue-6.12/mm-memory_hotplug-fix-memory-block-reference-leak-on-remove.patch
new file mode 100644 (file)
index 0000000..02d3566
--- /dev/null
@@ -0,0 +1,57 @@
+From 93866f55f7e292fe3d47d36c9efe5ee10213a06b Mon Sep 17 00:00:00 2001
+From: Muchun Song <songmuchun@bytedance.com>
+Date: Tue, 28 Apr 2026 16:52:17 +0800
+Subject: mm/memory_hotplug: fix memory block reference leak on remove
+
+From: Muchun Song <songmuchun@bytedance.com>
+
+commit 93866f55f7e292fe3d47d36c9efe5ee10213a06b upstream.
+
+Patch series "mm: Fix memory block leaks and locking", v2.
+
+This series fixes two memory block device reference leaks and one locking
+issue around the per-memory_block hwpoison counter.
+
+
+This patch (of 2):
+
+remove_memory_blocks_and_altmaps() looks up each memory block with
+find_memory_block(), which acquires a reference to the memory block
+device.
+
+That reference is never dropped on this path, resulting in a leaked device
+reference when removing memory blocks and their altmaps.  Drop the
+reference after retrieving mem->altmap and clearing mem->altmap, before
+removing the memory block device.
+
+Link: https://lore.kernel.org/20260428085219.1316047-1-songmuchun@bytedance.com
+Link: https://lore.kernel.org/20260428085219.1316047-2-songmuchun@bytedance.com
+Fixes: 6b8f0798b85a ("mm/memory_hotplug: split memmap_on_memory requests across memblocks")
+Signed-off-by: Muchun Song <songmuchun@bytedance.com>
+Acked-by: Oscar Salvador <osalvador@suse.de>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Cc: Danilo Krummrich <dakr@kernel.org>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "Huang, Ying" <huang.ying.caritas@gmail.com>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: "Rafael J. Wysocki" <rafael@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memory_hotplug.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1406,6 +1406,8 @@ static void remove_memory_blocks_and_alt
+               altmap = mem->altmap;
+               mem->altmap = NULL;
++              /* drop the ref. we got via find_memory_block() */
++              put_device(&mem->dev);
+               remove_memory_block_devices(cur_start, memblock_size);
diff --git a/queue-6.12/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch b/queue-6.12/net-bcmgenet-keep-rbuf-eee-pm-disabled.patch
new file mode 100644 (file)
index 0000000..0e59f62
--- /dev/null
@@ -0,0 +1,62 @@
+From 9a1730245e416d11ad5c0f2c100061d61cc43f60 Mon Sep 17 00:00:00 2001
+From: Nicolai Buchwitz <nb@tipi-net.de>
+Date: Wed, 20 May 2026 20:43:20 +0200
+Subject: net: bcmgenet: keep RBUF EEE/PM disabled
+
+From: Nicolai Buchwitz <nb@tipi-net.de>
+
+commit 9a1730245e416d11ad5c0f2c100061d61cc43f60 upstream.
+
+Setting RBUF_EEE_EN | RBUF_PM_EN in RBUF_ENERGY_CTRL breaks the RX
+path on GENET hardware once MAC EEE becomes active. RX traffic stops
+flowing while the link stays up and the usual descriptor/RX error
+counters remain quiet. In that state the MAC still accepts frames
+(rbuf_ovflow_cnt keeps climbing) but RBUF no longer forwards them to
+DMA, so rx_packets is no longer incremented at the netdev level. On
+some boards the corruption ends up as a paging fault in
+skb_release_data via bcmgenet_rx_poll on an LPI exit.
+
+Reproduced on Pi 4B (BCM2711 + BCM54213PE) and confirmed by Florian
+Fainelli on an internal Broadcom 4908-family board with the same crash
+signature. RBUF_PM_EN is not publicly documented.
+
+This shows up more often now that phy_support_eee() enables EEE by
+default, but it also affects older kernels as soon as TX LPI is
+turned on via ethtool, so it is not specific to recent changes.
+
+Always clear RBUF_EEE_EN | RBUF_PM_EN in bcmgenet_eee_enable_set so
+the bits stay off across resets. UMAC and TBUF setup is left alone so
+TX-side EEE keeps working.
+
+Link: https://github.com/raspberrypi/linux/issues/7304
+Fixes: 6ef398ea60d9 ("net: bcmgenet: add EEE support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20260520184320.652053-1-nb@tipi-net.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c |    9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -1325,13 +1325,12 @@ void bcmgenet_eee_enable_set(struct net_
+               reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
+       bcmgenet_writel(reg, priv->base + off);
+-      /* Do the same for thing for RBUF */
++      /* RBUF EEE/PM can break the RX path on GENET. Keep it disabled. */
+       reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL);
+-      if (enable)
+-              reg |= RBUF_EEE_EN | RBUF_PM_EN;
+-      else
++      if (reg & (RBUF_EEE_EN | RBUF_PM_EN)) {
+               reg &= ~(RBUF_EEE_EN | RBUF_PM_EN);
+-      bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL);
++              bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL);
++      }
+       if (!enable && priv->clk_eee_enabled) {
+               clk_disable_unprepare(priv->clk_eee);
diff --git a/queue-6.12/net-ifb-report-ethtool-stats-over-num_tx_queues.patch b/queue-6.12/net-ifb-report-ethtool-stats-over-num_tx_queues.patch
new file mode 100644 (file)
index 0000000..9770fe3
--- /dev/null
@@ -0,0 +1,101 @@
+From 5db89c99566fc4728cc92e941d8e1975711e24b5 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Wed, 13 May 2026 21:37:39 -0400
+Subject: net: ifb: report ethtool stats over num_tx_queues
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 5db89c99566fc4728cc92e941d8e1975711e24b5 upstream.
+
+ifb_dev_init() allocates dp->tx_private to dev->num_tx_queues
+entries via kzalloc_objs(*txp, dev->num_tx_queues). Both IFB
+per-queue RX and TX stats live in those entries: ifb_xmit() updates
+txp->rx_stats using the skb queue mapping, ifb_ri_tasklet() updates
+txp->tx_stats, and ifb_stats64() aggregates both over
+dev->num_tx_queues.
+
+The ethtool stats callbacks instead size and walk the per-queue
+stats with dev->real_num_rx_queues and dev->real_num_tx_queues. With
+an asymmetric device where the RX queue count exceeds the TX queue
+count, for example:
+
+    ip link add name ifb10 numtxqueues 1 numrxqueues 8 type ifb
+    ethtool -S ifb10
+
+ifb_get_ethtool_stats() indexes past the tx_private allocation and
+copies adjacent slab data through ETHTOOL_GSTATS.
+
+Use dev->num_tx_queues consistently for the stats strings, the
+stats count, and the stats data walks. This reports one RX stats
+group and one TX stats group for each backing ifb_q_private entry,
+which is the queue set IFB can actually populate.
+
+Reproduced under UML+KASAN at v7.1-rc2:
+
+  BUG: KASAN: slab-out-of-bounds in ifb_fill_stats_data+0x3c/0xae
+  Read of size 8 at addr 0000000062dbd228 by task ethtool/36
+  ifb_fill_stats_data+0x3c/0xae
+  ifb_get_ethtool_stats+0xc0/0x129
+  __dev_ethtool+0x1ca5/0x363c
+  dev_ethtool+0x123/0x1b3
+  dev_ioctl+0x56c/0x744
+  sock_do_ioctl+0x15f/0x1b2
+  sock_ioctl+0x4d5/0x50a
+  sys_ioctl+0xd8b/0xde9
+
+With the patch applied, the same UML+KASAN repro is silent and
+ethtool -S ifb10 reports only the stats backed by the single
+allocated tx_private entry.
+
+Fixes: a21ee5b2fcb8 ("net: ifb: support ethtools stats")
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Link: https://patch.msgid.link/20260514013739.3549624-1-michael.bommarito@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ifb.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ifb.c
++++ b/drivers/net/ifb.c
+@@ -211,12 +211,12 @@ static void ifb_get_strings(struct net_d
+       switch (stringset) {
+       case ETH_SS_STATS:
+-              for (i = 0; i < dev->real_num_rx_queues; i++)
++              for (i = 0; i < dev->num_tx_queues; i++)
+                       for (j = 0; j < IFB_Q_STATS_LEN; j++)
+                               ethtool_sprintf(&p, "rx_queue_%u_%.18s",
+                                               i, ifb_q_stats_desc[j].desc);
+-              for (i = 0; i < dev->real_num_tx_queues; i++)
++              for (i = 0; i < dev->num_tx_queues; i++)
+                       for (j = 0; j < IFB_Q_STATS_LEN; j++)
+                               ethtool_sprintf(&p, "tx_queue_%u_%.18s",
+                                               i, ifb_q_stats_desc[j].desc);
+@@ -229,8 +229,7 @@ static int ifb_get_sset_count(struct net
+ {
+       switch (sset) {
+       case ETH_SS_STATS:
+-              return IFB_Q_STATS_LEN * (dev->real_num_rx_queues +
+-                                        dev->real_num_tx_queues);
++              return IFB_Q_STATS_LEN * dev->num_tx_queues * 2;
+       default:
+               return -EOPNOTSUPP;
+       }
+@@ -262,12 +261,12 @@ static void ifb_get_ethtool_stats(struct
+       struct ifb_q_private *txp;
+       int i;
+-      for (i = 0; i < dev->real_num_rx_queues; i++) {
++      for (i = 0; i < dev->num_tx_queues; i++) {
+               txp = dp->tx_private + i;
+               ifb_fill_stats_data(&data, &txp->rx_stats);
+       }
+-      for (i = 0; i < dev->real_num_tx_queues; i++) {
++      for (i = 0; i < dev->num_tx_queues; i++) {
+               txp = dp->tx_private + i;
+               ifb_fill_stats_data(&data, &txp->tx_stats);
+       }
diff --git a/queue-6.12/net-pse-pd-fix-sign-on-enoent-check-in-of_load_pse_pis.patch b/queue-6.12/net-pse-pd-fix-sign-on-enoent-check-in-of_load_pse_pis.patch
new file mode 100644 (file)
index 0000000..b4fd08e
--- /dev/null
@@ -0,0 +1,41 @@
+From 33d35975cbead3fa6b738ee57e5e45e14fbe0886 Mon Sep 17 00:00:00 2001
+From: Jonas Jelonek <jelonek.jonas@gmail.com>
+Date: Fri, 15 May 2026 14:31:03 +0000
+Subject: net: pse-pd: fix sign on -ENOENT check in of_load_pse_pis()
+
+From: Jonas Jelonek <jelonek.jonas@gmail.com>
+
+commit 33d35975cbead3fa6b738ee57e5e45e14fbe0886 upstream.
+
+of_count_phandle_with_args() returns the count on success and a negative
+errno on failure, including -ENOENT when the "pairsets" property is
+absent. The existing comparison in of_load_pse_pis() checks against
+ENOENT (positive 2) instead of -ENOENT, so the branch is taken for any
+error return: legitimate DTs that omit "pairsets" trigger a spurious
+"wrong number of pairsets" error and probe fails with -EINVAL.
+
+Compare against -ENOENT so a missing "pairsets" property is correctly
+treated as "this PI has no pairsets, continue".
+
+Fixes: 9be9567a7c59 ("net: pse-pd: Add support for PSE PIs")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20260515143103.1721888-1-jelonek.jonas@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/pse-pd/pse_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/pse-pd/pse_core.c
++++ b/drivers/net/pse-pd/pse_core.c
+@@ -184,7 +184,7 @@ static int of_load_pse_pis(struct pse_co
+                       ret = of_load_pse_pi_pairsets(node, &pi, ret);
+                       if (ret)
+                               goto out;
+-              } else if (ret != ENOENT) {
++              } else if (ret != -ENOENT) {
+                       dev_err(pcdev->dev,
+                               "error: wrong number of pairsets. Should be 1 or 2, got %d (%pOF)\n",
+                               ret, node);
diff --git a/queue-6.12/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch b/queue-6.12/net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch
new file mode 100644 (file)
index 0000000..d841b92
--- /dev/null
@@ -0,0 +1,34 @@
+From c5d93b2c40355e999715262a824965aac025a427 Mon Sep 17 00:00:00 2001
+From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+Date: Tue, 19 May 2026 11:57:39 +0530
+Subject: net: wwan: iosm: fix potential memory leaks in ipc_imem_init()
+
+From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+
+commit c5d93b2c40355e999715262a824965aac025a427 upstream.
+
+The memory allocated in ipc_protocol_init() is not freed on the error
+paths that follow in ipc_imem_init(). Fix that by calling the
+corresponding release function ipc_protocol_deinit() in the error path.
+
+Fixes: 3670970dd8c6 ("net: iosm: shared memory IPC interface")
+Cc: stable@vger.kernel.org
+Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+Link: https://patch.msgid.link/20260519062815.55545-1-nihaal@cse.iitm.ac.in
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wwan/iosm/iosm_ipc_imem.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wwan/iosm/iosm_ipc_imem.c
++++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c
+@@ -1430,6 +1430,8 @@ imem_config_fail:
+ protocol_init_fail:
+       cancel_work_sync(&ipc_imem->run_state_worker);
+       ipc_task_deinit(ipc_imem->ipc_task);
++      if (ipc_imem->ipc_protocol)
++              ipc_protocol_deinit(ipc_imem->ipc_protocol);
+ ipc_task_init_fail:
+       kfree(ipc_imem->ipc_task);
+ ipc_task_fail:
diff --git a/queue-6.12/netfilter-ip6t_hbh-reject-oversized-option-lists.patch b/queue-6.12/netfilter-ip6t_hbh-reject-oversized-option-lists.patch
new file mode 100644 (file)
index 0000000..89f34c5
--- /dev/null
@@ -0,0 +1,51 @@
+From 4322dcde6b4173c2d8e8e6118ed290794263bcc8 Mon Sep 17 00:00:00 2001
+From: Zhengchuan Liang <zcliangcn@gmail.com>
+Date: Wed, 13 May 2026 15:57:17 +0800
+Subject: netfilter: ip6t_hbh: reject oversized option lists
+
+From: Zhengchuan Liang <zcliangcn@gmail.com>
+
+commit 4322dcde6b4173c2d8e8e6118ed290794263bcc8 upstream.
+
+struct ip6t_opts stores at most IP6T_OPTS_OPTSNR option descriptors,
+but hbh_mt6_check() does not reject larger optsnr values supplied from
+userspace.
+
+Validate optsnr in the rule setup path so only match data that fits the
+fixed-size opts array can be installed. This follows the existing xtables
+pattern of rejecting invalid user-provided counts in checkentry() and
+keeps the packet matching path unchanged.
+
+`struct ip6t_opts` has a fixed `opts[IP6T_OPTS_OPTSNR]` array,
+where `IP6T_OPTS_OPTSNR` is 16, then off-by-one array access is possible:
+
+[  137.924693][ T8692] UBSAN: array-index-out-of-bounds in ../net/ipv6/netfilter/ip6t_hbh.c:110:29
+[  137.926167][ T8692] index 16 is out of range for type '__u16 [16]'
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/netfilter/ip6t_hbh.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/ipv6/netfilter/ip6t_hbh.c
++++ b/net/ipv6/netfilter/ip6t_hbh.c
+@@ -168,6 +168,10 @@ static int hbh_mt6_check(const struct xt
+               pr_debug("unknown flags %X\n", optsinfo->invflags);
+               return -EINVAL;
+       }
++      if (optsinfo->optsnr > IP6T_OPTS_OPTSNR) {
++              pr_debug("too many supported opts specified\n");
++              return -EINVAL;
++      }
+       if (optsinfo->flags & IP6T_OPTS_NSTRICT) {
+               pr_debug("Not strict - not implemented");
diff --git a/queue-6.12/netfilter-ipset-stop-hash-range-iteration-at-end.patch b/queue-6.12/netfilter-ipset-stop-hash-range-iteration-at-end.patch
new file mode 100644 (file)
index 0000000..1e328a5
--- /dev/null
@@ -0,0 +1,130 @@
+From 0d3a282ab5f165fc207ff49ea5b6ad8f54616bd6 Mon Sep 17 00:00:00 2001
+From: Nan Li <tonanli66@gmail.com>
+Date: Tue, 12 May 2026 16:50:01 +0800
+Subject: netfilter: ipset: stop hash:* range iteration at end
+
+From: Nan Li <tonanli66@gmail.com>
+
+commit 0d3a282ab5f165fc207ff49ea5b6ad8f54616bd6 upstream.
+
+The following hash set variants:
+
+hash:ip,mark
+hash:ip,port
+hash:ip,port,ip
+hash:ip,port,net
+
+iterate IPv4 ranges with a 32-bit iterator.
+
+The iterator must stop once the last address in the requested range has
+been processed. Advancing it once more can move the traversal state past
+the end of the request, so a later retry may continue from an unintended
+position.
+
+Handle the iterator increment explicitly at the end of the loop and stop
+once the upper bound has been processed. This keeps the existing retry
+behaviour intact for valid ranges while preventing traversal from
+continuing past the original boundary.
+
+Fixes: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Nan Li <tonanli66@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/ipset/ip_set_hash_ipmark.c    |    6 +++++-
+ net/netfilter/ipset/ip_set_hash_ipport.c    |    5 ++++-
+ net/netfilter/ipset/ip_set_hash_ipportip.c  |    5 ++++-
+ net/netfilter/ipset/ip_set_hash_ipportnet.c |    5 ++++-
+ 4 files changed, 17 insertions(+), 4 deletions(-)
+
+--- a/net/netfilter/ipset/ip_set_hash_ipmark.c
++++ b/net/netfilter/ipset/ip_set_hash_ipmark.c
+@@ -150,7 +150,7 @@ hash_ipmark4_uadt(struct ip_set *set, st
+       if (retried)
+               ip = ntohl(h->next.ip);
+-      for (; ip <= ip_to; ip++, i++) {
++      for (; ip <= ip_to; i++) {
+               e.ip = htonl(ip);
+               if (i > IPSET_MAX_RANGE) {
+                       hash_ipmark4_data_next(&h->next, &e);
+@@ -162,6 +162,10 @@ hash_ipmark4_uadt(struct ip_set *set, st
+                       return ret;
+               ret = 0;
++
++              if (ip == ip_to)
++                      break;
++              ip++;
+       }
+       return ret;
+ }
+--- a/net/netfilter/ipset/ip_set_hash_ipport.c
++++ b/net/netfilter/ipset/ip_set_hash_ipport.c
+@@ -186,7 +186,7 @@ hash_ipport4_uadt(struct ip_set *set, st
+       if (retried)
+               ip = ntohl(h->next.ip);
+-      for (; ip <= ip_to; ip++) {
++      for (; ip <= ip_to;) {
+               p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
+                                                      : port;
+               for (; p <= port_to; p++, i++) {
+@@ -203,6 +203,9 @@ hash_ipport4_uadt(struct ip_set *set, st
+                       ret = 0;
+               }
++              if (ip == ip_to)
++                      break;
++              ip++;
+       }
+       return ret;
+ }
+--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
++++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
+@@ -182,7 +182,7 @@ hash_ipportip4_uadt(struct ip_set *set,
+       if (retried)
+               ip = ntohl(h->next.ip);
+-      for (; ip <= ip_to; ip++) {
++      for (; ip <= ip_to;) {
+               p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
+                                                      : port;
+               for (; p <= port_to; p++, i++) {
+@@ -199,6 +199,9 @@ hash_ipportip4_uadt(struct ip_set *set,
+                       ret = 0;
+               }
++              if (ip == ip_to)
++                      break;
++              ip++;
+       }
+       return ret;
+ }
+--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
++++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
+@@ -274,7 +274,7 @@ hash_ipportnet4_uadt(struct ip_set *set,
+               p = port;
+               ip2 = ip2_from;
+       }
+-      for (; ip <= ip_to; ip++) {
++      for (; ip <= ip_to;) {
+               e.ip = htonl(ip);
+               for (; p <= port_to; p++) {
+                       e.port = htons(p);
+@@ -298,6 +298,9 @@ hash_ipportnet4_uadt(struct ip_set *set,
+                       ip2 = ip2_from;
+               }
+               p = port;
++              if (ip == ip_to)
++                      break;
++              ip++;
+       }
+       return ret;
+ }
diff --git a/queue-6.12/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch b/queue-6.12/netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch
new file mode 100644 (file)
index 0000000..0046e9b
--- /dev/null
@@ -0,0 +1,90 @@
+From e196115ec330a18de415bdb9f5071aa9f08e53ce Mon Sep 17 00:00:00 2001
+From: Haoze Xie <royenheart@gmail.com>
+Date: Fri, 15 May 2026 11:19:02 +0800
+Subject: netfilter: nf_queue: hold bridge skb->dev while queued
+
+From: Haoze Xie <royenheart@gmail.com>
+
+commit e196115ec330a18de415bdb9f5071aa9f08e53ce upstream.
+
+br_pass_frame_up() rewrites skb->dev from the ingress port to the bridge
+master before queueing bridge LOCAL_IN packets. NFQUEUE only holds
+references on state.in/out and bridge physdevs, so a queued bridge
+packet can retain a freed bridge master in skb->dev until reinjection.
+
+When the verdict is reinjected later, br_netif_receive_skb() re-enters
+the receive path with skb->dev still pointing at the freed bridge master,
+triggering a use-after-free.
+
+Store skb->dev in the queue entry, hold a reference on it for the queue
+lifetime, and use the saved device when dropping queued packets during
+NETDEV_DOWN handling.
+
+Fixes: ac2863445686 ("netfilter: bridge: add nf_afinfo to enable queuing to userspace")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Haoze Xie <royenheart@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/netfilter/nf_queue.h |    1 +
+ net/netfilter/nf_queue.c         |    4 +++-
+ net/netfilter/nfnetlink_queue.c  |    2 ++
+ 3 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/include/net/netfilter/nf_queue.h
++++ b/include/net/netfilter/nf_queue.h
+@@ -14,6 +14,7 @@ struct nf_queue_entry {
+       struct list_head        list;
+       struct rhash_head       hash_node;
+       struct sk_buff          *skb;
++      struct net_device       *skb_dev;
+       unsigned int            id;
+       unsigned int            hook_index;     /* index in hook_entries->hook[] */
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+--- a/net/netfilter/nf_queue.c
++++ b/net/netfilter/nf_queue.c
+@@ -60,6 +60,7 @@ static void nf_queue_entry_release_refs(
+       struct nf_hook_state *state = &entry->state;
+       /* Release those devices we held, or Alexey will kill me. */
++      dev_put(entry->skb_dev);
+       dev_put(state->in);
+       dev_put(state->out);
+       if (state->sk)
+@@ -101,6 +102,7 @@ bool nf_queue_entry_get_refs(struct nf_q
+       if (state->sk && !refcount_inc_not_zero(&state->sk->sk_refcnt))
+               return false;
++      dev_hold(entry->skb_dev);
+       dev_hold(state->in);
+       dev_hold(state->out);
+@@ -201,11 +203,11 @@ static int __nf_queue(struct sk_buff *sk
+       *entry = (struct nf_queue_entry) {
+               .skb    = skb,
++              .skb_dev = skb->dev,
+               .state  = *state,
+               .hook_index = index,
+               .size   = sizeof(*entry) + route_key_size,
+       };
+-
+       __nf_queue_entry_init_physdevs(entry);
+       if (!nf_queue_entry_get_refs(entry)) {
+--- a/net/netfilter/nfnetlink_queue.c
++++ b/net/netfilter/nfnetlink_queue.c
+@@ -1196,6 +1196,8 @@ dev_cmp(struct nf_queue_entry *entry, un
+       if (physinif == ifindex || physoutif == ifindex)
+               return 1;
+ #endif
++      if (entry->skb_dev && entry->skb_dev->ifindex == ifindex)
++              return 1;
+       if (entry->state.in)
+               if (entry->state.in->ifindex == ifindex)
+                       return 1;
diff --git a/queue-6.12/netfilter-nft_inner-fix-ipv6-inner_thoff-desync.patch b/queue-6.12/netfilter-nft_inner-fix-ipv6-inner_thoff-desync.patch
new file mode 100644 (file)
index 0000000..6fffe13
--- /dev/null
@@ -0,0 +1,53 @@
+From b6a91f68ebfed9c38e0e9150f58a9b85da07181c Mon Sep 17 00:00:00 2001
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Date: Tue, 12 May 2026 01:30:41 +0800
+Subject: netfilter: nft_inner: Fix IPv6 inner_thoff desync
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+
+commit b6a91f68ebfed9c38e0e9150f58a9b85da07181c upstream.
+
+In nft_inner_parse_l2l3(), when processing inner IPv6 packets,
+ipv6_find_hdr() correctly computes the transport header offset
+traversing all extension headers, but the result is immediately
+overwritten with nhoff + sizeof(_ip6h) (40 bytes), which only
+accounts for the IPv6 base header. This creates a desync between
+inner_thoff (wrong — points to extension header start) and l4proto
+(correct — e.g., IPPROTO_TCP), enabling transport header forgery
+and potential firewall bypass. This issue affects stable versions
+from Linux 6.2.
+
+For comparison, the normal (non-inner) IPv6 path correctly
+preserves ipv6_find_hdr()'s result. Removing the incorrect overwrite
+ensures that ipv6_find_hdr()'s calculated transport header offset is
+preserved, thereby fixing the desynchronization.
+
+Fixes: 3a07327d10a0 ("netfilter: nft_inner: support for inner tunnel header matching")
+Cc: stable@vger.kernel.org
+Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
+Reported-by: Xuewei Feng <fengxw06@126.com>
+Reported-by: Qi Li <qli01@tsinghua.edu.cn>
+Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
+Assisted-by: GLM:5.1 Z.ai
+Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/nft_inner.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/net/netfilter/nft_inner.c
++++ b/net/netfilter/nft_inner.c
+@@ -156,7 +156,6 @@ static int nft_inner_parse_l2l3(const st
+                       return -1;
+               if (fragoff == 0) {
+-                      thoff = nhoff + sizeof(_ip6h);
+                       ctx->flags |= NFT_PAYLOAD_CTX_INNER_TH;
+                       ctx->inner_thoff = thoff;
+                       ctx->l4proto = l4proto;
diff --git a/queue-6.12/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch b/queue-6.12/phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch
new file mode 100644 (file)
index 0000000..ebcd607
--- /dev/null
@@ -0,0 +1,105 @@
+From dbc81608e3a653dea6cf403f20cae35468b8ab9c Mon Sep 17 00:00:00 2001
+From: Zijing Yin <yzjaurora@gmail.com>
+Date: Tue, 19 May 2026 10:26:33 -0700
+Subject: phonet/pep: disable BH around forwarded sk_receive_skb()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zijing Yin <yzjaurora@gmail.com>
+
+commit dbc81608e3a653dea6cf403f20cae35468b8ab9c upstream.
+
+The networking receive path is usually run from softirq context, but
+protocols that take the socket lock may have packets stored in the
+backlog and processed later from process context. In that case
+release_sock() -> __release_sock() drops the slock with spin_unlock_bh()
+and then calls sk->sk_backlog_rcv() with bottom halves enabled.
+
+Typical sk_backlog_rcv handlers process the socket whose backlog is
+being drained, so the BH state at entry is irrelevant for the slocks
+they touch. pep_do_rcv() is different: when the inbound skb targets an
+existing PEP pipe, it forwards the skb to a different *child* socket
+via sk_receive_skb(). That helper takes the child slock with
+bh_lock_sock_nested(), which is just spin_lock_nested() and assumes BH
+is already off. The same child slock therefore ends up acquired with
+BH on (process path) and with BH off (softirq path):
+
+  process context                   softirq context
+  ---------------                   ---------------
+  release_sock(listener)            __netif_receive_skb()
+   __release_sock()                  phonet_rcv()
+    spin_unlock_bh()                  __sk_receive_skb(listener)
+    [BH now ENABLED]                  [BH already disabled]
+    sk_backlog_rcv:                   sk_backlog_rcv:
+     pep_do_rcv()                      pep_do_rcv()
+      sk_receive_skb(child)             sk_receive_skb(child)
+       bh_lock_sock_nested(child)        bh_lock_sock_nested(child)
+       => SOFTIRQ-ON-W                   => IN-SOFTIRQ-W
+
+Lockdep flags this as inconsistent lock state, and it can become a real
+self-deadlock if a softirq on the same CPU tries to receive to the same
+child socket while its slock is held in the BH-enabled path:
+
+  WARNING: inconsistent lock state
+  inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
+   (slock-AF_PHONET/1){+.?.}-{3:3}, at: __sk_receive_skb+0x1cf/0x900
+    __sk_receive_skb              net/core/sock.c:563
+    sk_receive_skb                include/net/sock.h:2022 [inline]
+    pep_do_rcv                    net/phonet/pep.c:675
+    sk_backlog_rcv                include/net/sock.h:1190
+    __release_sock                net/core/sock.c:3216
+    release_sock                  net/core/sock.c:3815
+    pep_sock_accept               net/phonet/pep.c:879
+
+Wrap the forwarded sk_receive_skb() in local_bh_disable() /
+local_bh_enable() so the child slock is always acquired with BH off.
+local_bh_disable() nests safely on the softirq path.
+
+Discovered via in-house syzkaller fuzzing; the same root cause also
+on the linux-6.1.y syzbot dashboard as extid 44f0626dd6284f02663c.
+Reproduced under KASAN + LOCKDEP + PROVE_LOCKING, reproducer:
+https://pastebin.com/A3t8xzCR
+
+Fixes: 9641458d3ec4 ("Phonet: Pipe End Point for Phonet Pipes protocol")
+Link: https://syzkaller.appspot.com/bug?extid=44f0626dd6284f02663c
+Cc: stable@vger.kernel.org
+Signed-off-by: Zijing Yin <yzjaurora@gmail.com>
+Acked-by: Rémi Denis-Courmont <remi@remlab.net>
+Reported-by: syzbot+9f4a135646b66c509935@syzkaller.appspotmail.com
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260519172635.86304-1-yzjaurora@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/phonet/pep.c |   19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+--- a/net/phonet/pep.c
++++ b/net/phonet/pep.c
+@@ -671,8 +671,23 @@ static int pep_do_rcv(struct sock *sk, s
+       /* Look for an existing pipe handle */
+       sknode = pep_find_pipe(&pn->hlist, &dst, pipe_handle);
+-      if (sknode)
+-              return sk_receive_skb(sknode, skb, 1);
++      if (sknode) {
++              int rc;
++
++              /* pep_do_rcv() runs from two contexts: from softirq via
++               * phonet_rcv() -> __sk_receive_skb() with BH disabled,
++               * and from process context via
++               * release_sock() -> __release_sock(), which drops
++               * the listener slock with spin_unlock_bh() before draining
++               * the backlog.  The child pipe slock is taken below via
++               * bh_lock_sock_nested(), which does not itself disable BH, so
++               * disable BH here to keep both acquire contexts consistent.
++               */
++              local_bh_disable();
++              rc = sk_receive_skb(sknode, skb, 1);
++              local_bh_enable();
++              return rc;
++      }
+       switch (hdr->message_id) {
+       case PNS_PEP_CONNECT_REQ:
diff --git a/queue-6.12/selftests-mm-run_vmtests.sh-fix-destructive-tests-invocation.patch b/queue-6.12/selftests-mm-run_vmtests.sh-fix-destructive-tests-invocation.patch
new file mode 100644 (file)
index 0000000..3265048
--- /dev/null
@@ -0,0 +1,43 @@
+From 3432cbb291aabf85f8af4b9d1ec37179168ff999 Mon Sep 17 00:00:00 2001
+From: Luiz Capitulino <luizcap@redhat.com>
+Date: Mon, 27 Apr 2026 12:03:51 -0400
+Subject: selftests/mm: run_vmtests.sh: fix destructive tests invocation
+
+From: Luiz Capitulino <luizcap@redhat.com>
+
+commit 3432cbb291aabf85f8af4b9d1ec37179168ff999 upstream.
+
+Destructive tests should be invoked with -d command-line option, but this
+won't work today since 'd' is missing in getopts command-line.  This
+commit fixes it.
+
+Link: https://lore.kernel.org/214fd9e4-5398-4c26-859e-c982c2e277c3@redhat.com
+Fixes: f16ff3b692ad ("selftests/mm: run_vmtests.sh: add missing tests")
+Signed-off-by: Luiz Capitulino <luizcap@redhat.com>
+Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/mm/run_vmtests.sh |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/testing/selftests/mm/run_vmtests.sh
++++ b/tools/testing/selftests/mm/run_vmtests.sh
+@@ -85,7 +85,7 @@ RUN_ALL=false
+ RUN_DESTRUCTIVE=false
+ TAP_PREFIX="# "
+-while getopts "aht:n" OPT; do
++while getopts "aht:nd" OPT; do
+       case ${OPT} in
+               "a") RUN_ALL=true ;;
+               "h") usage ;;
index 44e259ab5415042855d4ae526e1c42e6f2c9a1fd..6de5135af154ced6541b6af22cf471a65d8edb68 100644 (file)
@@ -39,3 +39,38 @@ riscv-fgraph-fix-stack-layout-to-match-__arch_ftrace.patch
 hwmon-pmbus-core-protect-regulator-operations-with-m.patch
 arm64-kconfig-remove-selecting-replaced-have_functio.patch
 i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in.patch
+sysfs-don-t-remove-existing-directory-on-update-failure.patch
+mm-damon-sysfs-schemes-call-missing-mem_cgroup_iter_break.patch
+ksmbd-fix-null-pointer-dereference-in-compare_guid_key.patch
+ksmbd-fix-sid-memory-leak-in-set_posix_acl_entries_dacl-on-overflow.patch
+ksmbd-validate-sid-in-parent-security-descriptor-during-acl-inheritance.patch
+smb-client-require-net-admin-for-cifs-swn-netlink.patch
+smb-client-protect-tc_count-increment-in-smb2_find_smb_sess_tcon_unlocked.patch
+smb-client-use-data_len-for-smb2-read-encrypted-folioq-copy.patch
+smb-server-promote-s_del_on_cls-to-s_del_pending-when-close.patch
+hwmon-pmbus-adm1266-widen-blackbox-info-buffer-to-i2c_smbus_block_max.patch
+alsa-ua101-reject-too-short-usb-descriptors.patch
+alsa-pcm-don-t-setup-bogus-iov_iter-for-silencing.patch
+alsa-asihpi-fix-potential-oob-array-access-at-reading-cache.patch
+efi-allocate-runtime-workqueue-before-acpi-init.patch
+io_uring-waitid-clear-waitid-info-before-copying-it-to-userspace.patch
+drivers-base-memory-fix-memory-block-reference-leak-in-poison-accounting.patch
+ipv6-ioam-refresh-hdr-pointer-before-ioam6_event.patch
+mm-memory_hotplug-fix-memory-block-reference-leak-on-remove.patch
+selftests-mm-run_vmtests.sh-fix-destructive-tests-invocation.patch
+net-wwan-iosm-fix-potential-memory-leaks-in-ipc_imem_init.patch
+bluetooth-fix-uaf-in-l2cap_sock_cleanup_listen-vs-l2cap_conn_del.patch
+bluetooth-iso-drop-iso_end-frames-received-without-prior-iso_start.patch
+bluetooth-bnep-fix-uaf-read-of-dev-name.patch
+bluetooth-hci_uart-fix-uafs-and-race-conditions-in-close-and-init-paths.patch
+bluetooth-l2cap-ecred_reconfigure-send-packed-pdu-not-stack-pointer.patch
+bluetooth-mgmt-validate-add-extended-advertising-data-length.patch
+bluetooth-serialize-accept_q-access.patch
+phonet-pep-disable-bh-around-forwarded-sk_receive_skb.patch
+net-bcmgenet-keep-rbuf-eee-pm-disabled.patch
+net-ifb-report-ethtool-stats-over-num_tx_queues.patch
+net-pse-pd-fix-sign-on-enoent-check-in-of_load_pse_pis.patch
+netfilter-ip6t_hbh-reject-oversized-option-lists.patch
+netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch
+netfilter-ipset-stop-hash-range-iteration-at-end.patch
+netfilter-nft_inner-fix-ipv6-inner_thoff-desync.patch
diff --git a/queue-6.12/smb-client-protect-tc_count-increment-in-smb2_find_smb_sess_tcon_unlocked.patch b/queue-6.12/smb-client-protect-tc_count-increment-in-smb2_find_smb_sess_tcon_unlocked.patch
new file mode 100644 (file)
index 0000000..9e81602
--- /dev/null
@@ -0,0 +1,38 @@
+From 4d8690dace005a38e6dbde9ecce2da3ad85c7c41 Mon Sep 17 00:00:00 2001
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+Date: Thu, 14 May 2026 20:18:25 -0300
+Subject: smb: client: protect tc_count increment in smb2_find_smb_sess_tcon_unlocked()
+
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+
+commit 4d8690dace005a38e6dbde9ecce2da3ad85c7c41 upstream.
+
+Commit 96c4af418586 ("cifs: Fix locking usage for tcon fields")
+refactored cifs code to change cifs_tcp_ses_lock for tc_lock around
+tc_count changes.
+
+There was missing lock around tc_count increment inside
+smb2_find_smb_sess_tcon_unlocked().
+
+Cc: stable@vger.kernel.org
+Fixes: 96c4af418586 ("cifs: Fix locking usage for tcon fields")
+Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/smb2transport.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/smb/client/smb2transport.c
++++ b/fs/smb/client/smb2transport.c
+@@ -214,7 +214,9 @@ smb2_find_smb_sess_tcon_unlocked(struct
+       list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+               if (tcon->tid != tid)
+                       continue;
++              spin_lock(&tcon->tc_lock);
+               ++tcon->tc_count;
++              spin_unlock(&tcon->tc_lock);
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_get_find_sess_tcon);
+               return tcon;
diff --git a/queue-6.12/smb-client-require-net-admin-for-cifs-swn-netlink.patch b/queue-6.12/smb-client-require-net-admin-for-cifs-swn-netlink.patch
new file mode 100644 (file)
index 0000000..109e19f
--- /dev/null
@@ -0,0 +1,58 @@
+From d1ebfce2c1d161186a82e77590bf7da2ea1bce91 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Sun, 17 May 2026 20:11:50 -0400
+Subject: smb: client: require net admin for CIFS SWN netlink
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit d1ebfce2c1d161186a82e77590bf7da2ea1bce91 upstream.
+
+CIFS_GENL_CMD_SWN_NOTIFY is the userspace witness-notify command.  The
+intended sender is the cifs.witness helper, but the generic-netlink
+operation currently has no capability flag, so any local process can send
+RESOURCE_CHANGE or CLIENT_MOVE notifications to the in-kernel witness
+handler.
+
+The same family exposes CIFS_GENL_MCGRP_SWN without multicast-group
+capability flags.  Register messages sent to that group include the witness
+registration id and, for NTLM-authenticated mounts, the username, domain,
+and password attributes copied from the CIFS session.  An unprivileged
+local process should not be able to join that group and receive those
+messages.
+
+Require CAP_NET_ADMIN for incoming SWN_NOTIFY commands with
+GENL_ADMIN_PERM, and require CAP_NET_ADMIN over the network namespace for
+joining the SWN multicast group with GENL_MCAST_CAP_NET_ADMIN.  The
+cifs.witness service runs with the privileges needed for both operations.
+
+Fixes: fed979a7e082 ("cifs: Set witness notification handler for messages from userspace daemon")
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/netlink.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/fs/smb/client/netlink.c
++++ b/fs/smb/client/netlink.c
+@@ -33,13 +33,17 @@ static const struct nla_policy cifs_genl
+ static const struct genl_ops cifs_genl_ops[] = {
+       {
+               .cmd = CIFS_GENL_CMD_SWN_NOTIFY,
++              .flags = GENL_ADMIN_PERM,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+               .doit = cifs_swn_notify,
+       },
+ };
+ static const struct genl_multicast_group cifs_genl_mcgrps[] = {
+-      [CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
++      [CIFS_GENL_MCGRP_SWN] = {
++              .name = CIFS_GENL_MCGRP_SWN_NAME,
++              .flags = GENL_MCAST_CAP_NET_ADMIN,
++      },
+ };
+ struct genl_family cifs_genl_family = {
diff --git a/queue-6.12/smb-client-use-data_len-for-smb2-read-encrypted-folioq-copy.patch b/queue-6.12/smb-client-use-data_len-for-smb2-read-encrypted-folioq-copy.patch
new file mode 100644 (file)
index 0000000..be78eb9
--- /dev/null
@@ -0,0 +1,79 @@
+From d4d76c9ee1997cc8c977a63f6c43551c253c1066 Mon Sep 17 00:00:00 2001
+From: Jeremy Erazo <mendozayt13@gmail.com>
+Date: Fri, 15 May 2026 19:31:41 +0000
+Subject: smb: client: use data_len for SMB2 READ encrypted folioq copy
+
+From: Jeremy Erazo <mendozayt13@gmail.com>
+
+commit d4d76c9ee1997cc8c977a63f6c43551c253c1066 upstream.
+
+In handle_read_data() the encrypted/folioq branch
+(buf_len <= data_offset, reached via receive_encrypted_read for
+transform PDUs > CIFSMaxBufSize + MAX_HEADER_SIZE) copies the READ
+payload using buffer_len rather than data_len:
+
+       rdata->result = cifs_copy_folioq_to_iter(buffer, buffer_len,
+                                                cur_off,
+                                                &rdata->subreq.io_iter);
+       ...
+       rdata->got_bytes = buffer_len;
+
+buffer_len comes from the SMB3 transform header OriginalMessageSize
+field (OriginalMessageSize - read_rsp_size); it represents the size
+of the decrypted message after the SMB2 header.  data_len comes from
+the SMB2 READ response DataLength field; it represents the actual
+READ payload size and may be smaller than buffer_len when the
+decrypted message contains padding or other trailing bytes after the
+READ payload.  The existing check `data_len > buffer_len - pad_len`
+only enforces an upper bound, so a server that emits
+OriginalMessageSize larger than read_rsp_size + pad_len + data_len
+passes the check and the kernel copies buffer_len bytes per response,
+ignoring the server-asserted DataLength.
+
+Two observable failures with a crafted server (DataLength=4,
+buffer_len=20000):
+
+  - the kernel returns 20000 bytes per sub-request to userspace and
+    sets got_bytes = buffer_len, even though the response claimed
+    only 4 bytes of payload;
+
+  - on a partial netfs sub-request whose iterator is sized to
+    data_len, the over-large copy_folio_to_iter() short-reads,
+    cifs_copy_folioq_to_iter() returns -EIO via the n != len path,
+    and the entire netfs read collapses to -EIO even though the
+    leading sub-requests succeeded.
+
+Use data_len for the copy length and for got_bytes so the kernel
+honours the server-asserted READ payload size.  For well-formed
+servers (where buffer_len == pad_len + data_len) the change is
+behaviour-equivalent.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Jeremy Erazo <mendozayt13@gmail.com>
+Acked-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/smb2ops.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -4781,7 +4781,7 @@ handle_read_data(struct TCP_Server_Info
+               }
+               /* Copy the data to the output I/O iterator. */
+-              rdata->result = cifs_copy_folioq_to_iter(buffer, buffer_len,
++              rdata->result = cifs_copy_folioq_to_iter(buffer, data_len,
+                                                        cur_off, &rdata->subreq.io_iter);
+               if (rdata->result != 0) {
+                       if (is_offloaded)
+@@ -4790,7 +4790,7 @@ handle_read_data(struct TCP_Server_Info
+                               dequeue_mid(mid, rdata->result);
+                       return 0;
+               }
+-              rdata->got_bytes = buffer_len;
++              rdata->got_bytes = data_len;
+       } else if (buf_len >= data_offset + data_len) {
+               /* read response payload is in buf */
diff --git a/queue-6.12/smb-server-promote-s_del_on_cls-to-s_del_pending-when-close.patch b/queue-6.12/smb-server-promote-s_del_on_cls-to-s_del_pending-when-close.patch
new file mode 100644 (file)
index 0000000..e1de135
--- /dev/null
@@ -0,0 +1,76 @@
+From 4ec9c8e023c79f613fe4d5ad8cc737112efb2e44 Mon Sep 17 00:00:00 2001
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Date: Mon, 18 May 2026 15:23:22 +0000
+Subject: smb/server: promote S_DEL_ON_CLS to S_DEL_PENDING when close
+
+From: ChenXiaoSong <chenxiaosong@kylinos.cn>
+
+commit 4ec9c8e023c79f613fe4d5ad8cc737112efb2e44 upstream.
+
+Reproducer:
+
+  1. server: systemctl start ksmbd
+  2. client: mount -t cifs //${server_ip}/export /mnt
+  3. client: C program: openat(AT_FDCWD, "/mnt", O_RDWR | O_TMPFILE, 0600)
+
+Do not treat `FILE_DELETE_ON_CLOSE_LE` as delete pending while files
+remain open.
+
+This patch fixes xfstests generic/004.
+
+Cc: stable@vger.kernel.org
+Link: https://chenxiaosong.com/en/smb-xfstests-generic-004.html
+Co-developed-by: Huiwen He <hehuiwen@kylinos.cn>
+Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
+Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Tested-by: Steve French <stfrench@microsoft.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/vfs_cache.c |   16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/fs/smb/server/vfs_cache.c
++++ b/fs/smb/server/vfs_cache.c
+@@ -118,7 +118,7 @@ int ksmbd_query_inode_status(struct dent
+               return ret;
+       down_read(&ci->m_lock);
+-      if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS))
++      if (ci->m_flags & S_DEL_PENDING)
+               ret = KSMBD_INODE_STATUS_PENDING_DELETE;
+       else
+               ret = KSMBD_INODE_STATUS_OK;
+@@ -134,7 +134,7 @@ bool ksmbd_inode_pending_delete(struct k
+       int ret;
+       down_read(&ci->m_lock);
+-      ret = (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS));
++      ret = (ci->m_flags & S_DEL_PENDING);
+       up_read(&ci->m_lock);
+       return ret;
+@@ -302,12 +302,20 @@ static void __ksmbd_inode_close(struct k
+               }
+       }
++      down_write(&ci->m_lock);
++      /* Promote S_DEL_ON_CLS to S_DEL_PENDING when close */
++      if (ci->m_flags & S_DEL_ON_CLS) {
++              ci->m_flags &= ~S_DEL_ON_CLS;
++              ci->m_flags |= S_DEL_PENDING;
++      }
++      up_write(&ci->m_lock);
++
+       if (atomic_dec_and_test(&ci->m_count)) {
+               bool do_unlink = false;
+               down_write(&ci->m_lock);
+-              if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
+-                      ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
++              if (ci->m_flags & S_DEL_PENDING) {
++                      ci->m_flags &= ~S_DEL_PENDING;
+                       do_unlink = true;
+               }
+               up_write(&ci->m_lock);
diff --git a/queue-6.12/sysfs-don-t-remove-existing-directory-on-update-failure.patch b/queue-6.12/sysfs-don-t-remove-existing-directory-on-update-failure.patch
new file mode 100644 (file)
index 0000000..5675392
--- /dev/null
@@ -0,0 +1,43 @@
+From 237557b8a81ab948e8332f7c0058e758f081c0a3 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Wed, 20 May 2026 15:05:04 +0200
+Subject: sysfs: don't remove existing directory on update failure
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit 237557b8a81ab948e8332f7c0058e758f081c0a3 upstream.
+
+When sysfs_update_group() is called for a named group and create_files()
+fails (e.g. -ENOMEM), internal_create_group() calls kernfs_remove(kn) on
+the group directory.  In the update path, kn was obtained via
+kernfs_find_and_get() and refers to a directory that already existed
+before this call.  Removing it silently destroys a sysfs group that the
+caller did not create.
+
+Only remove the directory if we created it ourselves.  On update failure
+the directory remains as it is left empty by remove_files() inside
+create_files(), but can be repopulated by a retry.
+
+Cc: Rajat Jain <rajatja@google.com>
+Fixes: c855cf2759d2 ("sysfs: Fix internal_create_group() for named group updates")
+Cc: stable <stable@kernel.org>
+Assisted-by: gkh_clanker_t1000
+Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
+Reviewed-by: Danilo Krummrich <dakr@kernel.org>
+Link: https://patch.msgid.link/2026052003-uniquely-hastily-c093@gregkh
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/sysfs/group.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/sysfs/group.c
++++ b/fs/sysfs/group.c
+@@ -179,7 +179,7 @@ static int internal_create_group(struct
+       kernfs_get(kn);
+       error = create_files(kn, kobj, uid, gid, grp, update);
+       if (error) {
+-              if (grp->name)
++              if (grp->name && !update)
+                       kernfs_remove(kn);
+       }
+       kernfs_put(kn);