]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 Jun 2026 05:06:08 +0000 (10:36 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 Jun 2026 05:06:08 +0000 (10:36 +0530)
added patches:
alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch
hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch
iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch
iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch
iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch
iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch
memfd-deny-writeable-mappings-when-implying-seal_write.patch
mm-hugetlb-rename-folio_putback_active_hugetlb-to-folio_putback_hugetlb.patch
mm-hugetlb-rename-isolate_hugetlb-to-folio_isolate_hugetlb.patch
mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch
mm-memory-failure-fix-missing-mf_stats-count-in-hugetlb-poison.patch
mm-migrate-don-t-call-folio_putback_active_hugetlb-on-dst-hugetlb-folio.patch
netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch
rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch
rdma-move-dma-block-iterator-logic-into-dedicated-files.patch
rdma-umem-fix-kernel-doc-warnings.patch
rdma-umem-fix-truncation-for-block-sizes-4g.patch
scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch
serial-qcom_geni-fix-kfifo-underflow-when-flush-precedes-dma-completion-irq.patch
serial-samsung_tty-use-port-lock-wrappers.patch
thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch
tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch
tty-serial-samsung-use-u32-for-register-interactions.patch
usb-cdns3-plat-fix-leaked-usb2_phy-initialization-on-usb3_phy-acquisition-failure.patch
usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch
usb-gadget-uvc-hold-opts-lock-across-xu-walks-in-uvc_function_bind.patch
usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch
usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch
usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch

30 files changed:
queue-6.6/alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch [new file with mode: 0644]
queue-6.6/hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch [new file with mode: 0644]
queue-6.6/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch [new file with mode: 0644]
queue-6.6/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch [new file with mode: 0644]
queue-6.6/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch [new file with mode: 0644]
queue-6.6/iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch [new file with mode: 0644]
queue-6.6/memfd-deny-writeable-mappings-when-implying-seal_write.patch [new file with mode: 0644]
queue-6.6/mm-hugetlb-rename-folio_putback_active_hugetlb-to-folio_putback_hugetlb.patch [new file with mode: 0644]
queue-6.6/mm-hugetlb-rename-isolate_hugetlb-to-folio_isolate_hugetlb.patch [new file with mode: 0644]
queue-6.6/mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch [new file with mode: 0644]
queue-6.6/mm-memory-failure-fix-missing-mf_stats-count-in-hugetlb-poison.patch [new file with mode: 0644]
queue-6.6/mm-migrate-don-t-call-folio_putback_active_hugetlb-on-dst-hugetlb-folio.patch [new file with mode: 0644]
queue-6.6/netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch [new file with mode: 0644]
queue-6.6/rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch [new file with mode: 0644]
queue-6.6/rdma-move-dma-block-iterator-logic-into-dedicated-files.patch [new file with mode: 0644]
queue-6.6/rdma-umem-fix-kernel-doc-warnings.patch [new file with mode: 0644]
queue-6.6/rdma-umem-fix-truncation-for-block-sizes-4g.patch [new file with mode: 0644]
queue-6.6/scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch [new file with mode: 0644]
queue-6.6/serial-qcom_geni-fix-kfifo-underflow-when-flush-precedes-dma-completion-irq.patch [new file with mode: 0644]
queue-6.6/serial-samsung_tty-use-port-lock-wrappers.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch [new file with mode: 0644]
queue-6.6/tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch [new file with mode: 0644]
queue-6.6/tty-serial-samsung-use-u32-for-register-interactions.patch [new file with mode: 0644]
queue-6.6/usb-cdns3-plat-fix-leaked-usb2_phy-initialization-on-usb3_phy-acquisition-failure.patch [new file with mode: 0644]
queue-6.6/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch [new file with mode: 0644]
queue-6.6/usb-gadget-uvc-hold-opts-lock-across-xu-walks-in-uvc_function_bind.patch [new file with mode: 0644]
queue-6.6/usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch [new file with mode: 0644]
queue-6.6/usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch [new file with mode: 0644]

diff --git a/queue-6.6/alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch b/queue-6.6/alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch
new file mode 100644 (file)
index 0000000..d6367a2
--- /dev/null
@@ -0,0 +1,74 @@
+From stable+bounces-260602-greg=kroah.com@vger.kernel.org Fri Jun  5 07:15:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 21:31:06 -0400
+Subject: ALSA: firewire-motu: Protect register DSP event queue positions
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Takashi Sakamoto" <o-takashi@sakamocchi.jp>, "Takashi Iwai" <tiwai@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260605013107.2963134-1-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit 98fb1c1bb11e29eb609b7200a25e136e05aa4498 ]
+
+The register DSP event queue is updated under parser->lock, but
+snd_motu_register_dsp_message_parser_count_event() reads pull_pos and
+push_pos without the lock.
+snd_motu_register_dsp_message_parser_copy_event() also reads both queue
+positions before taking the lock.
+
+Protect these accesses with parser->lock as well. This keeps the hwdep
+poll/read path consistent with the producer side and with the cached
+meter/parameter accessors.
+
+Fixes: 634ec0b2906e ("ALSA: firewire-motu: notify event for parameter change in register DSP model")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260521-alsa-firewire-motu-event-locking-v1-1-708e1c2b5e56@gmail.com
+[ converted copy_event() from manual spin_lock_irqsave/spin_unlock_irqrestore to guard(spinlock_irqsave) ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/firewire/motu/motu-register-dsp-message-parser.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
++++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
+@@ -393,6 +393,8 @@ unsigned int snd_motu_register_dsp_messa
+ {
+       struct msg_parser *parser = motu->message_parser;
++      guard(spinlock_irqsave)(&parser->lock);
++
+       if (parser->pull_pos > parser->push_pos)
+               return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
+       else
+@@ -402,14 +404,14 @@ unsigned int snd_motu_register_dsp_messa
+ bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
+ {
+       struct msg_parser *parser = motu->message_parser;
+-      unsigned int pos = parser->pull_pos;
+-      unsigned long flags;
++      unsigned int pos;
+-      if (pos == parser->push_pos)
+-              return false;
++      guard(spinlock_irqsave)(&parser->lock);
+-      spin_lock_irqsave(&parser->lock, flags);
++      if (parser->pull_pos == parser->push_pos)
++              return false;
++      pos = parser->pull_pos;
+       *event = parser->event_queue[pos];
+       ++pos;
+@@ -417,7 +419,5 @@ bool snd_motu_register_dsp_message_parse
+               pos = 0;
+       parser->pull_pos = pos;
+-      spin_unlock_irqrestore(&parser->lock, flags);
+-
+       return true;
+ }
diff --git a/queue-6.6/hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch b/queue-6.6/hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch
new file mode 100644 (file)
index 0000000..038577e
--- /dev/null
@@ -0,0 +1,92 @@
+From stable+bounces-263425-greg=kroah.com@vger.kernel.org Mon Jun 15 23:38:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 14:08:00 -0400
+Subject: hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf
+To: stable@vger.kernel.org
+Cc: Anton Leontev <leontyevantony@gmail.com>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615180800.2317919-1-sashal@kernel.org>
+
+From: Anton Leontev <leontyevantony@gmail.com>
+
+[ Upstream commit 004e9ecfe6c5384f9e0b2f6f6389d42ec22789af ]
+
+netvsc_copy_to_send_buf() copies page buffer entries into the VMBus
+send buffer using phys_to_virt() on the entry PFN. Entries for the
+RNDIS header and the skb linear data come from kmalloc'd memory and
+are always in the kernel direct map, but entries for skb fragments
+reference page cache or user pages, which on 32-bit x86 with
+CONFIG_HIGHMEM=y can live above the LOWMEM boundary. For such a page
+phys_to_virt() returns an address outside the direct map and the
+subsequent memcpy() faults on the transmit softirq path, which is
+fatal.
+
+Map the pages with kmap_local_page() instead, handling two properties
+of the page buffer entries:
+
+ - pb[i].pfn is a Hyper-V PFN at HV_HYP_PAGE_SIZE (4K) granularity,
+   not a native PFN. Reconstruct the physical address first and derive
+   the native page from it, so the mapping stays correct where
+   PAGE_SIZE > HV_HYP_PAGE_SIZE (e.g. arm64 with 64K pages).
+
+ - Since commit 41a6328b2c55 ("hv_netvsc: Preserve contiguous PFN
+   grouping in the page buffer array"), an entry describes a full
+   physically contiguous fragment and pb[i].len can exceed PAGE_SIZE,
+   while kmap_local_page() maps a single page. Copy page by page,
+   splitting at native page boundaries.
+
+The copy path only handles packets smaller than the send section size
+(6144 bytes by default); larger packets take the cp_partial path where
+only the RNDIS header is copied. So entries here are bounded by the
+section size and a copy is split at most once on 4K-page systems. On
+!CONFIG_HIGHMEM configs kmap_local_page() folds to page_address() and
+no mapping work is added.
+
+Fixes: c25aaf814a63 ("hyperv: Enable sendbuf mechanism on the send path")
+Cc: stable@vger.kernel.org
+Signed-off-by: Anton Leontev <leontyevantony@gmail.com>
+Link: https://patch.msgid.link/20260604165938.32033-1-leontyevantony@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted `phys_to_page(paddr)` to `pfn_to_page(PHYS_PFN(paddr))` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/hyperv/netvsc.c |   19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/hyperv/netvsc.c
++++ b/drivers/net/hyperv/netvsc.c
+@@ -12,6 +12,7 @@
+ #include <linux/sched.h>
+ #include <linux/wait.h>
+ #include <linux/mm.h>
++#include <linux/highmem.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
+@@ -957,12 +958,22 @@ static void netvsc_copy_to_send_buf(stru
+       }
+       for (i = 0; i < page_count; i++) {
+-              char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT);
+-              u32 offset = pb[i].offset;
++              phys_addr_t paddr = (pb[i].pfn << HV_HYP_PAGE_SHIFT) +
++                                  pb[i].offset;
+               u32 len = pb[i].len;
+-              memcpy(dest, (src + offset), len);
+-              dest += len;
++              while (len) {
++                      struct page *page = pfn_to_page(PHYS_PFN(paddr));
++                      u32 off = offset_in_page(paddr);
++                      u32 chunk = min_t(u32, len, PAGE_SIZE - off);
++                      char *src = kmap_local_page(page);
++
++                      memcpy(dest, src + off, chunk);
++                      kunmap_local(src);
++                      dest += chunk;
++                      paddr += chunk;
++                      len -= chunk;
++              }
+       }
+       if (padding)
diff --git a/queue-6.6/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch b/queue-6.6/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch
new file mode 100644 (file)
index 0000000..c17e703
--- /dev/null
@@ -0,0 +1,38 @@
+From stable+bounces-260560-greg=kroah.com@vger.kernel.org Fri Jun  5 00:33:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 14:57:11 -0400
+Subject: iio: chemical: scd30: fix division by zero in write_raw
+To: stable@vger.kernel.org
+Cc: Antoniu Miclaus <antoniu.miclaus@analog.com>, Stable@vger.kernel.org, Jonathan Cameron <jic23@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604185711.605210-2-sashal@kernel.org>
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+[ Upstream commit 5aba4f94b225617a55fed442a70329b2ee19c0a5 ]
+
+Add a zero check for val2 before using it as a divisor when setting the
+sampling frequency. A user writing a zero fractional part to the
+sampling_frequency sysfs attribute triggers a division by zero in the
+kernel.
+
+Fixes: 64b3d8b1b0f5 ("iio: chemical: scd30: add core driver")
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/chemical/scd30_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iio/chemical/scd30_core.c
++++ b/drivers/iio/chemical/scd30_core.c
+@@ -257,7 +257,7 @@ static int scd30_write_raw(struct iio_de
+       guard(mutex)(&state->lock);
+       switch (mask) {
+       case IIO_CHAN_INFO_SAMP_FREQ:
+-              if (val)
++              if (val || !val2)
+                       return -EINVAL;
+               val = 1000000000 / val2;
diff --git a/queue-6.6/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch b/queue-6.6/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch
new file mode 100644 (file)
index 0000000..3488535
--- /dev/null
@@ -0,0 +1,178 @@
+From stable+bounces-260559-greg=kroah.com@vger.kernel.org Fri Jun  5 00:32:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 14:57:10 -0400
+Subject: iio: chemical: scd30: Use guard(mutex) to allow early returns
+To: stable@vger.kernel.org
+Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>, David Lechner <dlechner@baylibre.com>, Tomasz Duszynski <tomasz.duszynski@octakon.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604185711.605210-1-sashal@kernel.org>
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 5feb5532870fbced5d6f450b8061a33f461b88ca ]
+
+Auto cleanup based release of the lock allows for simpler code flow in a
+few functions with large multiplexing style switch statements and no
+common operations following the switch.
+
+Suggested-by: David Lechner <dlechner@baylibre.com>
+Cc: Tomasz Duszynski <tomasz.duszynski@octakon.com>
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Link: https://patch.msgid.link/20250209180624.701140-3-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 5aba4f94b225 ("iio: chemical: scd30: fix division by zero in write_raw")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/chemical/scd30_core.c |   63 ++++++++++++++++----------------------
+ 1 file changed, 28 insertions(+), 35 deletions(-)
+
+--- a/drivers/iio/chemical/scd30_core.c
++++ b/drivers/iio/chemical/scd30_core.c
+@@ -5,6 +5,7 @@
+  * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>
+  */
+ #include <linux/bits.h>
++#include <linux/cleanup.h>
+ #include <linux/completion.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
+@@ -198,112 +199,104 @@ static int scd30_read_raw(struct iio_dev
+                         int *val, int *val2, long mask)
+ {
+       struct scd30_state *state = iio_priv(indio_dev);
+-      int ret = -EINVAL;
++      int ret;
+       u16 tmp;
+-      mutex_lock(&state->lock);
++      guard(mutex)(&state->lock);
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+       case IIO_CHAN_INFO_PROCESSED:
+               if (chan->output) {
+                       *val = state->pressure_comp;
+-                      ret = IIO_VAL_INT;
+-                      break;
++                      return IIO_VAL_INT;
+               }
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+-                      break;
++                      return ret;
+               ret = scd30_read(state);
+               if (ret) {
+                       iio_device_release_direct_mode(indio_dev);
+-                      break;
++                      return ret;
+               }
+               *val = state->meas[chan->address];
+               iio_device_release_direct_mode(indio_dev);
+-              ret = IIO_VAL_INT;
+-              break;
++              return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               *val = 0;
+               *val2 = 1;
+-              ret = IIO_VAL_INT_PLUS_MICRO;
+-              break;
++              return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               ret = scd30_command_read(state, CMD_MEAS_INTERVAL, &tmp);
+               if (ret)
+-                      break;
++                      return ret;
+               *val = 0;
+               *val2 = 1000000000 / tmp;
+-              ret = IIO_VAL_INT_PLUS_NANO;
+-              break;
++              return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               ret = scd30_command_read(state, CMD_TEMP_OFFSET, &tmp);
+               if (ret)
+-                      break;
++                      return ret;
+               *val = tmp;
+-              ret = IIO_VAL_INT;
+-              break;
++              return IIO_VAL_INT;
++      default:
++              return -EINVAL;
+       }
+-      mutex_unlock(&state->lock);
+-
+-      return ret;
+ }
+ static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                          int val, int val2, long mask)
+ {
+       struct scd30_state *state = iio_priv(indio_dev);
+-      int ret = -EINVAL;
++      int ret;
+-      mutex_lock(&state->lock);
++      guard(mutex)(&state->lock);
+       switch (mask) {
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               if (val)
+-                      break;
++                      return -EINVAL;
+               val = 1000000000 / val2;
+               if (val < SCD30_MEAS_INTERVAL_MIN_S || val > SCD30_MEAS_INTERVAL_MAX_S)
+-                      break;
++                      return -EINVAL;
+               ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val);
+               if (ret)
+-                      break;
++                      return ret;
+               state->meas_interval = val;
+-              break;
++              return 0;
+       case IIO_CHAN_INFO_RAW:
+               switch (chan->type) {
+               case IIO_PRESSURE:
+                       if (val < SCD30_PRESSURE_COMP_MIN_MBAR ||
+                           val > SCD30_PRESSURE_COMP_MAX_MBAR)
+-                              break;
++                              return -EINVAL;
+                       ret = scd30_command_write(state, CMD_START_MEAS, val);
+                       if (ret)
+-                              break;
++                              return ret;
+                       state->pressure_comp = val;
+-                      break;
++                      return 0;
+               default:
+-                      break;
++                      return -EINVAL;
+               }
+-              break;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               if (val < 0 || val > SCD30_TEMP_OFFSET_MAX)
+-                      break;
++                      return -EINVAL;
+               /*
+                * Manufacturer does not explicitly specify min/max sensible
+                * values hence check is omitted for simplicity.
+                */
+-              ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);
++              return scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);
++      default:
++              return -EINVAL;
+       }
+-      mutex_unlock(&state->lock);
+-
+-      return ret;
+ }
+ static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
diff --git a/queue-6.6/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch b/queue-6.6/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch
new file mode 100644 (file)
index 0000000..7fda7f3
--- /dev/null
@@ -0,0 +1,65 @@
+From stable+bounces-260592-greg=kroah.com@vger.kernel.org Fri Jun  5 06:04:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 20:34:32 -0400
+Subject: iio: dac: ad5686: fix ref bit initialization for single-channel parts
+To: stable@vger.kernel.org
+Cc: Rodrigo Alencar <rodrigo.alencar@analog.com>, Andy Shevchenko <andriy.shevchenko@intel.com>, Stable@vger.kernel.org, Jonathan Cameron <jic23@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605003432.2705436-1-sashal@kernel.org>
+
+From: Rodrigo Alencar <rodrigo.alencar@analog.com>
+
+[ Upstream commit ecae2ae606d493cf11457946436335bd0e726663 ]
+
+The reference bit position was ignored when writing the register at the
+probe() function (!!val was used). When such bit is 1, internal voltage
+reference is disabled so that an external one can be used. For
+multi-channel devices, bit 0 of the Internal Reference Setup command
+behaves the same way, so AD5686_REF_BIT_MSK is created. The issue exists
+since support for single-channel devices were first introduced.
+
+Fixes: be1b24d24541 ("iio:dac:ad5686: Add AD5691R/AD5692R/AD5693/AD5693R support")
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
+Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+[ adapted `has_external_vref` to the in-tree equivalent `voltage_uv` variable in the `val =` computation ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/dac/ad5686.c |    6 +++---
+ drivers/iio/dac/ad5686.h |    1 +
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/iio/dac/ad5686.c
++++ b/drivers/iio/dac/ad5686.c
+@@ -528,7 +528,7 @@ int ad5686_probe(struct device *dev,
+               break;
+       case AD5686_REGMAP:
+               cmd = AD5686_CMD_INTERNAL_REFER_SETUP;
+-              ref_bit_msk = 0;
++              ref_bit_msk = AD5686_REF_BIT_MSK;
+               break;
+       case AD5693_REGMAP:
+               cmd = AD5686_CMD_CONTROL_REG;
+@@ -540,9 +540,9 @@ int ad5686_probe(struct device *dev,
+               goto error_disable_reg;
+       }
+-      val = (voltage_uv | ref_bit_msk);
++      val = voltage_uv ? ref_bit_msk : 0;
+-      ret = st->write(st, cmd, 0, !!val);
++      ret = st->write(st, cmd, 0, val);
+       if (ret)
+               goto error_disable_reg;
+--- a/drivers/iio/dac/ad5686.h
++++ b/drivers/iio/dac/ad5686.h
+@@ -46,6 +46,7 @@
+ #define AD5310_REF_BIT_MSK                    BIT(8)
+ #define AD5683_REF_BIT_MSK                    BIT(12)
++#define AD5686_REF_BIT_MSK                    BIT(0)
+ #define AD5693_REF_BIT_MSK                    BIT(12)
+ /**
diff --git a/queue-6.6/iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch b/queue-6.6/iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch
new file mode 100644 (file)
index 0000000..67c623c
--- /dev/null
@@ -0,0 +1,39 @@
+From stable+bounces-260547-greg=kroah.com@vger.kernel.org Thu Jun  4 23:08:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 13:37:58 -0400
+Subject: iio: gyro: adis16260: fix division by zero in write_raw
+To: stable@vger.kernel.org
+Cc: "Antoniu Miclaus" <antoniu.miclaus@analog.com>, "Nuno Sá" <nuno.sa@analog.com>, Stable@vger.kernel.org, "Jonathan Cameron" <Jonathan.Cameron@huawei.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260604173758.25903-1-sashal@kernel.org>
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+[ Upstream commit 761e8b489e6cf166c574034b70637f8a7eadd0ee ]
+
+Add a validation check for the sampling frequency value before using it
+as a divisor. A user writing zero to the sampling_frequency sysfs
+attribute triggers a division by zero in the kernel.
+
+Fixes: 089a41985c6c ("staging: iio: adis16260 digital gyro driver")
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/gyro/adis16260.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/iio/gyro/adis16260.c
++++ b/drivers/iio/gyro/adis16260.c
+@@ -288,6 +288,9 @@ static int adis16260_write_raw(struct ii
+               addr = adis16260_addresses[chan->scan_index][1];
+               return adis_write_reg_16(adis, addr, val);
+       case IIO_CHAN_INFO_SAMP_FREQ:
++              if (val <= 0)
++                      return -EINVAL;
++
+               adis_dev_lock(adis);
+               if (spi_get_device_id(adis->spi)->driver_data)
+                       t = 256 / val;
diff --git a/queue-6.6/memfd-deny-writeable-mappings-when-implying-seal_write.patch b/queue-6.6/memfd-deny-writeable-mappings-when-implying-seal_write.patch
new file mode 100644 (file)
index 0000000..790c1d7
--- /dev/null
@@ -0,0 +1,71 @@
+From stable+bounces-260593-greg=kroah.com@vger.kernel.org Fri Jun  5 06:04:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 20:34:51 -0400
+Subject: memfd: deny writeable mappings when implying SEAL_WRITE
+To: stable@vger.kernel.org
+Cc: "Pratyush Yadav (Google)" <pratyush@kernel.org>, Pasha Tatashin <pasha.tatashin@soleen.com>, Jeff Xu <jeffxu@google.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, Brendan Jackman <jackmanb@google.com>, Greg Thelen <gthelen@google.com>, Hugh Dickins <hughd@google.com>, Kees Cook <kees@kernel.org>, "David Hildenbrand (Arm)" <david@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605003451.2707256-1-sashal@kernel.org>
+
+From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
+
+[ Upstream commit 3b041514cb6eae45869b020f743c14d983363222 ]
+
+When SEAL_EXEC is added, SEAL_WRITE is implied to make W^X.  But the
+implied seal is set after the check that makes sure the memfd can not have
+any writable mappings.  This means one can use SEAL_EXEC to apply
+SEAL_WRITE while having writeable mappings.
+
+This breaks the contract that SEAL_WRITE provides and can be used by an
+attacker to pass a memfd that appears to be write sealed but can still be
+modified arbitrarily.
+
+Fix this by adding the implied seals before the call for
+mapping_deny_writable() is done.
+
+Link: https://lore.kernel.org/20260505133922.797635-1-pratyush@kernel.org
+Fixes: c4f75bc8bd6b ("mm/memfd: add write seals when apply SEAL_EXEC to executable memfd")
+Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
+Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
+Acked-by: Jeff Xu <jeffxu@google.com>
+Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Greg Thelen <gthelen@google.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: "David Hildenbrand (Arm)" <david@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memfd.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/mm/memfd.c
++++ b/mm/memfd.c
+@@ -210,6 +210,12 @@ static int memfd_add_seals(struct file *
+               goto unlock;
+       }
++      /*
++       * SEAL_EXEC implies SEAL_WRITE, making W^X from the start.
++       */
++      if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
++              seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
++
+       if ((seals & F_SEAL_WRITE) && !(*file_seals & F_SEAL_WRITE)) {
+               error = mapping_deny_writable(file->f_mapping);
+               if (error)
+@@ -222,12 +228,6 @@ static int memfd_add_seals(struct file *
+               }
+       }
+-      /*
+-       * SEAL_EXEC implys SEAL_WRITE, making W^X from the start.
+-       */
+-      if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
+-              seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
+-
+       *file_seals |= seals;
+       error = 0;
diff --git a/queue-6.6/mm-hugetlb-rename-folio_putback_active_hugetlb-to-folio_putback_hugetlb.patch b/queue-6.6/mm-hugetlb-rename-folio_putback_active_hugetlb-to-folio_putback_hugetlb.patch
new file mode 100644 (file)
index 0000000..7337d1a
--- /dev/null
@@ -0,0 +1,114 @@
+From stable+bounces-263330-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:01 -0400
+Subject: mm/hugetlb: rename folio_putback_active_hugetlb() to folio_putback_hugetlb()
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Muchun Song <muchun.song@linux.dev>, Sidhartha Kumar <sidhartha.kumar@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-3-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit b235448e8cab7eea17d164efc7bf55505985ba65 ]
+
+Now that folio_putback_hugetlb() is only called on folios that were
+previously isolated through folio_isolate_hugetlb(), let's rename it to
+match folio_putback_lru().
+
+Add some kernel doc to clarify how this function is supposed to be used.
+
+Link: https://lkml.kernel.org/r/20250113131611.2554758-5-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h |    4 ++--
+ mm/hugetlb.c            |   15 +++++++++++++--
+ mm/migrate.c            |    6 +++---
+ 3 files changed, 18 insertions(+), 7 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -166,7 +166,7 @@ bool folio_isolate_hugetlb(struct folio
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+ int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+                               bool *migratable_cleared);
+-void folio_putback_active_hugetlb(struct folio *folio);
++void folio_putback_hugetlb(struct folio *folio);
+ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
+ void hugetlb_fix_reserve_counts(struct inode *inode);
+ extern struct mutex *hugetlb_fault_mutex_table;
+@@ -462,7 +462,7 @@ static inline int get_huge_page_for_hwpo
+       return 0;
+ }
+-static inline void folio_putback_active_hugetlb(struct folio *folio)
++static inline void folio_putback_hugetlb(struct folio *folio)
+ {
+ }
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7259,7 +7259,7 @@ __weak unsigned long hugetlb_mask_last_p
+  * it is already isolated/non-migratable.
+  *
+  * On success, an additional folio reference is taken that must be dropped
+- * using folio_putback_active_hugetlb() to undo the isolation.
++ * using folio_putback_hugetlb() to undo the isolation.
+  *
+  * Return: True if isolation worked, otherwise False.
+  */
+@@ -7311,7 +7311,18 @@ int get_huge_page_for_hwpoison(unsigned
+       return ret;
+ }
+-void folio_putback_active_hugetlb(struct folio *folio)
++/**
++ * folio_putback_hugetlb - unisolate a hugetlb folio
++ * @folio: the isolated hugetlb folio
++ *
++ * Putback/un-isolate the hugetlb folio that was previous isolated using
++ * folio_isolate_hugetlb(): marking it non-isolated/migratable and putting it
++ * back onto the active list.
++ *
++ * Will drop the additional folio reference obtained through
++ * folio_isolate_hugetlb().
++ */
++void folio_putback_hugetlb(struct folio *folio)
+ {
+       spin_lock_irq(&hugetlb_lock);
+       folio_set_hugetlb_migratable(folio);
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -151,7 +151,7 @@ void putback_movable_pages(struct list_h
+       list_for_each_entry_safe(folio, folio2, l, lru) {
+               if (unlikely(folio_test_hugetlb(folio))) {
+-                      folio_putback_active_hugetlb(folio);
++                      folio_putback_hugetlb(folio);
+                       continue;
+               }
+               list_del(&folio->lru);
+@@ -1373,7 +1373,7 @@ static int unmap_and_move_huge_page(new_
+       if (folio_ref_count(src) == 1) {
+               /* page was freed from under us. So we are done. */
+-              folio_putback_active_hugetlb(src);
++              folio_putback_hugetlb(src);
+               return MIGRATEPAGE_SUCCESS;
+       }
+@@ -1456,7 +1456,7 @@ out_unlock:
+       folio_unlock(src);
+ out:
+       if (rc == MIGRATEPAGE_SUCCESS)
+-              folio_putback_active_hugetlb(src);
++              folio_putback_hugetlb(src);
+       else if (rc != -EAGAIN)
+               list_move_tail(&src->lru, ret);
diff --git a/queue-6.6/mm-hugetlb-rename-isolate_hugetlb-to-folio_isolate_hugetlb.patch b/queue-6.6/mm-hugetlb-rename-isolate_hugetlb-to-folio_isolate_hugetlb.patch
new file mode 100644 (file)
index 0000000..c96b53c
--- /dev/null
@@ -0,0 +1,168 @@
+From stable+bounces-263328-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:38:59 -0400
+Subject: mm/hugetlb: rename isolate_hugetlb() to folio_isolate_hugetlb()
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Baolin Wang <baolin.wang@linux.alibaba.com>, Muchun Song <muchun.song@linux.dev>, Sidhartha Kumar <sidhartha.kumar@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-1-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 4c640f128074e0d4459ecf072595a44df5c2ae18 ]
+
+Let's make the function name match "folio_isolate_lru()", and add some
+kernel doc.
+
+Link: https://lkml.kernel.org/r/20250113131611.2554758-3-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h |    4 ++--
+ mm/gup.c                |    2 +-
+ mm/hugetlb.c            |   25 +++++++++++++++++++------
+ mm/memory-failure.c     |    2 +-
+ mm/memory_hotplug.c     |    2 +-
+ mm/mempolicy.c          |    2 +-
+ mm/migrate.c            |    4 ++--
+ 7 files changed, 27 insertions(+), 14 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -162,7 +162,7 @@ bool hugetlb_reserve_pages(struct inode
+                                               vm_flags_t vm_flags);
+ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,
+                                               long freed);
+-bool isolate_hugetlb(struct folio *folio, struct list_head *list);
++bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list);
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+ int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+                               bool *migratable_cleared);
+@@ -446,7 +446,7 @@ static inline pte_t *huge_pte_offset(str
+       return NULL;
+ }
+-static inline bool isolate_hugetlb(struct folio *folio, struct list_head *list)
++static inline bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list)
+ {
+       return false;
+ }
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -1971,7 +1971,7 @@ static unsigned long collect_longterm_un
+                       continue;
+               if (folio_test_hugetlb(folio)) {
+-                      isolate_hugetlb(folio, movable_page_list);
++                      folio_isolate_hugetlb(folio, movable_page_list);
+                       continue;
+               }
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -2969,7 +2969,7 @@ retry:
+                * Fail with -EBUSY if not possible.
+                */
+               spin_unlock_irq(&hugetlb_lock);
+-              isolated = isolate_hugetlb(old_folio, list);
++              isolated = folio_isolate_hugetlb(old_folio, list);
+               ret = isolated ? 0 : -EBUSY;
+               spin_lock_irq(&hugetlb_lock);
+               goto free_new;
+@@ -3045,7 +3045,7 @@ int isolate_or_dissolve_huge_page(struct
+       if (hstate_is_gigantic(h))
+               return -ENOMEM;
+-      if (folio_ref_count(folio) && isolate_hugetlb(folio, list))
++      if (folio_ref_count(folio) && folio_isolate_hugetlb(folio, list))
+               ret = 0;
+       else if (!folio_ref_count(folio))
+               ret = alloc_and_dissolve_hugetlb_folio(h, folio, list);
+@@ -7246,11 +7246,24 @@ __weak unsigned long hugetlb_mask_last_p
+ #endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
+-/*
+- * These functions are overwritable if your architecture needs its own
+- * behavior.
++/**
++ * folio_isolate_hugetlb - try to isolate an allocated hugetlb folio
++ * @folio: the folio to isolate
++ * @list: the list to add the folio to on success
++ *
++ * Isolate an allocated (refcount > 0) hugetlb folio, marking it as
++ * isolated/non-migratable, and moving it from the active list to the
++ * given list.
++ *
++ * Isolation will fail if @folio is not an allocated hugetlb folio, or if
++ * it is already isolated/non-migratable.
++ *
++ * On success, an additional folio reference is taken that must be dropped
++ * using folio_putback_active_hugetlb() to undo the isolation.
++ *
++ * Return: True if isolation worked, otherwise False.
+  */
+-bool isolate_hugetlb(struct folio *folio, struct list_head *list)
++bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list)
+ {
+       bool ret = true;
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -2639,7 +2639,7 @@ static bool isolate_page(struct page *pa
+       bool isolated = false;
+       if (PageHuge(page)) {
+-              isolated = isolate_hugetlb(page_folio(page), pagelist);
++              isolated = folio_isolate_hugetlb(page_folio(page), pagelist);
+       } else {
+               bool lru = !__PageMovable(page);
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1720,7 +1720,7 @@ static void do_migrate_range(unsigned lo
+               if (PageHuge(page)) {
+                       pfn = page_to_pfn(head) + compound_nr(head) - 1;
+-                      isolate_hugetlb(folio, &source);
++                      folio_isolate_hugetlb(folio, &source);
+                       continue;
+               } else if (PageTransHuge(page))
+                       pfn = page_to_pfn(head) + thp_nr_pages(page) - 1;
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -608,7 +608,7 @@ static int queue_folios_hugetlb(pte_t *p
+        */
+       if ((flags & MPOL_MF_MOVE_ALL) ||
+           (folio_estimated_sharers(folio) == 1 && !hugetlb_pmd_shared(pte)))
+-              if (!isolate_hugetlb(folio, qp->pagelist))
++              if (!folio_isolate_hugetlb(folio, qp->pagelist))
+                       qp->nr_failed++;
+ unlock:
+       spin_unlock(ptl);
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -142,7 +142,7 @@ static void putback_movable_folio(struct
+  *
+  * This function shall be used whenever the isolated pageset has been
+  * built from lru, balloon, hugetlbfs page. See isolate_migratepages_range()
+- * and isolate_hugetlb().
++ * and folio_isolate_hugetlb().
+  */
+ void putback_movable_pages(struct list_head *l)
+ {
+@@ -2113,7 +2113,7 @@ static int add_page_for_migration(struct
+       if (PageHuge(page)) {
+               if (PageHead(page)) {
+-                      isolated = isolate_hugetlb(page_folio(page), pagelist);
++                      isolated = folio_isolate_hugetlb(page_folio(page), pagelist);
+                       err = isolated ? 1 : -EBUSY;
+               }
+       } else {
diff --git a/queue-6.6/mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch b/queue-6.6/mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch
new file mode 100644 (file)
index 0000000..19977ff
--- /dev/null
@@ -0,0 +1,199 @@
+From stable+bounces-263332-greg=kroah.com@vger.kernel.org Mon Jun 15 21:13:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:03 -0400
+Subject: mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison
+To: stable@vger.kernel.org
+Cc: Wupeng Ma <mawupeng1@huawei.com>, "Oscar Salvador (SUSE)" <osalvador@kernel.org>, Muchun Song <muchun.song@linux.dev>, Kefeng Wang <wangkefeng.wang@huawei.com>, Miaohe Lin <linmiaohe@huawei.com>, David Hildenbrand <david@kernel.org>, Liam Howlett <liam.howlett@oracle.com>, Lorenzo Stoakes <ljs@kernel.org>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Naoya Horiguchi <nao.horiguchi@gmail.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-5-sashal@kernel.org>
+
+From: Wupeng Ma <mawupeng1@huawei.com>
+
+[ Upstream commit 3c2d42b8ee345b17a4ba56b0f6492d1ff4c1178e ]
+
+Two concurrent madvise(MADV_HWPOISON) calls on the same hugetlb page can
+trigger a recursive spinlock self-deadlock (AA deadlock) on hugetlb_lock
+when racing with a concurrent unmap:
+
+  thread#0                              thread#1
+  --------                              --------
+  madvise(folio, MADV_HWPOISON)
+    -> poisons the folio successfully
+  madvise(folio, MADV_HWPOISON)         unmap(folio)
+    try_memory_failure_hugetlb
+      get_huge_page_for_hwpoison
+        spin_lock_irq(&hugetlb_lock)    <- held
+        __get_huge_page_for_hwpoison
+          hugetlb_update_hwpoison()
+            -> MF_HUGETLB_FOLIO_PRE_POISONED
+          goto out:
+            folio_put()
+              refcount: 1 -> 0
+              free_huge_folio()
+                spin_lock_irqsave(&hugetlb_lock)
+                  -> AA DEADLOCK!
+
+The out: path in __get_huge_page_for_hwpoison() calls folio_put() to drop
+the GUP reference while the hugetlb_lock is still held by the hugetlb.c
+wrapper get_huge_page_for_hwpoison().  If concurrent unmap has released
+the page table mapping reference, folio_put() drops the folio refcount to
+zero, triggering free_huge_folio() which attempts to re-acquire the
+non-recursive hugetlb_lock.
+
+Fix this by moving hugetlb_lock acquisition from the hugetlb.c wrapper
+into get_huge_page_for_hwpoison().  Place spin_unlock_irq() before the
+folio_put() at the out: label so the folio is always released outside the
+lock.
+
+[akpm@linux-foundation.org: fix race, rename label per Miaohe]
+  Link: https://sashiko.dev/#/patchset/20260522010305.4099834-1-mawupeng1@huawei.com
+  Link: https://lore.kernel.org/f39f405e-4b4b-8f79-70fe-a2b5b62114eb@huawei.com
+Link: https://lore.kernel.org/20260522010305.4099834-1-mawupeng1@huawei.com
+Fixes: 405ce051236c ("mm/hwpoison: fix race between hugetlb free/demotion and memory_failure_hugetlb()")
+Signed-off-by: Wupeng Ma <mawupeng1@huawei.com>
+Acked-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
+Acked-by: Muchun Song <muchun.song@linux.dev>
+Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Acked-by: Miaohe Lin <linmiaohe@huawei.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+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: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h |    8 --------
+ include/linux/mm.h      |    8 --------
+ mm/hugetlb.c            |   11 -----------
+ mm/memory-failure.c     |   19 ++++++++++---------
+ 4 files changed, 10 insertions(+), 36 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -164,8 +164,6 @@ long hugetlb_unreserve_pages(struct inod
+                                               long freed);
+ bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list);
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+-                              bool *migratable_cleared);
+ void folio_putback_hugetlb(struct folio *folio);
+ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
+ void hugetlb_fix_reserve_counts(struct inode *inode);
+@@ -455,12 +453,6 @@ static inline int get_hwpoison_hugetlb_f
+ {
+       return 0;
+ }
+-
+-static inline int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+-                                      bool *migratable_cleared)
+-{
+-      return 0;
+-}
+ static inline void folio_putback_hugetlb(struct folio *folio)
+ {
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -3924,8 +3924,6 @@ extern int soft_offline_page(unsigned lo
+  */
+ extern const struct attribute_group memory_failure_attr_group;
+ extern void memory_failure_queue(unsigned long pfn, int flags);
+-extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+-                                      bool *migratable_cleared);
+ void num_poisoned_pages_inc(unsigned long pfn);
+ void num_poisoned_pages_sub(unsigned long pfn, long i);
+ struct task_struct *task_early_kill(struct task_struct *tsk, int force_early);
+@@ -3934,12 +3932,6 @@ static inline void memory_failure_queue(
+ {
+ }
+-static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+-                                      bool *migratable_cleared)
+-{
+-      return 0;
+-}
+-
+ static inline void num_poisoned_pages_inc(unsigned long pfn)
+ {
+ }
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7300,17 +7300,6 @@ int get_hwpoison_hugetlb_folio(struct fo
+       return ret;
+ }
+-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+-                              bool *migratable_cleared)
+-{
+-      int ret;
+-
+-      spin_lock_irq(&hugetlb_lock);
+-      ret = __get_huge_page_for_hwpoison(pfn, flags, migratable_cleared);
+-      spin_unlock_irq(&hugetlb_lock);
+-      return ret;
+-}
+-
+ /**
+  * folio_putback_hugetlb - unisolate a hugetlb folio
+  * @folio: the isolated hugetlb folio
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -1994,20 +1994,19 @@ void folio_clear_hugetlb_hwpoison(struct
+       folio_free_raw_hwp(folio, true);
+ }
+-/*
+- * Called from hugetlb code with hugetlb_lock held.
+- */
+-int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
++static int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+                                bool *migratable_cleared)
+ {
+       struct page *page = pfn_to_page(pfn);
+-      struct folio *folio = page_folio(page);
++      struct folio *folio;
+       bool count_increased = false;
+       int ret, rc;
++      spin_lock_irq(&hugetlb_lock);
++      folio = page_folio(page);
+       if (!folio_test_hugetlb(folio)) {
+               ret = MF_HUGETLB_NON_HUGEPAGE;
+-              goto out;
++              goto out_unlock;
+       } else if (flags & MF_COUNT_INCREASED) {
+               ret = MF_HUGETLB_IN_USED;
+               count_increased = true;
+@@ -2023,13 +2022,13 @@ int __get_huge_page_for_hwpoison(unsigne
+       } else {
+               ret = MF_HUGETLB_RETRY;
+               if (!(flags & MF_NO_RETRY))
+-                      goto out;
++                      goto out_unlock;
+       }
+       rc = hugetlb_update_hwpoison(folio, page);
+       if (rc >= MF_HUGETLB_FOLIO_PRE_POISONED) {
+               ret = rc;
+-              goto out;
++              goto out_unlock;
+       }
+       /*
+@@ -2041,8 +2040,10 @@ int __get_huge_page_for_hwpoison(unsigne
+               *migratable_cleared = true;
+       }
++      spin_unlock_irq(&hugetlb_lock);
+       return ret;
+-out:
++out_unlock:
++      spin_unlock_irq(&hugetlb_lock);
+       if (count_increased)
+               folio_put(folio);
+       return ret;
diff --git a/queue-6.6/mm-memory-failure-fix-missing-mf_stats-count-in-hugetlb-poison.patch b/queue-6.6/mm-memory-failure-fix-missing-mf_stats-count-in-hugetlb-poison.patch
new file mode 100644 (file)
index 0000000..2656f0c
--- /dev/null
@@ -0,0 +1,212 @@
+From stable+bounces-263331-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:02 -0400
+Subject: mm/memory-failure: fix missing ->mf_stats count in hugetlb poison
+To: stable@vger.kernel.org
+Cc: Jane Chu <jane.chu@oracle.com>, Miaohe Lin <linmiaohe@huawei.com>, Chris Mason <clm@meta.com>, David Hildenbrand <david@kernel.org>, David Rientjes <rientjes@google.com>, Jiaqi Yan <jiaqiyan@google.com>, "Liam R. Howlett" <Liam.Howlett@oracle.com>, Lorenzo Stoakes <lorenzo.stoakes@oracle.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Muchun Song <muchun.song@linux.dev>, Naoya Horiguchi <nao.horiguchi@gmail.com>, Oscar Salvador <osalvador@suse.de>, Suren Baghdasaryan <surenb@google.com>, William Roche <william.roche@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-4-sashal@kernel.org>
+
+From: Jane Chu <jane.chu@oracle.com>
+
+[ Upstream commit a148a2040191b12b45b82cb29c281cb3036baf90 ]
+
+When a newly poisoned subpage ends up in an already poisoned hugetlb
+folio, 'num_poisoned_pages' is incremented, but the per node ->mf_stats is
+not.  Fix the inconsistency by designating action_result() to update them
+both.
+
+While at it, define __get_huge_page_for_hwpoison() return values in terms
+of symbol names for better readibility.  Also rename
+folio_set_hugetlb_hwpoison() to hugetlb_update_hwpoison() since the
+function does more than the conventional bit setting and the fact three
+possible return values are expected.
+
+Link: https://lkml.kernel.org/r/20260120232234.3462258-1-jane.chu@oracle.com
+Fixes: 18f41fa616ee ("mm: memory-failure: bump memory failure stats to pglist_data")
+Signed-off-by: Jane Chu <jane.chu@oracle.com>
+Acked-by: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Chris Mason <clm@meta.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Jiaqi Yan <jiaqiyan@google.com>
+Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: William Roche <william.roche@oracle.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memory-failure.c |   73 ++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 46 insertions(+), 27 deletions(-)
+
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -1912,12 +1912,22 @@ static unsigned long __folio_free_raw_hw
+       return count;
+ }
+-static int folio_set_hugetlb_hwpoison(struct folio *folio, struct page *page)
++#define       MF_HUGETLB_FREED                0       /* freed hugepage */
++#define       MF_HUGETLB_IN_USED              1       /* in-use hugepage */
++#define       MF_HUGETLB_NON_HUGEPAGE         2       /* not a hugepage */
++#define       MF_HUGETLB_FOLIO_PRE_POISONED   3       /* folio already poisoned */
++#define       MF_HUGETLB_PAGE_PRE_POISONED    4       /* exact page already poisoned */
++#define       MF_HUGETLB_RETRY                5       /* hugepage is busy, retry */
++/*
++ * Set hugetlb folio as hwpoisoned, update folio private raw hwpoison list
++ * to keep track of the poisoned pages.
++ */
++static int hugetlb_update_hwpoison(struct folio *folio, struct page *page)
+ {
+       struct llist_head *head;
+       struct raw_hwp_page *raw_hwp;
+       struct raw_hwp_page *p, *next;
+-      int ret = folio_test_set_hwpoison(folio) ? -EHWPOISON : 0;
++      int ret = folio_test_set_hwpoison(folio) ? MF_HUGETLB_FOLIO_PRE_POISONED : 0;
+       /*
+        * Once the hwpoison hugepage has lost reliable raw error info,
+@@ -1925,11 +1935,11 @@ static int folio_set_hugetlb_hwpoison(st
+        * so skip to add additional raw error info.
+        */
+       if (folio_test_hugetlb_raw_hwp_unreliable(folio))
+-              return -EHWPOISON;
++              return MF_HUGETLB_FOLIO_PRE_POISONED;
+       head = raw_hwp_list_head(folio);
+       llist_for_each_entry_safe(p, next, head->first, node) {
+               if (p->page == page)
+-                      return -EHWPOISON;
++                      return MF_HUGETLB_PAGE_PRE_POISONED;
+       }
+       raw_hwp = kmalloc(sizeof(struct raw_hwp_page), GFP_ATOMIC);
+@@ -1986,42 +1996,39 @@ void folio_clear_hugetlb_hwpoison(struct
+ /*
+  * Called from hugetlb code with hugetlb_lock held.
+- *
+- * Return values:
+- *   0             - free hugepage
+- *   1             - in-use hugepage
+- *   2             - not a hugepage
+- *   -EBUSY        - the hugepage is busy (try to retry)
+- *   -EHWPOISON    - the hugepage is already hwpoisoned
+  */
+ int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+                                bool *migratable_cleared)
+ {
+       struct page *page = pfn_to_page(pfn);
+       struct folio *folio = page_folio(page);
+-      int ret = 2;    /* fallback to normal page handling */
+       bool count_increased = false;
++      int ret, rc;
+-      if (!folio_test_hugetlb(folio))
++      if (!folio_test_hugetlb(folio)) {
++              ret = MF_HUGETLB_NON_HUGEPAGE;
+               goto out;
+-
+-      if (flags & MF_COUNT_INCREASED) {
+-              ret = 1;
++      } else if (flags & MF_COUNT_INCREASED) {
++              ret = MF_HUGETLB_IN_USED;
+               count_increased = true;
+       } else if (folio_test_hugetlb_freed(folio)) {
+-              ret = 0;
++              ret = MF_HUGETLB_FREED;
+       } else if (folio_test_hugetlb_migratable(folio)) {
+-              ret = folio_try_get(folio);
+-              if (ret)
++              if (folio_try_get(folio)) {
++                      ret = MF_HUGETLB_IN_USED;
+                       count_increased = true;
++              } else {
++                      ret = MF_HUGETLB_FREED;
++              }
+       } else {
+-              ret = -EBUSY;
++              ret = MF_HUGETLB_RETRY;
+               if (!(flags & MF_NO_RETRY))
+                       goto out;
+       }
+-      if (folio_set_hugetlb_hwpoison(folio, page)) {
+-              ret = -EHWPOISON;
++      rc = hugetlb_update_hwpoison(folio, page);
++      if (rc >= MF_HUGETLB_FOLIO_PRE_POISONED) {
++              ret = rc;
+               goto out;
+       }
+@@ -2046,6 +2053,12 @@ out:
+  * with basic operations like hugepage allocation/free/demotion.
+  * So some of prechecks for hwpoison (pinning, and testing/setting
+  * PageHWPoison) should be done in single hugetlb_lock range.
++ * Returns:
++ *    0               - not hugetlb, or recovered
++ *    -EBUSY          - not recovered
++ *    -EOPNOTSUPP     - hwpoison_filter'ed
++ *    -EHWPOISON      - folio or exact page already poisoned
++ *    -EFAULT         - kill_accessing_process finds current->mm null
+  */
+ static int try_memory_failure_hugetlb(unsigned long pfn, int flags, int *hugetlb)
+ {
+@@ -2058,22 +2071,28 @@ static int try_memory_failure_hugetlb(un
+       *hugetlb = 1;
+ retry:
+       res = get_huge_page_for_hwpoison(pfn, flags, &migratable_cleared);
+-      if (res == 2) { /* fallback to normal page handling */
++      switch (res) {
++      case MF_HUGETLB_NON_HUGEPAGE:   /* fallback to normal page handling */
+               *hugetlb = 0;
+               return 0;
+-      } else if (res == -EHWPOISON) {
++      case MF_HUGETLB_FOLIO_PRE_POISONED:
++      case MF_HUGETLB_PAGE_PRE_POISONED:
+               pr_err("%#lx: already hardware poisoned\n", pfn);
++              res = -EHWPOISON;
+               if (flags & MF_ACTION_REQUIRED) {
+                       folio = page_folio(p);
+                       res = kill_accessing_process(current, folio_pfn(folio), flags);
+               }
+               return res;
+-      } else if (res == -EBUSY) {
++      case MF_HUGETLB_RETRY:
+               if (!(flags & MF_NO_RETRY)) {
+                       flags |= MF_NO_RETRY;
+                       goto retry;
+               }
+               return action_result(pfn, MF_MSG_UNKNOWN, MF_IGNORED);
++      default:
++              WARN_ON((res != MF_HUGETLB_FREED) && (res != MF_HUGETLB_IN_USED));
++              break;
+       }
+       folio = page_folio(p);
+@@ -2084,7 +2103,7 @@ retry:
+               if (migratable_cleared)
+                       folio_set_hugetlb_migratable(folio);
+               folio_unlock(folio);
+-              if (res == 1)
++              if (res == MF_HUGETLB_IN_USED)
+                       folio_put(folio);
+               return -EOPNOTSUPP;
+       }
+@@ -2093,7 +2112,7 @@ retry:
+        * Handling free hugepage.  The possible race with hugepage allocation
+        * or demotion can be prevented by PageHWPoison flag.
+        */
+-      if (res == 0) {
++      if (res == MF_HUGETLB_FREED) {
+               folio_unlock(folio);
+               if (__page_handle_poison(p) > 0) {
+                       page_ref_inc(p);
diff --git a/queue-6.6/mm-migrate-don-t-call-folio_putback_active_hugetlb-on-dst-hugetlb-folio.patch b/queue-6.6/mm-migrate-don-t-call-folio_putback_active_hugetlb-on-dst-hugetlb-folio.patch
new file mode 100644 (file)
index 0000000..93f9bf3
--- /dev/null
@@ -0,0 +1,83 @@
+From stable+bounces-263329-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:00 -0400
+Subject: mm/migrate: don't call folio_putback_active_hugetlb() on dst hugetlb folio
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Muchun Song <muchun.song@linux.dev>, Sidhartha Kumar <sidhartha.kumar@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-2-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit ba23f58de896842028b4b33b95530f08288396fe ]
+
+We replaced a simple put_page() by a putback_active_hugepage() call in
+commit 3aaa76e125c1 ("mm: migrate: hugetlb: putback destination hugepage
+to active list"), to set the "active" flag on the dst hugetlb folio.
+
+Nowadays, we decoupled the "active" list from the flag, by calling the
+flag "migratable".
+
+Calling "putback" on something that wasn't allocated is weird and not
+future proof, especially if we might reach that path when migration failed
+and we just want to free the freshly allocated hugetlb folio.
+
+Let's simply handle the migratable flag and the active list flag in
+move_hugetlb_state(), where we know that allocation succeeded and already
+handle the temporary flag; use a simple folio_put() to return our
+reference.
+
+Link: https://lkml.kernel.org/r/20250113131611.2554758-4-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c |   10 ++++++++++
+ mm/migrate.c |    8 ++++----
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7358,6 +7358,16 @@ void move_hugetlb_state(struct folio *ol
+               }
+               spin_unlock_irq(&hugetlb_lock);
+       }
++
++      /*
++       * Our old folio is isolated and has "migratable" cleared until it
++       * is putback. As migration succeeded, set the new folio "migratable"
++       * and add it to the active list.
++       */
++      spin_lock_irq(&hugetlb_lock);
++      folio_set_hugetlb_migratable(new_folio);
++      list_move_tail(&new_folio->lru, &(folio_hstate(new_folio))->hugepage_activelist);
++      spin_unlock_irq(&hugetlb_lock);
+ }
+ /*
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -1461,14 +1461,14 @@ out:
+               list_move_tail(&src->lru, ret);
+       /*
+-       * If migration was not successful and there's a freeing callback, use
+-       * it.  Otherwise, put_page() will drop the reference grabbed during
+-       * isolation.
++       * If migration was not successful and there's a freeing callback,
++       * return the folio to that special allocator. Otherwise, simply drop
++       * our additional reference.
+        */
+       if (put_new_folio)
+               put_new_folio(dst, private);
+       else
+-              folio_putback_active_hugetlb(dst);
++              folio_put(dst);
+       return rc;
+ }
diff --git a/queue-6.6/netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch b/queue-6.6/netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch
new file mode 100644 (file)
index 0000000..13fc12d
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-263293-greg=kroah.com@vger.kernel.org Mon Jun 15 20:52:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:16:35 -0400
+Subject: netfilter: nft_fib: fix stale stack leak via the OIFNAME register
+To: stable@vger.kernel.org
+Cc: Davide Ornaghi <d.ornaghi97@gmail.com>, Florian Westphal <fw@strlen.de>, Pablo Neira Ayuso <pablo@netfilter.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615151635.2204309-1-sashal@kernel.org>
+
+From: Davide Ornaghi <d.ornaghi97@gmail.com>
+
+[ Upstream commit ab185e0c4fb82dfba6fb86f8271e06f931d9c64c ]
+
+For NFT_FIB_RESULT_OIFNAME the destination register is declared with
+len = IFNAMSIZ (four 32-bit registers), but on the lookup-fail,
+RTN_LOCAL and oif-mismatch paths nft_fib{4,6}_eval() only writes one
+register via "*dest = 0". The remaining three registers are left as
+whatever was on the stack in nft_do_chain()'s struct nft_regs, and a
+downstream expression that loads the register span can leak that
+uninitialised kernel stack to userspace.
+
+The NFTA_FIB_F_PRESENT existence check has the same shape: it is only
+meaningful for NFT_FIB_RESULT_OIF, yet it was accepted for any result type
+while the eval stores a single byte via nft_reg_store8(), leaving the rest
+of the declared span stale.
+
+Fix both:
+
+ - replace the bare "*dest = 0" in the eval with nft_fib_store_result(),
+   which strscpy_pad()s the whole IFNAMSIZ for OIFNAME (and is already
+   used on the other early-return path), and
+
+ - restrict NFTA_FIB_F_PRESENT to NFT_FIB_RESULT_OIF and declare its
+   destination as a single u8, so the marked span matches the one byte
+   the eval writes.
+
+Fixes: f6d0cbcf09c5 ("netfilter: nf_tables: add fib expression")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Davide Ornaghi <d.ornaghi97@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+[ kept the tree's existing `ip6_route_lookup`/`rt6_info` machinery (missing `fib6_lookup` refactor) and changed only `*dest = 0;` to `nft_fib_store_result(dest, priv, NULL)` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/netfilter/nft_fib_ipv4.c |    2 +-
+ net/ipv6/netfilter/nft_fib_ipv6.c |    2 +-
+ net/netfilter/nft_fib.c           |    6 ++++++
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/netfilter/nft_fib_ipv4.c
++++ b/net/ipv4/netfilter/nft_fib_ipv4.c
+@@ -122,7 +122,7 @@ void nft_fib4_eval(const struct nft_expr
+               fl4.saddr = get_saddr(iph->daddr);
+       }
+-      *dest = 0;
++      nft_fib_store_result(dest, priv, NULL);
+       if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
+               return;
+--- a/net/ipv6/netfilter/nft_fib_ipv6.c
++++ b/net/ipv6/netfilter/nft_fib_ipv6.c
+@@ -193,7 +193,7 @@ void nft_fib6_eval(const struct nft_expr
+               }
+       }
+-      *dest = 0;
++      nft_fib_store_result(dest, priv, NULL);
+       rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb,
+                                     lookup_flags);
+       if (rt->dst.error)
+--- a/net/netfilter/nft_fib.c
++++ b/net/netfilter/nft_fib.c
+@@ -107,6 +107,12 @@ int nft_fib_init(const struct nft_ctx *c
+               return -EINVAL;
+       }
++      if (priv->flags & NFTA_FIB_F_PRESENT) {
++              if (priv->result != NFT_FIB_RESULT_OIF)
++                      return -EINVAL;
++              len = sizeof(u8);
++      }
++
+       err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
+                                      NULL, NFT_DATA_VALUE, len);
+       if (err < 0)
diff --git a/queue-6.6/rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch b/queue-6.6/rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch
new file mode 100644 (file)
index 0000000..dad16c0
--- /dev/null
@@ -0,0 +1,157 @@
+From stable+bounces-263480-greg=kroah.com@vger.kernel.org Tue Jun 16 04:24:12 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 18:52:07 -0400
+Subject: RDMA: During rereg_mr ensure that REREG_ACCESS is compatible
+To: stable@vger.kernel.org
+Cc: Jason Gunthorpe <jgg@nvidia.com>, Philip Tsukerman <philiptsukerman@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615225207.2520056-1-sashal@kernel.org>
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit badad6fad60def1b9805559dd81dbab3d97b82aa ]
+
+If IB_MR_REREG_ACCESS changes from RO to RW then the umem has to be
+re-evaluated to ensure it is properly pinned as RW. Since the umem is
+hidden inside each driver's mr struct add a ib_umem_check_rereg() function
+that each driver has to call before processing IB_MR_REREG_ACCESS.
+
+mlx4 has to retain its duplicate ib_access_writable check because it
+implements IB_MR_REREG_ACCESS | IB_MR_REREG_TRANS by changing both items
+in place sequentially while the MR is live, so it will continue to not
+support this combination.
+
+Cc: stable@vger.kernel.org
+Fixes: b40656aa7d55 ("RDMA/umem: remove FOLL_FORCE usage")
+Link: https://patch.msgid.link/r/0-v1-06fb1a2d6cf5+107-rereg_access_jgg@nvidia.com
+Reported-by: Philip Tsukerman <philiptsukerman@gmail.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/umem.c          |   16 ++++++++++++++++
+ drivers/infiniband/hw/hns/hns_roce_mr.c |    4 ++++
+ drivers/infiniband/hw/irdma/verbs.c     |    4 ++++
+ drivers/infiniband/hw/mlx4/mr.c         |    4 ++++
+ drivers/infiniband/hw/mlx5/mr.c         |    4 ++++
+ drivers/infiniband/sw/rxe/rxe_verbs.c   |    5 +++++
+ include/rdma/ib_umem.h                  |    8 ++++++++
+ 7 files changed, 45 insertions(+)
+
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -326,3 +326,19 @@ int ib_umem_copy_from(void *dst, struct
+               return 0;
+ }
+ EXPORT_SYMBOL(ib_umem_copy_from);
++
++/*
++ * Called during rereg mr if the driver is able to re-use a umem for
++ * IB_MR_REREG_ACCESS.
++ */
++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags)
++{
++      if (!umem)
++              return 0;
++
++      if ((flags & IB_MR_REREG_ACCESS) && !(flags & IB_MR_REREG_TRANS))
++              if (ib_access_writable(new_access_flags) && !umem->writable)
++                      return -EACCES;
++      return 0;
++}
++EXPORT_SYMBOL(ib_umem_check_rereg);
+--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
+@@ -277,6 +277,10 @@ struct ib_mr *hns_roce_rereg_user_mr(str
+       if (!mr->enabled)
+               return ERR_PTR(-EINVAL);
++      ret = ib_umem_check_rereg(mr->pbl_mtr.umem, flags, mr_access_flags);
++      if (ret)
++              return ERR_PTR(ret);
++
+       mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
+       if (IS_ERR(mailbox))
+               return ERR_CAST(mailbox);
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -3244,6 +3244,10 @@ static struct ib_mr *irdma_rereg_user_mr
+       if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
+               return ERR_PTR(-EOPNOTSUPP);
++      ret = ib_umem_check_rereg(iwmr->region, flags, new_access);
++      if (ret)
++              return ERR_PTR(ret);
++
+       ret = irdma_hwdereg_mr(ib_mr);
+       if (ret)
+               return ERR_PTR(ret);
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -466,6 +466,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(stru
+       struct mlx4_mpt_entry **pmpt_entry = &mpt_entry;
+       int err;
++      err = ib_umem_check_rereg(mmr->umem, flags, mr_access_flags);
++      if (err)
++              return ERR_PTR(err);
++
+       /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs,
+        * we assume that the calls can't run concurrently. Otherwise, a
+        * race exists.
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -1698,6 +1698,10 @@ struct ib_mr *mlx5_ib_rereg_user_mr(stru
+       if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
+               return ERR_PTR(-EOPNOTSUPP);
++      err = ib_umem_check_rereg(mr->umem, flags, new_access_flags);
++      if (err)
++              return ERR_PTR(err);
++
+       if (!(flags & IB_MR_REREG_ACCESS))
+               new_access_flags = mr->access_flags;
+       if (!(flags & IB_MR_REREG_PD))
+--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
+@@ -1316,6 +1316,7 @@ static struct ib_mr *rxe_rereg_user_mr(s
+       struct rxe_mr *mr = to_rmr(ibmr);
+       struct rxe_pd *old_pd = to_rpd(ibmr->pd);
+       struct rxe_pd *pd = to_rpd(ibpd);
++      int err;
+       /* for now only support the two easy cases:
+        * rereg_pd and rereg_access
+@@ -1325,6 +1326,10 @@ static struct ib_mr *rxe_rereg_user_mr(s
+               return ERR_PTR(-EOPNOTSUPP);
+       }
++      err = ib_umem_check_rereg(mr->umem, flags, access);
++      if (err)
++              return ERR_PTR(err);
++
+       if (flags & IB_MR_REREG_PD) {
+               rxe_put(old_pd);
+               rxe_get(pd);
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -154,6 +154,8 @@ int ib_umem_dmabuf_map_pages(struct ib_u
+ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf);
+ void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf);
++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags);
++
+ #else /* CONFIG_INFINIBAND_USER_MEM */
+ #include <linux/err.h>
+@@ -203,5 +205,11 @@ static inline int ib_umem_dmabuf_map_pag
+ static inline void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) { }
+ static inline void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) { }
++static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags,
++                                    int new_access_flags)
++{
++      return -EOPNOTSUPP;
++}
++
+ #endif /* CONFIG_INFINIBAND_USER_MEM */
+ #endif /* IB_UMEM_H */
diff --git a/queue-6.6/rdma-move-dma-block-iterator-logic-into-dedicated-files.patch b/queue-6.6/rdma-move-dma-block-iterator-logic-into-dedicated-files.patch
new file mode 100644 (file)
index 0000000..80545b9
--- /dev/null
@@ -0,0 +1,509 @@
+From stable+bounces-263489-greg=kroah.com@vger.kernel.org Tue Jun 16 05:29:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 19:58:47 -0400
+Subject: RDMA: Move DMA block iterator logic into dedicated files
+To: stable@vger.kernel.org
+Cc: Leon Romanovsky <leonro@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615235848.2562462-2-sashal@kernel.org>
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 6094ea64c69520ed1e770e7c79c43412de202bfa ]
+
+The DMA iterator logic was mixed into verbs and umem-specific code,
+forcing all users to include rdma/ib_umem.h. Move the block iterator
+logic into iter.c and rdma/iter.h so that rdma/ib_umem.h and
+rdma/ib_verbs.h can be separated in a follow-up patch.
+
+Link: https://patch.msgid.link/20260213-refactor-umem-v1-1-f3be85847922@nvidia.com
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/Makefile             |    2 
+ drivers/infiniband/core/iter.c               |   43 +++++++++++++
+ drivers/infiniband/core/verbs.c              |   38 -----------
+ drivers/infiniband/hw/bnxt_re/qplib_res.c    |    2 
+ drivers/infiniband/hw/cxgb4/mem.c            |    2 
+ drivers/infiniband/hw/efa/efa_verbs.c        |    2 
+ drivers/infiniband/hw/erdma/erdma_verbs.c    |    2 
+ drivers/infiniband/hw/hns/hns_roce_alloc.c   |    2 
+ drivers/infiniband/hw/irdma/main.h           |    2 
+ drivers/infiniband/hw/mana/mana_ib.h         |    2 
+ drivers/infiniband/hw/mlx4/mr.c              |    1 
+ drivers/infiniband/hw/mlx5/mem.c             |    1 
+ drivers/infiniband/hw/mlx5/umr.c             |    1 
+ drivers/infiniband/hw/mthca/mthca_provider.c |    2 
+ drivers/infiniband/hw/ocrdma/ocrdma_verbs.c  |    2 
+ drivers/infiniband/hw/qedr/verbs.c           |    2 
+ drivers/infiniband/hw/vmw_pvrdma/pvrdma.h    |    2 
+ include/rdma/ib_umem.h                       |   32 ---------
+ include/rdma/ib_verbs.h                      |   48 --------------
+ include/rdma/iter.h                          |   88 +++++++++++++++++++++++++++
+ 20 files changed, 146 insertions(+), 130 deletions(-)
+ create mode 100644 drivers/infiniband/core/iter.c
+ create mode 100644 include/rdma/iter.h
+
+--- a/drivers/infiniband/core/Makefile
++++ b/drivers/infiniband/core/Makefile
+@@ -12,7 +12,7 @@ ib_core-y :=                 packer.o ud_header.o verb
+                               roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
+                               multicast.o mad.o smi.o agent.o mad_rmpp.o \
+                               nldev.o restrack.o counters.o ib_core_uverbs.o \
+-                              trace.o lag.o
++                              trace.o lag.o iter.o
+ ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
+ ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
+--- /dev/null
++++ b/drivers/infiniband/core/iter.c
+@@ -0,0 +1,43 @@
++// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
++
++#include <linux/export.h>
++#include <rdma/iter.h>
++
++void __rdma_block_iter_start(struct ib_block_iter *biter,
++                           struct scatterlist *sglist, unsigned int nents,
++                           unsigned long pgsz)
++{
++      memset(biter, 0, sizeof(struct ib_block_iter));
++      biter->__sg = sglist;
++      biter->__sg_nents = nents;
++
++      /* Driver provides best block size to use */
++      biter->__pg_bit = __fls(pgsz);
++}
++EXPORT_SYMBOL(__rdma_block_iter_start);
++
++bool __rdma_block_iter_next(struct ib_block_iter *biter)
++{
++      unsigned int block_offset;
++      unsigned int delta;
++
++      if (!biter->__sg_nents || !biter->__sg)
++              return false;
++
++      biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
++      block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
++      delta = BIT_ULL(biter->__pg_bit) - block_offset;
++
++      while (biter->__sg_nents && biter->__sg &&
++             sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
++              delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
++              biter->__sg_advance = 0;
++              biter->__sg = sg_next(biter->__sg);
++              biter->__sg_nents--;
++      }
++      biter->__sg_advance += delta;
++
++      return true;
++}
++EXPORT_SYMBOL(__rdma_block_iter_next);
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -3013,44 +3013,6 @@ int rdma_init_netdev(struct ib_device *d
+ }
+ EXPORT_SYMBOL(rdma_init_netdev);
+-void __rdma_block_iter_start(struct ib_block_iter *biter,
+-                           struct scatterlist *sglist, unsigned int nents,
+-                           unsigned long pgsz)
+-{
+-      memset(biter, 0, sizeof(struct ib_block_iter));
+-      biter->__sg = sglist;
+-      biter->__sg_nents = nents;
+-
+-      /* Driver provides best block size to use */
+-      biter->__pg_bit = __fls(pgsz);
+-}
+-EXPORT_SYMBOL(__rdma_block_iter_start);
+-
+-bool __rdma_block_iter_next(struct ib_block_iter *biter)
+-{
+-      unsigned int block_offset;
+-      unsigned int delta;
+-
+-      if (!biter->__sg_nents || !biter->__sg)
+-              return false;
+-
+-      biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
+-      block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
+-      delta = BIT_ULL(biter->__pg_bit) - block_offset;
+-
+-      while (biter->__sg_nents && biter->__sg &&
+-             sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
+-              delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
+-              biter->__sg_advance = 0;
+-              biter->__sg = sg_next(biter->__sg);
+-              biter->__sg_nents--;
+-      }
+-      biter->__sg_advance += delta;
+-
+-      return true;
+-}
+-EXPORT_SYMBOL(__rdma_block_iter_next);
+-
+ /**
+  * rdma_alloc_hw_stats_struct - Helper function to allocate dynamic struct
+  *   for the drivers.
+--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
+@@ -46,7 +46,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/vmalloc.h>
+ #include <rdma/ib_verbs.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include "roce_hsi.h"
+ #include "qplib_res.h"
+--- a/drivers/infiniband/hw/cxgb4/mem.c
++++ b/drivers/infiniband/hw/cxgb4/mem.c
+@@ -32,9 +32,9 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+-#include <rdma/ib_umem.h>
+ #include <linux/atomic.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+ #include "iw_cxgb4.h"
+--- a/drivers/infiniband/hw/efa/efa_verbs.c
++++ b/drivers/infiniband/hw/efa/efa_verbs.c
+@@ -9,9 +9,9 @@
+ #include <linux/log2.h>
+ #include <rdma/ib_addr.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/ib_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include "efa.h"
+--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
++++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
+@@ -12,7 +12,7 @@
+ #include <linux/vmalloc.h>
+ #include <net/addrconf.h>
+ #include <rdma/erdma-abi.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include "erdma.h"
+--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
++++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
+@@ -32,7 +32,7 @@
+  */
+ #include <linux/vmalloc.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include "hns_roce_device.h"
+ void hns_roce_buf_free(struct hns_roce_dev *hr_dev, struct hns_roce_buf *buf)
+--- a/drivers/infiniband/hw/irdma/main.h
++++ b/drivers/infiniband/hw/irdma/main.h
+@@ -37,8 +37,8 @@
+ #include <rdma/rdma_cm.h>
+ #include <rdma/iw_cm.h>
+ #include <rdma/ib_user_verbs.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include "osdep.h"
+ #include "defs.h"
+--- a/drivers/infiniband/hw/mana/mana_ib.h
++++ b/drivers/infiniband/hw/mana/mana_ib.h
+@@ -8,7 +8,7 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_mad.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include <rdma/mana-abi.h>
+ #include <rdma/uverbs_ioctl.h>
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -33,6 +33,7 @@
+ #include <linux/slab.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+ #include "mlx4_ib.h"
+--- a/drivers/infiniband/hw/mlx5/mem.c
++++ b/drivers/infiniband/hw/mlx5/mem.c
+@@ -32,6 +32,7 @@
+ #include <linux/io.h>
+ #include <rdma/ib_umem_odp.h>
++#include <rdma/iter.h>
+ #include "mlx5_ib.h"
+ #include <linux/jiffies.h>
+--- a/drivers/infiniband/hw/mlx5/umr.c
++++ b/drivers/infiniband/hw/mlx5/umr.c
+@@ -2,6 +2,7 @@
+ /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
+ #include <rdma/ib_umem_odp.h>
++#include <rdma/iter.h>
+ #include "mlx5_ib.h"
+ #include "umr.h"
+ #include "wr.h"
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -35,8 +35,8 @@
+  */
+ #include <rdma/ib_smi.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include <linux/sched.h>
+--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
++++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+@@ -45,9 +45,9 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/iw_cm.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include "ocrdma.h"
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -39,9 +39,9 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/iw_cm.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include <linux/qed/common_hsi.h>
+--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
+@@ -53,8 +53,8 @@
+ #include <linux/pci.h>
+ #include <linux/semaphore.h>
+ #include <linux/workqueue.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/vmw_pvrdma-abi.h>
+ #include "pvrdma_ring.h"
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -70,38 +70,6 @@ static inline size_t ib_umem_num_pages(s
+ {
+       return ib_umem_num_dma_blocks(umem, PAGE_SIZE);
+ }
+-
+-static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
+-                                              struct ib_umem *umem,
+-                                              unsigned long pgsz)
+-{
+-      __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
+-                              umem->sgt_append.sgt.nents, pgsz);
+-      biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
+-      biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
+-}
+-
+-static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
+-{
+-      return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
+-}
+-
+-/**
+- * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+- * @umem: umem to iterate over
+- * @biter: block iterator variable
+- * @pgsz: Page size to split the list into
+- *
+- * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+- * returned DMA blocks will be aligned to pgsz and span the range:
+- * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
+- *
+- * Performs exactly ib_umem_num_dma_blocks() iterations.
+- */
+-#define rdma_umem_for_each_dma_block(umem, biter, pgsz)                        \
+-      for (__rdma_umem_block_iter_start(biter, umem, pgsz);                  \
+-           __rdma_umem_block_iter_next(biter);)
+-
+ #ifdef CONFIG_INFINIBAND_USER_MEM
+ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
+--- a/include/rdma/ib_verbs.h
++++ b/include/rdma/ib_verbs.h
+@@ -2839,22 +2839,6 @@ struct ib_client {
+       u8 no_kverbs_req:1;
+ };
+-/*
+- * IB block DMA iterator
+- *
+- * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
+- * to a HW supported page size.
+- */
+-struct ib_block_iter {
+-      /* internal states */
+-      struct scatterlist *__sg;       /* sg holding the current aligned block */
+-      dma_addr_t __dma_addr;          /* unaligned DMA address of this block */
+-      size_t __sg_numblocks;          /* ib_umem_num_dma_blocks() */
+-      unsigned int __sg_nents;        /* number of SG entries */
+-      unsigned int __sg_advance;      /* number of bytes to advance in sg in next step */
+-      unsigned int __pg_bit;          /* alignment of current block */
+-};
+-
+ struct ib_device *_ib_alloc_device(size_t size);
+ #define ib_alloc_device(drv_struct, member)                                    \
+       container_of(_ib_alloc_device(sizeof(struct drv_struct) +              \
+@@ -2876,38 +2860,6 @@ void ib_unregister_device_queued(struct
+ int ib_register_client   (struct ib_client *client);
+ void ib_unregister_client(struct ib_client *client);
+-void __rdma_block_iter_start(struct ib_block_iter *biter,
+-                           struct scatterlist *sglist,
+-                           unsigned int nents,
+-                           unsigned long pgsz);
+-bool __rdma_block_iter_next(struct ib_block_iter *biter);
+-
+-/**
+- * rdma_block_iter_dma_address - get the aligned dma address of the current
+- * block held by the block iterator.
+- * @biter: block iterator holding the memory block
+- */
+-static inline dma_addr_t
+-rdma_block_iter_dma_address(struct ib_block_iter *biter)
+-{
+-      return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
+-}
+-
+-/**
+- * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
+- * @sglist: sglist to iterate over
+- * @biter: block iterator holding the memory block
+- * @nents: maximum number of sg entries to iterate over
+- * @pgsz: best HW supported page size to use
+- *
+- * Callers may use rdma_block_iter_dma_address() to get each
+- * blocks aligned DMA address.
+- */
+-#define rdma_for_each_block(sglist, biter, nents, pgsz)               \
+-      for (__rdma_block_iter_start(biter, sglist, nents,      \
+-                                   pgsz);                     \
+-           __rdma_block_iter_next(biter);)
+-
+ /**
+  * ib_get_client_data - Get IB client context
+  * @device:Device to get context for
+--- /dev/null
++++ b/include/rdma/iter.h
+@@ -0,0 +1,88 @@
++/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
++
++#ifndef _RDMA_ITER_H_
++#define _RDMA_ITER_H_
++
++#include <linux/scatterlist.h>
++#include <rdma/ib_umem.h>
++
++/**
++ * IB block DMA iterator
++ *
++ * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
++ * to a HW supported page size.
++ */
++struct ib_block_iter {
++      /* internal states */
++      struct scatterlist *__sg;       /* sg holding the current aligned block */
++      dma_addr_t __dma_addr;          /* unaligned DMA address of this block */
++      size_t __sg_numblocks;          /* ib_umem_num_dma_blocks() */
++      unsigned int __sg_nents;        /* number of SG entries */
++      unsigned int __sg_advance;      /* number of bytes to advance in sg in next step */
++      unsigned int __pg_bit;          /* alignment of current block */
++};
++
++void __rdma_block_iter_start(struct ib_block_iter *biter,
++                           struct scatterlist *sglist,
++                           unsigned int nents,
++                           unsigned long pgsz);
++bool __rdma_block_iter_next(struct ib_block_iter *biter);
++
++/**
++ * rdma_block_iter_dma_address - get the aligned dma address of the current
++ * block held by the block iterator.
++ * @biter: block iterator holding the memory block
++ */
++static inline dma_addr_t
++rdma_block_iter_dma_address(struct ib_block_iter *biter)
++{
++      return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
++}
++
++/**
++ * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
++ * @sglist: sglist to iterate over
++ * @biter: block iterator holding the memory block
++ * @nents: maximum number of sg entries to iterate over
++ * @pgsz: best HW supported page size to use
++ *
++ * Callers may use rdma_block_iter_dma_address() to get each
++ * blocks aligned DMA address.
++ */
++#define rdma_for_each_block(sglist, biter, nents, pgsz)               \
++      for (__rdma_block_iter_start(biter, sglist, nents,      \
++                                   pgsz);                     \
++           __rdma_block_iter_next(biter);)
++
++static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
++                                              struct ib_umem *umem,
++                                              unsigned long pgsz)
++{
++      __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
++                              umem->sgt_append.sgt.nents, pgsz);
++      biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
++      biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
++}
++
++static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
++{
++      return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
++}
++
++/**
++ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
++ * @umem: umem to iterate over
++ * @pgsz: Page size to split the list into
++ *
++ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
++ * returned DMA blocks will be aligned to pgsz and span the range:
++ * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
++ *
++ * Performs exactly ib_umem_num_dma_blocks() iterations.
++ */
++#define rdma_umem_for_each_dma_block(umem, biter, pgsz)                        \
++      for (__rdma_umem_block_iter_start(biter, umem, pgsz);                  \
++           __rdma_umem_block_iter_next(biter);)
++
++#endif /* _RDMA_ITER_H_ */
diff --git a/queue-6.6/rdma-umem-fix-kernel-doc-warnings.patch b/queue-6.6/rdma-umem-fix-kernel-doc-warnings.patch
new file mode 100644 (file)
index 0000000..0156ae6
--- /dev/null
@@ -0,0 +1,60 @@
+From stable+bounces-263488-greg=kroah.com@vger.kernel.org Tue Jun 16 05:30:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 19:58:46 -0400
+Subject: RDMA/umem: fix kernel-doc warnings
+To: stable@vger.kernel.org
+Cc: Randy Dunlap <rdunlap@infradead.org>, Leon Romanovsky <leon@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615235848.2562462-1-sashal@kernel.org>
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit ff46d1392750444fab5ae5a0194764ffdc4ac0d2 ]
+
+Add or correct kernel-doc comments to eliminate warnings:
+
+Warning: include/rdma/ib_umem.h:104 function parameter 'biter' not
+ described in 'rdma_umem_for_each_dma_block'
+Warning: include/rdma/ib_umem.h:140 function parameter 'pgsz_bitmap' not
+ described in 'ib_umem_find_best_pgoff'
+Warning: include/rdma/ib_umem.h:141 No description found for return
+ value of 'ib_umem_find_best_pgoff'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Link: https://patch.msgid.link/20260224003120.3173892-1-rdunlap@infradead.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/rdma/ib_umem.h |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -89,6 +89,7 @@ static inline bool __rdma_umem_block_ite
+ /**
+  * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+  * @umem: umem to iterate over
++ * @biter: block iterator variable
+  * @pgsz: Page size to split the list into
+  *
+  * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+@@ -116,7 +117,7 @@ unsigned long ib_umem_find_best_pgsz(str
+  * ib_umem_find_best_pgoff - Find best HW page size
+  *
+  * @umem: umem struct
+- * @pgsz_bitmap bitmap of HW supported page sizes
++ * @pgsz_bitmap: bitmap of HW supported page sizes
+  * @pgoff_bitmask: Mask of bits that can be represented with an offset
+  *
+  * This is very similar to ib_umem_find_best_pgsz() except instead of accepting
+@@ -129,6 +130,9 @@ unsigned long ib_umem_find_best_pgsz(str
+  *
+  * If the pgoff_bitmask requires either alignment in the low bit or an
+  * unavailable page size for the high bits, this function returns 0.
++ *
++ * Returns: best HW page size for the parameters or 0 if none available
++ *   for the given parameters.
+  */
+ static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem,
+                                                   unsigned long pgsz_bitmap,
diff --git a/queue-6.6/rdma-umem-fix-truncation-for-block-sizes-4g.patch b/queue-6.6/rdma-umem-fix-truncation-for-block-sizes-4g.patch
new file mode 100644 (file)
index 0000000..ddc8e41
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-263490-greg=kroah.com@vger.kernel.org Tue Jun 16 05:29:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 19:58:48 -0400
+Subject: RDMA/umem: Fix truncation for block sizes >= 4G
+To: stable@vger.kernel.org
+Cc: Jason Gunthorpe <jgg@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615235848.2562462-3-sashal@kernel.org>
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 15fe76e23615f502d051ef0768f86babaf08746c ]
+
+When the iommu is used the linearization of the mapping can give a single
+block that is very large split across multiple SG entries.
+
+When __rdma_block_iter_next() reassembles the split SG entries it is
+overflowing the 32 bit stack values and computed the wrong DMA addresses
+for blocks after the truncation.
+
+Use the right types to hold DMA addresses.
+
+Link: https://patch.msgid.link/r/1-v1-88303e9e509f+f7-ib_umem_types_jgg@nvidia.com
+Cc: stable@vger.kernel.org
+Fixes: a808273a495c ("RDMA/verbs: Add a DMA iterator to return aligned contiguous memory blocks")
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/iter.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/core/iter.c
++++ b/drivers/infiniband/core/iter.c
+@@ -19,8 +19,8 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
+ bool __rdma_block_iter_next(struct ib_block_iter *biter)
+ {
+-      unsigned int block_offset;
+-      unsigned int delta;
++      dma_addr_t block_offset;
++      dma_addr_t delta;
+       if (!biter->__sg_nents || !biter->__sg)
+               return false;
diff --git a/queue-6.6/scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch b/queue-6.6/scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch
new file mode 100644 (file)
index 0000000..d77d8e1
--- /dev/null
@@ -0,0 +1,124 @@
+From stable+bounces-260871-greg=kroah.com@vger.kernel.org Sat Jun  6 17:50:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  6 Jun 2026 08:19:09 -0400
+Subject: scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd()
+To: stable@vger.kernel.org
+Cc: Michael Bommarito <michael.bommarito@gmail.com>, John Garry <john.g.garry@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260606121909.2851630-1-sashal@kernel.org>
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit 778c2ab142c625a8a8afa570e0f9b7873f445d99 ]
+
+Two latent bugs in the Text-phase handler, both present since the
+original LIO integration in commit e48354ce078c ("iscsi-target: Add
+iSCSI fabric support for target v4.1"):
+
+1) DataDigest CRC buffer overread (4 bytes past text_in).
+
+   text_in is kzalloc()'d at ALIGN(payload_length, 4).  rx_size is then
+   incremented by ISCSI_CRC_LEN to make room for the received DataDigest
+   in the iovec, but the same (now-bumped) rx_size is passed as the
+   buffer length to iscsit_crc_buf():
+
+       if (conn->conn_ops->DataDigest) {
+               ...
+               rx_size += ISCSI_CRC_LEN;
+       }
+       ...
+       if (conn->conn_ops->DataDigest) {
+               data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL);
+
+   iscsit_crc_buf() walks rx_size bytes of text_in with crc32c(), so
+   when DataDigest is negotiated it reads 4 bytes past the end of the
+   text_in allocation.  KASAN reproduces this directly on the unpatched
+   mainline tree as slab-out-of-bounds in crc32c() called from the Text
+   PDU path.  The OOB bytes feed crc32c() and are then compared against
+   the initiator-supplied checksum, so the value does not flow back to
+   the attacker, but the kernel does read past the buffer on every Text
+   PDU with DataDigest=CRC32C.
+
+   Fix by passing the actual padded payload length
+   (ALIGN(payload_length, 4)) that was used for the kzalloc().
+
+2) Stale cmd->text_in_ptr re-free (double-free) on ERL>0 bad DataDigest
+   drop.
+
+   On DataDigest mismatch with ErrorRecoveryLevel > 0 the handler
+   silently drops the PDU and lets the initiator plug the CmdSN gap:
+
+               kfree(text_in);
+               return 0;
+
+   cmd->text_in_ptr still points at the freed buffer.  The next Text
+   Request on the same ITT re-enters iscsit_setup_text_cmd(), which
+   unconditionally does
+
+       kfree(cmd->text_in_ptr);
+       cmd->text_in_ptr = NULL;
+
+   freeing the same pointer a second time.  Session teardown via
+   iscsit_release_cmd() has the same shape and hits the same double-free
+   if the connection is dropped before a second Text Request arrives.
+
+   On an unmodified mainline tree the bug-1 CRC overread fires first on
+   the initial valid Text Request and perturbs the subsequent state, so
+   #4 was isolated by building a kernel with only the bug-1 hunk of this
+   patch applied plus temporary printk() observability around the three
+   relevant kfree() sites.  The observability prints are not part of
+   this patch.  On that build, a three-PDU Text Request sequence after
+   login produces two back-to-back splats:
+
+       BUG: KASAN: double-free in iscsit_setup_text_cmd+0x??
+       BUG: KASAN: double-free in iscsit_release_cmd+0x??
+
+   showing the same pointer freed in the ERL>0 drop path and again in
+   iscsit_setup_text_cmd() (next Text Request on the same ITT) and once
+   more in iscsit_release_cmd() (session teardown).  On distro kernels
+   with CONFIG_SLAB_FREELIST_HARDENED=y (default) the double-free
+   becomes a remote kernel BUG(); on non-hardened kernels it corrupts
+   the slab freelist.
+
+   Fix by clearing cmd->text_in_ptr after the kfree() in the ERL>0 drop
+   path.  With both hunks applied #4 is directly observable on the stock
+   tree without observability printks; fixing bug-1 alone would mask #4
+   less, not more, so the hunks are submitted together.
+
+Both fixes are one-liners.  The Text PDU state machine is unchanged and
+the wire protocol is unaffected.
+
+Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Tested-by: John Garry <john.g.garry@oracle.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/target/iscsi/iscsi_target.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -2335,8 +2335,9 @@ iscsit_handle_text_cmd(struct iscsit_con
+               if (conn->conn_ops->DataDigest) {
+                       iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
+-                                                text_in, rx_size, 0, NULL,
+-                                                &data_crc);
++                                                text_in,
++                                                ALIGN(payload_length, 4),
++                                                0, NULL, &data_crc);
+                       if (checksum != data_crc) {
+                               pr_err("Text data CRC32C DataDigest"
+@@ -2356,6 +2357,7 @@ iscsit_handle_text_cmd(struct iscsit_con
+                                       " Command CmdSN: 0x%08x due to"
+                                       " DataCRC error.\n", hdr->cmdsn);
+                                       kfree(text_in);
++                                      cmd->text_in_ptr = NULL;
+                                       return 0;
+                               }
+                       } else {
diff --git a/queue-6.6/serial-qcom_geni-fix-kfifo-underflow-when-flush-precedes-dma-completion-irq.patch b/queue-6.6/serial-qcom_geni-fix-kfifo-underflow-when-flush-precedes-dma-completion-irq.patch
new file mode 100644 (file)
index 0000000..1f54171
--- /dev/null
@@ -0,0 +1,69 @@
+From stable+bounces-260880-greg=kroah.com@vger.kernel.org Sat Jun  6 18:19:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  6 Jun 2026 08:49:44 -0400
+Subject: serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ
+To: stable@vger.kernel.org
+Cc: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>, stable <stable@kernel.org>, Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260606124944.2878832-1-sashal@kernel.org>
+
+From: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
+
+[ Upstream commit 452d6fa37ae9b021f4f6d397dbae077f7296f6f4 ]
+
+When uart_flush_buffer() runs before the DMA completion IRQ is delivered,
+the following race can occur (all steps serialized by uart_port_lock):
+
+  1. DMA starts: tx_remaining = N, kfifo contains N bytes
+  2. DMA completes in hardware; IRQ is pending but not yet delivered
+  3. uart_flush_buffer() acquires the port lock and calls kfifo_reset(),
+     making kfifo_len() = 0 while tx_remaining remains N
+  4. uart_flush_buffer() releases the port lock
+  5. DMA IRQ fires; handle_tx_dma() acquires the port lock and calls
+     uart_xmit_advance(uport, tx_remaining) on an empty kfifo
+
+uart_xmit_advance() increments kfifo->out by tx_remaining. Since
+kfifo_reset() already set both in and out to 0, out wraps past in,
+causing kfifo_len() to return UART_XMIT_SIZE - tx_remaining. The next
+start_tx_dma() call then submits a DMA transfer of stale buffer data.
+
+Fix this by snapshotting kfifo_len() at the start of handle_tx_dma()
+and skipping uart_xmit_advance() when fifo_len < tx_remaining, which
+indicates the kfifo was reset by a preceding flush.
+
+Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260506-serial-dma-stale-tx-buf-v1-1-e3ccb360d719@oss.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/qcom_geni_serial.c |   15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/qcom_geni_serial.c
++++ b/drivers/tty/serial/qcom_geni_serial.c
+@@ -962,8 +962,21 @@ static void qcom_geni_serial_handle_tx_d
+ {
+       struct qcom_geni_serial_port *port = to_dev_port(uport);
+       struct circ_buf *xmit = &uport->state->xmit;
++      unsigned int chars_pending = uart_circ_chars_pending(xmit);
++
++      /*
++       * Only advance the buffer if it still contains the bytes that were
++       * transferred. uart_flush_buffer() may have run before this IRQ
++       * fired: it clears the circular buffer under the port lock, making
++       * chars_pending = 0 while tx_remaining remains non-zero. Calling
++       * uart_xmit_advance() in that case would advance xmit->tail past
++       * xmit->head, making uart_circ_chars_pending() wrap to
++       * UART_XMIT_SIZE - tx_remaining and triggering a spurious large DMA
++       * transfer of stale data.
++       */
++      if (chars_pending >= port->tx_remaining)
++              uart_xmit_advance(uport, port->tx_remaining);
+-      uart_xmit_advance(uport, port->tx_remaining);
+       geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining);
+       port->tx_dma_addr = 0;
+       port->tx_remaining = 0;
diff --git a/queue-6.6/serial-samsung_tty-use-port-lock-wrappers.patch b/queue-6.6/serial-samsung_tty-use-port-lock-wrappers.patch
new file mode 100644 (file)
index 0000000..160d769
--- /dev/null
@@ -0,0 +1,254 @@
+From stable+bounces-260700-greg=kroah.com@vger.kernel.org Fri Jun  5 19:23:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 09:53:22 -0400
+Subject: serial: samsung_tty: Use port lock wrappers
+To: stable@vger.kernel.org
+Cc: Thomas Gleixner <tglx@linutronix.de>, John Ogness <john.ogness@linutronix.de>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605135324.928676-1-sashal@kernel.org>
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 97d7a9aeba1d424c2359f1686d02c75d798ad184 ]
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-54-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/samsung_tty.c |   50 +++++++++++++++++++--------------------
+ 1 file changed, 25 insertions(+), 25 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -248,7 +248,7 @@ static void s3c24xx_serial_rx_enable(str
+       unsigned int ucon, ufcon;
+       int count = 10000;
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       while (--count && !s3c24xx_serial_txempty_nofifo(port))
+               udelay(100);
+@@ -262,7 +262,7 @@ static void s3c24xx_serial_rx_enable(str
+       wr_regl(port, S3C2410_UCON, ucon);
+       ourport->rx_enabled = 1;
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+ }
+ static void s3c24xx_serial_rx_disable(struct uart_port *port)
+@@ -271,14 +271,14 @@ static void s3c24xx_serial_rx_disable(st
+       unsigned long flags;
+       unsigned int ucon;
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       ucon = rd_regl(port, S3C2410_UCON);
+       ucon &= ~S3C2410_UCON_RXIRQMODE;
+       wr_regl(port, S3C2410_UCON, ucon);
+       ourport->rx_enabled = 0;
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+ }
+ static void s3c24xx_serial_stop_tx(struct uart_port *port)
+@@ -344,7 +344,7 @@ static void s3c24xx_serial_tx_dma_comple
+                               dma->tx_transfer_addr, dma->tx_size,
+                               DMA_TO_DEVICE);
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       uart_xmit_advance(port, count);
+       ourport->tx_in_progress = 0;
+@@ -353,7 +353,7 @@ static void s3c24xx_serial_tx_dma_comple
+               uart_write_wakeup(port);
+       s3c24xx_serial_start_next_tx(ourport);
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+ }
+ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
+@@ -619,7 +619,7 @@ static void s3c24xx_serial_rx_dma_comple
+       received  = dma->rx_bytes_requested - state.residue;
+       async_tx_ack(dma->rx_desc);
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       if (received)
+               s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
+@@ -631,7 +631,7 @@ static void s3c24xx_serial_rx_dma_comple
+       s3c64xx_start_rx_dma(ourport);
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+ }
+ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
+@@ -722,7 +722,7 @@ static irqreturn_t s3c24xx_serial_rx_cha
+       utrstat = rd_regl(port, S3C2410_UTRSTAT);
+       rd_regl(port, S3C2410_UFSTAT);
+-      spin_lock(&port->lock);
++      uart_port_lock(port);
+       if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) {
+               s3c64xx_start_rx_dma(ourport);
+@@ -751,7 +751,7 @@ static irqreturn_t s3c24xx_serial_rx_cha
+       wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT);
+ finish:
+-      spin_unlock(&port->lock);
++      uart_port_unlock(port);
+       return IRQ_HANDLED;
+ }
+@@ -849,9 +849,9 @@ static irqreturn_t s3c24xx_serial_rx_cha
+       struct s3c24xx_uart_port *ourport = dev_id;
+       struct uart_port *port = &ourport->port;
+-      spin_lock(&port->lock);
++      uart_port_lock(port);
+       s3c24xx_serial_rx_drain_fifo(ourport);
+-      spin_unlock(&port->lock);
++      uart_port_unlock(port);
+       return IRQ_HANDLED;
+ }
+@@ -932,11 +932,11 @@ static irqreturn_t s3c24xx_serial_tx_irq
+       struct s3c24xx_uart_port *ourport = id;
+       struct uart_port *port = &ourport->port;
+-      spin_lock(&port->lock);
++      uart_port_lock(port);
+       s3c24xx_serial_tx_chars(ourport);
+-      spin_unlock(&port->lock);
++      uart_port_unlock(port);
+       return IRQ_HANDLED;
+ }
+@@ -1032,7 +1032,7 @@ static void s3c24xx_serial_break_ctl(str
+       unsigned long flags;
+       unsigned int ucon;
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       ucon = rd_regl(port, S3C2410_UCON);
+@@ -1043,7 +1043,7 @@ static void s3c24xx_serial_break_ctl(str
+       wr_regl(port, S3C2410_UCON, ucon);
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+ }
+ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
+@@ -1302,7 +1302,7 @@ static int s3c64xx_serial_startup(struct
+       ourport->rx_enabled = 1;
+       ourport->tx_enabled = 0;
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       ufcon = rd_regl(port, S3C2410_UFCON);
+       ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+@@ -1312,7 +1312,7 @@ static int s3c64xx_serial_startup(struct
+       enable_rx_pio(ourport);
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+       /* Enable Rx Interrupt */
+       s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
+@@ -1340,7 +1340,7 @@ static int apple_s5l_serial_startup(stru
+       ourport->rx_enabled = 1;
+       ourport->tx_enabled = 0;
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       ufcon = rd_regl(port, S3C2410_UFCON);
+       ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+@@ -1350,7 +1350,7 @@ static int apple_s5l_serial_startup(stru
+       enable_rx_pio(ourport);
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+       /* Enable Rx Interrupt */
+       s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
+@@ -1625,7 +1625,7 @@ static void s3c24xx_serial_set_termios(s
+               ulcon |= S3C2410_LCON_PNONE;
+       }
+-      spin_lock_irqsave(&port->lock, flags);
++      uart_port_lock_irqsave(port, &flags);
+       dev_dbg(port->dev,
+               "setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
+@@ -1683,7 +1683,7 @@ static void s3c24xx_serial_set_termios(s
+       if ((termios->c_cflag & CREAD) == 0)
+               port->ignore_status_mask |= RXSTAT_DUMMY_READ;
+-      spin_unlock_irqrestore(&port->lock, flags);
++      uart_port_unlock_irqrestore(port, flags);
+ }
+ static const char *s3c24xx_serial_type(struct uart_port *port)
+@@ -2375,14 +2375,14 @@ s3c24xx_serial_console_write(struct cons
+       if (cons_uart->sysrq)
+               locked = false;
+       else if (oops_in_progress)
+-              locked = spin_trylock_irqsave(&cons_uart->lock, flags);
++              locked = uart_port_trylock_irqsave(cons_uart, &flags);
+       else
+-              spin_lock_irqsave(&cons_uart->lock, flags);
++              uart_port_lock_irqsave(cons_uart, &flags);
+       uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
+       if (locked)
+-              spin_unlock_irqrestore(&cons_uart->lock, flags);
++              uart_port_unlock_irqrestore(cons_uart, flags);
+ }
+ /* Shouldn't be __init, as it can be instantiated from other module */
index df6775514da01a6ceb9843ee2b9eecafd9619137..906a64334509f36d3edf0ed5b205c2fe1822b277 100644 (file)
@@ -406,3 +406,32 @@ serdev-provide-a-bustype-shutdown-function.patch
 bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch
 bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch
 mptcp-handle-first-subflow-closing-consistently.patch
+iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch
+iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch
+iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch
+usb-cdns3-plat-fix-leaked-usb2_phy-initialization-on-usb3_phy-acquisition-failure.patch
+iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch
+memfd-deny-writeable-mappings-when-implying-seal_write.patch
+alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch
+serial-samsung_tty-use-port-lock-wrappers.patch
+tty-serial-samsung-use-u32-for-register-interactions.patch
+tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch
+usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch
+usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch
+usb-gadget-uvc-hold-opts-lock-across-xu-walks-in-uvc_function_bind.patch
+usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch
+thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch
+scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch
+serial-qcom_geni-fix-kfifo-underflow-when-flush-precedes-dma-completion-irq.patch
+usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch
+netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch
+mm-hugetlb-rename-isolate_hugetlb-to-folio_isolate_hugetlb.patch
+mm-migrate-don-t-call-folio_putback_active_hugetlb-on-dst-hugetlb-folio.patch
+mm-hugetlb-rename-folio_putback_active_hugetlb-to-folio_putback_hugetlb.patch
+mm-memory-failure-fix-missing-mf_stats-count-in-hugetlb-poison.patch
+mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch
+hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch
+rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch
+rdma-umem-fix-kernel-doc-warnings.patch
+rdma-move-dma-block-iterator-logic-into-dedicated-files.patch
+rdma-umem-fix-truncation-for-block-sizes-4g.patch
diff --git a/queue-6.6/thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch b/queue-6.6/thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch
new file mode 100644 (file)
index 0000000..7b70303
--- /dev/null
@@ -0,0 +1,112 @@
+From stable+bounces-260811-greg=kroah.com@vger.kernel.org Sat Jun  6 01:17:55 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 15:42:47 -0400
+Subject: thunderbolt: property: Cap recursion depth in __tb_property_parse_dir()
+To: stable@vger.kernel.org
+Cc: Michael Bommarito <michael.bommarito@gmail.com>, Mika Westerberg <mika.westerberg@linux.intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605194247.2177334-1-sashal@kernel.org>
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit 928abe19fbf0127003abcb1ea69cabc1c897d0ab ]
+
+A DIRECTORY entry's value field is used as the dir_offset for a
+recursive call into __tb_property_parse_dir() with no depth counter.
+A crafted peer that chains DIRECTORY entries into a back-reference
+loop drives the parser until the kernel stack is exhausted and the
+guard page fires.  Any untrusted XDomain peer (cable, dock, in-line
+inspector, adjacent host) that reaches the PROPERTIES_REQUEST
+control-plane exchange can trigger this without authentication.
+
+Thread a depth counter through tb_property_parse() and
+__tb_property_parse_dir(), and reject blocks that exceed
+TB_PROPERTY_MAX_DEPTH = 8.  That is comfortably larger than any
+observed legitimate XDomain layout.
+
+Operators who do not need XDomain host-to-host discovery can disable
+the path entirely with thunderbolt.xdomain=0 on the kernel command
+line.
+
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Assisted-by: Codex:gpt-5-4
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/property.c |   18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -35,10 +35,11 @@ struct tb_property_dir_entry {
+ };
+ #define TB_PROPERTY_ROOTDIR_MAGIC     0x55584401
++#define TB_PROPERTY_MAX_DEPTH         8
+ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
+       size_t block_len, unsigned int dir_offset, size_t dir_len,
+-      bool is_root);
++      bool is_root, unsigned int depth);
+ static inline void parse_dwdata(void *dst, const void *src, size_t dwords)
+ {
+@@ -99,7 +100,8 @@ tb_property_alloc(const char *key, enum
+ }
+ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
+-                                      const struct tb_property_entry *entry)
++                                      const struct tb_property_entry *entry,
++                                      unsigned int depth)
+ {
+       char key[TB_PROPERTY_KEY_SIZE + 1];
+       struct tb_property *property;
+@@ -120,7 +122,7 @@ static struct tb_property *tb_property_p
+       switch (property->type) {
+       case TB_PROPERTY_TYPE_DIRECTORY:
+               dir = __tb_property_parse_dir(block, block_len, entry->value,
+-                                            entry->length, false);
++                                            entry->length, false, depth + 1);
+               if (!dir) {
+                       kfree(property);
+                       return NULL;
+@@ -165,13 +167,17 @@ static struct tb_property *tb_property_p
+ }
+ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
+-      size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root)
++      size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root,
++      unsigned int depth)
+ {
+       const struct tb_property_entry *entries;
+       size_t i, content_len, nentries;
+       unsigned int content_offset;
+       struct tb_property_dir *dir;
++      if (depth > TB_PROPERTY_MAX_DEPTH)
++              return NULL;
++
+       dir = kzalloc(sizeof(*dir), GFP_KERNEL);
+       if (!dir)
+               return NULL;
+@@ -206,7 +212,7 @@ static struct tb_property_dir *__tb_prop
+       for (i = 0; i < nentries; i++) {
+               struct tb_property *property;
+-              property = tb_property_parse(block, block_len, &entries[i]);
++              property = tb_property_parse(block, block_len, &entries[i], depth);
+               if (!property) {
+                       tb_property_free_dir(dir);
+                       return NULL;
+@@ -243,7 +249,7 @@ struct tb_property_dir *tb_property_pars
+               return NULL;
+       return __tb_property_parse_dir(block, block_len, 0, rootdir->length,
+-                                     true);
++                                     true, 0);
+ }
+ /**
diff --git a/queue-6.6/tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch b/queue-6.6/tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch
new file mode 100644 (file)
index 0000000..b0a98b4
--- /dev/null
@@ -0,0 +1,85 @@
+From sashal@kernel.org Fri Jun  5 19:23:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 09:53:24 -0400
+Subject: tty: serial: samsung: Remove redundant port lock acquisition in rx helpers
+To: stable@vger.kernel.org
+Cc: Tudor Ambarus <tudor.ambarus@linaro.org>, stable <stable@kernel.org>, John Ogness <john.ogness@linutronix.de>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605135324.928676-3-sashal@kernel.org>
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit a3bb136bff5e6a5e48cdd813246c9c4686feaaa9 ]
+
+Sashiko identified a deadlock when the console flow is engaged [1].
+
+When console flow control is enabled (UPF_CONS_FLOW),
+s3c24xx_serial_stop_tx() calls s3c24xx_serial_rx_enable() and
+s3c24xx_serial_start_tx() calls s3c24xx_serial_rx_disable().
+
+The serial core framework invokes the .stop_tx() and .start_tx()
+callbacks with the port->lock spinlock already held. Furthermore, all
+internal driver paths that invoke stop_tx (such as the DMA TX
+completion handler s3c24xx_serial_tx_dma_complete() or the PIO TX IRQ
+handler s3c24xx_serial_tx_irq()) also acquire port->lock prior to
+calling it. (Note that s3c24xx_serial_start_tx() is only invoked by the
+serial core).
+
+However, s3c24xx_serial_rx_enable() and s3c24xx_serial_rx_disable()
+unconditionally attempt to acquire port->lock again using
+uart_port_lock_irqsave(). Since spinlocks are not recursive, this
+causes a deadlock on the same CPU when console flow control is engaged.
+
+Remove the redundant lock acquisition from both rx helper functions.
+
+Cc: stable <stable@kernel.org>
+Fixes: b497549a035c ("[ARM] S3C24XX: Split serial driver into core and per-cpu drivers")
+Reported-by: John Ogness <john.ogness@linutronix.de>
+Closes: https://sashiko.dev/#/patchset/20260506121606.5805-1-john.ogness%40linutronix.de [1]
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Link: https://patch.msgid.link/20260515-samsung-tty-flow-control-deadlock-v1-1-93255edbc9bc@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/samsung_tty.c |    8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -244,12 +244,9 @@ static int s3c24xx_serial_txempty_nofifo
+ static void s3c24xx_serial_rx_enable(struct uart_port *port)
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+-      unsigned long flags;
+       int count = 10000;
+       u32 ucon, ufcon;
+-      uart_port_lock_irqsave(port, &flags);
+-
+       while (--count && !s3c24xx_serial_txempty_nofifo(port))
+               udelay(100);
+@@ -262,23 +259,18 @@ static void s3c24xx_serial_rx_enable(str
+       wr_regl(port, S3C2410_UCON, ucon);
+       ourport->rx_enabled = 1;
+-      uart_port_unlock_irqrestore(port, flags);
+ }
+ static void s3c24xx_serial_rx_disable(struct uart_port *port)
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+-      unsigned long flags;
+       u32 ucon;
+-      uart_port_lock_irqsave(port, &flags);
+-
+       ucon = rd_regl(port, S3C2410_UCON);
+       ucon &= ~S3C2410_UCON_RXIRQMODE;
+       wr_regl(port, S3C2410_UCON, ucon);
+       ourport->rx_enabled = 0;
+-      uart_port_unlock_irqrestore(port, flags);
+ }
+ static void s3c24xx_serial_stop_tx(struct uart_port *port)
diff --git a/queue-6.6/tty-serial-samsung-use-u32-for-register-interactions.patch b/queue-6.6/tty-serial-samsung-use-u32-for-register-interactions.patch
new file mode 100644 (file)
index 0000000..5b489dc
--- /dev/null
@@ -0,0 +1,353 @@
+From sashal@kernel.org Fri Jun  5 19:23:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 09:53:23 -0400
+Subject: tty: serial: samsung: use u32 for register interactions
+To: stable@vger.kernel.org
+Cc: Tudor Ambarus <tudor.ambarus@linaro.org>, Sam Protsenko <semen.protsenko@linaro.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605135324.928676-2-sashal@kernel.org>
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit 032a725c16add79332d774348d7ad7d0d4b86479 ]
+
+All registers of the IP have 32 bits. Use u32 variables when reading
+or writing from/to the registers. The purpose of those variables becomes
+clearer.
+
+Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Link: https://lore.kernel.org/r/20240119104526.1221243-9-tudor.ambarus@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/samsung_tty.c |   79 +++++++++++++++++++--------------------
+ 1 file changed, 39 insertions(+), 40 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -199,7 +199,7 @@ static void wr_reg(const struct uart_por
+ /* Byte-order aware bit setting/clearing functions. */
+ static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
+-                                 unsigned int reg)
++                                 u32 reg)
+ {
+       unsigned long flags;
+       u32 val;
+@@ -212,7 +212,7 @@ static inline void s3c24xx_set_bit(const
+ }
+ static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx,
+-                                   unsigned int reg)
++                                   u32 reg)
+ {
+       unsigned long flags;
+       u32 val;
+@@ -245,8 +245,8 @@ static void s3c24xx_serial_rx_enable(str
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+       unsigned long flags;
+-      unsigned int ucon, ufcon;
+       int count = 10000;
++      u32 ucon, ufcon;
+       uart_port_lock_irqsave(port, &flags);
+@@ -269,7 +269,7 @@ static void s3c24xx_serial_rx_disable(st
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+       unsigned long flags;
+-      unsigned int ucon;
++      u32 ucon;
+       uart_port_lock_irqsave(port, &flags);
+@@ -591,7 +591,7 @@ static inline const struct s3c2410_uartc
+ }
+ static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport,
+-                                   unsigned long ufstat)
++                                   u32 ufstat)
+ {
+       const struct s3c24xx_uart_info *info = ourport->info;
+@@ -663,7 +663,7 @@ static void s3c64xx_start_rx_dma(struct
+ static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
+ {
+       struct uart_port *port = &ourport->port;
+-      unsigned int ucon;
++      u32 ucon;
+       /* set Rx mode to DMA mode */
+       ucon = rd_regl(port, S3C2410_UCON);
+@@ -686,7 +686,7 @@ static void enable_rx_dma(struct s3c24xx
+ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
+ {
+       struct uart_port *port = &ourport->port;
+-      unsigned int ucon;
++      u32 ucon;
+       /* set Rx mode to DMA mode */
+       ucon = rd_regl(port, S3C2410_UCON);
+@@ -711,13 +711,14 @@ static void s3c24xx_serial_rx_drain_fifo
+ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
+ {
+-      unsigned int utrstat, received;
+       struct s3c24xx_uart_port *ourport = dev_id;
+       struct uart_port *port = &ourport->port;
+       struct s3c24xx_uart_dma *dma = ourport->dma;
+       struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
+       struct tty_port *t = &port->state->port;
+       struct dma_tx_state state;
++      unsigned int received;
++      u32 utrstat;
+       utrstat = rd_regl(port, S3C2410_UTRSTAT);
+       rd_regl(port, S3C2410_UFSTAT);
+@@ -759,9 +760,9 @@ finish:
+ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
+ {
+       struct uart_port *port = &ourport->port;
+-      unsigned int ufcon, ufstat, uerstat;
+       unsigned int fifocnt = 0;
+       int max_count = port->fifosize;
++      u32 ufcon, ufstat, uerstat;
+       u8 ch, flag;
+       while (max_count-- > 0) {
+@@ -945,7 +946,7 @@ static irqreturn_t s3c64xx_serial_handle
+ {
+       const struct s3c24xx_uart_port *ourport = id;
+       const struct uart_port *port = &ourport->port;
+-      unsigned int pend = rd_regl(port, S3C64XX_UINTP);
++      u32 pend = rd_regl(port, S3C64XX_UINTP);
+       irqreturn_t ret = IRQ_HANDLED;
+       if (pend & S3C64XX_UINTM_RXD_MSK) {
+@@ -964,7 +965,7 @@ static irqreturn_t apple_serial_handle_i
+ {
+       const struct s3c24xx_uart_port *ourport = id;
+       const struct uart_port *port = &ourport->port;
+-      unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
++      u32 pend = rd_regl(port, S3C2410_UTRSTAT);
+       irqreturn_t ret = IRQ_NONE;
+       if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
+@@ -983,8 +984,8 @@ static irqreturn_t apple_serial_handle_i
+ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
+ {
+       const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+-      unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
+-      unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
++      u32 ufstat = rd_regl(port, S3C2410_UFSTAT);
++      u32 ufcon = rd_regl(port, S3C2410_UFCON);
+       if (ufcon & S3C2410_UFCON_FIFOMODE) {
+               if ((ufstat & info->tx_fifomask) != 0 ||
+@@ -999,7 +1000,7 @@ static unsigned int s3c24xx_serial_tx_em
+ /* no modem control lines */
+ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
+ {
+-      unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
++      u32 umstat = rd_reg(port, S3C2410_UMSTAT);
+       if (umstat & S3C2410_UMSTAT_CTS)
+               return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+@@ -1009,8 +1010,8 @@ static unsigned int s3c24xx_serial_get_m
+ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+ {
+-      unsigned int umcon = rd_regl(port, S3C2410_UMCON);
+-      unsigned int ucon = rd_regl(port, S3C2410_UCON);
++      u32 umcon = rd_regl(port, S3C2410_UMCON);
++      u32 ucon = rd_regl(port, S3C2410_UCON);
+       if (mctrl & TIOCM_RTS)
+               umcon |= S3C2410_UMCOM_RTS_LOW;
+@@ -1030,7 +1031,7 @@ static void s3c24xx_serial_set_mctrl(str
+ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
+ {
+       unsigned long flags;
+-      unsigned int ucon;
++      u32 ucon;
+       uart_port_lock_irqsave(port, &flags);
+@@ -1211,7 +1212,7 @@ static void apple_s5l_serial_shutdown(st
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+-      unsigned int ucon;
++      u32 ucon;
+       ucon = rd_regl(port, S3C2410_UCON);
+       ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+@@ -1279,7 +1280,7 @@ static int s3c64xx_serial_startup(struct
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+       unsigned long flags;
+-      unsigned int ufcon;
++      u32 ufcon;
+       int ret;
+       wr_regl(port, S3C64XX_UINTM, 0xf);
+@@ -1324,7 +1325,7 @@ static int apple_s5l_serial_startup(stru
+ {
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+       unsigned long flags;
+-      unsigned int ufcon;
++      u32 ufcon;
+       int ret;
+       wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
+@@ -1409,7 +1410,7 @@ static void s3c24xx_serial_pm(struct uar
+ static inline int s3c24xx_serial_getsource(struct uart_port *port)
+ {
+       const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+-      unsigned int ucon;
++      u32 ucon;
+       if (info->num_clks == 1)
+               return 0;
+@@ -1423,7 +1424,7 @@ static void s3c24xx_serial_setsource(str
+                       unsigned int clk_sel)
+ {
+       const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+-      unsigned int ucon;
++      u32 ucon;
+       if (info->num_clks == 1)
+               return;
+@@ -1540,9 +1541,8 @@ static void s3c24xx_serial_set_termios(s
+       struct clk *clk = ERR_PTR(-EINVAL);
+       unsigned long flags;
+       unsigned int baud, quot, clk_sel = 0;
+-      unsigned int ulcon;
+-      unsigned int umcon;
+       unsigned int udivslot = 0;
++      u32 ulcon, umcon;
+       /*
+        * We don't support modem control lines.
+@@ -1849,7 +1849,7 @@ static void s3c24xx_serial_resetport(str
+                                    const struct s3c2410_uartcfg *cfg)
+ {
+       const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+-      unsigned long ucon = rd_regl(port, S3C2410_UCON);
++      u32 ucon = rd_regl(port, S3C2410_UCON);
+       ucon &= (info->clksel_mask | info->ucon_mask);
+       wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+@@ -2005,7 +2005,7 @@ static int s3c24xx_serial_init_port(stru
+               wr_regl(port, S3C64XX_UINTSP, 0xf);
+               break;
+       case TYPE_APPLE_S5L: {
+-              unsigned int ucon;
++              u32 ucon;
+               ucon = rd_regl(port, S3C2410_UCON);
+               ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+@@ -2212,7 +2212,7 @@ static int s3c24xx_serial_resume_noirq(s
+               /* restore IRQ mask */
+               switch (ourport->info->type) {
+               case TYPE_S3C6400: {
+-                      unsigned int uintm = 0xf;
++                      u32 uintm = 0xf;
+                       if (ourport->tx_enabled)
+                               uintm &= ~S3C64XX_UINTM_TXD_MSK;
+@@ -2228,7 +2228,7 @@ static int s3c24xx_serial_resume_noirq(s
+                       break;
+               }
+               case TYPE_APPLE_S5L: {
+-                      unsigned int ucon;
++                      u32 ucon;
+                       int ret;
+                       ret = clk_prepare_enable(ourport->clk);
+@@ -2290,10 +2290,10 @@ static const struct dev_pm_ops s3c24xx_s
+ static struct uart_port *cons_uart;
+ static int
+-s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
++s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon)
+ {
+       const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+-      unsigned long ufstat, utrstat;
++      u32 ufstat, utrstat;
+       if (ufcon & S3C2410_UFCON_FIFOMODE) {
+               /* fifo mode - check amount of data in fifo registers... */
+@@ -2309,7 +2309,7 @@ s3c24xx_serial_console_txrdy(struct uart
+ }
+ static bool
+-s3c24xx_port_configured(unsigned int ucon)
++s3c24xx_port_configured(u32 ucon)
+ {
+       /* consider the serial port configured if the tx/rx mode set */
+       return (ucon & 0xf) != 0;
+@@ -2324,7 +2324,7 @@ s3c24xx_port_configured(unsigned int uco
+ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
+ {
+       const struct s3c24xx_uart_port *ourport = to_ourport(port);
+-      unsigned int ufstat;
++      u32 ufstat;
+       ufstat = rd_regl(port, S3C2410_UFSTAT);
+       if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
+@@ -2336,8 +2336,8 @@ static int s3c24xx_serial_get_poll_char(
+ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
+               unsigned char c)
+ {
+-      unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
+-      unsigned int ucon = rd_regl(port, S3C2410_UCON);
++      u32 ufcon = rd_regl(port, S3C2410_UFCON);
++      u32 ucon = rd_regl(port, S3C2410_UCON);
+       /* not possible to xmit on unconfigured port */
+       if (!s3c24xx_port_configured(ucon))
+@@ -2353,7 +2353,7 @@ static void s3c24xx_serial_put_poll_char
+ static void
+ s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch)
+ {
+-      unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
++      u32 ufcon = rd_regl(port, S3C2410_UFCON);
+       while (!s3c24xx_serial_console_txrdy(port, ufcon))
+               cpu_relax();
+@@ -2364,7 +2364,7 @@ static void
+ s3c24xx_serial_console_write(struct console *co, const char *s,
+                            unsigned int count)
+ {
+-      unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
++      u32 ucon = rd_regl(cons_uart, S3C2410_UCON);
+       unsigned long flags;
+       bool locked = true;
+@@ -2391,11 +2391,9 @@ s3c24xx_serial_get_options(struct uart_p
+                          int *parity, int *bits)
+ {
+       struct clk *clk;
+-      unsigned int ulcon;
+-      unsigned int ucon;
+-      unsigned int ubrdiv;
+       unsigned long rate;
+       unsigned int clk_sel;
++      u32 ulcon, ucon, ubrdiv;
+       char clk_name[MAX_CLK_NAME_LENGTH];
+       ulcon  = rd_regl(port, S3C2410_ULCON);
+@@ -2806,7 +2804,8 @@ static int samsung_early_read(struct con
+ {
+       struct earlycon_device *dev = con->data;
+       const struct samsung_early_console_data *data = dev->port.private_data;
+-      int ch, ufstat, num_read = 0;
++      int num_read = 0;
++      u32 ch, ufstat;
+       while (num_read < n) {
+               ufstat = rd_regl(&dev->port, S3C2410_UFSTAT);
diff --git a/queue-6.6/usb-cdns3-plat-fix-leaked-usb2_phy-initialization-on-usb3_phy-acquisition-failure.patch b/queue-6.6/usb-cdns3-plat-fix-leaked-usb2_phy-initialization-on-usb3_phy-acquisition-failure.patch
new file mode 100644 (file)
index 0000000..7dbcf4c
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-260588-greg=kroah.com@vger.kernel.org Fri Jun  5 05:19:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  4 Jun 2026 19:49:13 -0400
+Subject: usb: cdns3: plat: fix leaked usb2_phy initialization on usb3_phy acquisition failure
+To: stable@vger.kernel.org
+Cc: Peter Chen <peter.chen@cixtech.com>, stable <stable@kernel.org>, sashiko-bot <sashiko-bot@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604234913.2468901-1-sashal@kernel.org>
+
+From: Peter Chen <peter.chen@cixtech.com>
+
+[ Upstream commit e6970cda63fd4b4546aeed9d0e2f53a7c95cd09c ]
+
+Move usb2_phy initialization after usb3_phy acquisition.
+
+Fixes: f738957277ba ("usb: cdns3: Split core.c into cdns3-plat and core.c file")
+Cc: stable <stable@kernel.org>
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://lore.kernel.org/linux-devicetree/agKaEePSFknhDBg2@nchen-desktop/T/#m21e1d9c1574eb127ce03c0c2a1a49002ce435b52
+Signed-off-by: Peter Chen <peter.chen@cixtech.com>
+Link: https://patch.msgid.link/20260513085310.2217547-2-peter.chen@cixtech.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/cdns3/cdns3-plat.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/cdns3/cdns3-plat.c
++++ b/drivers/usb/cdns3/cdns3-plat.c
+@@ -121,14 +121,14 @@ static int cdns3_plat_probe(struct platf
+       if (IS_ERR(cdns->usb2_phy))
+               return PTR_ERR(cdns->usb2_phy);
+-      ret = phy_init(cdns->usb2_phy);
+-      if (ret)
+-              return ret;
+-
+       cdns->usb3_phy = devm_phy_optional_get(dev, "cdns3,usb3-phy");
+       if (IS_ERR(cdns->usb3_phy))
+               return PTR_ERR(cdns->usb3_phy);
++      ret = phy_init(cdns->usb2_phy);
++      if (ret)
++              return ret;
++
+       ret = phy_init(cdns->usb3_phy);
+       if (ret)
+               goto err_phy3_init;
diff --git a/queue-6.6/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch b/queue-6.6/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch
new file mode 100644 (file)
index 0000000..cdf0d27
--- /dev/null
@@ -0,0 +1,95 @@
+From sashal@kernel.org Fri Jun  5 21:01:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 11:31:11 -0400
+Subject: usb: dwc3: xilinx: fix error handling in zynqmp init error paths
+To: stable@vger.kernel.org
+Cc: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605153111.1929312-1-sashal@kernel.org>
+
+From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+
+[ Upstream commit c1a0ecbf32c4b397353204e2ec94c5bb9f3300ed ]
+
+Fix error handling and resource cleanup i.e remove invalid
+phy_exit() after failed phy_init(), route failures through
+proper cleanup paths and return 0 explicitly on success.
+
+Fixes: 84770f028fab ("usb: dwc3: Add driver for Xilinx platforms")
+Cc: stable@vger.kernel.org
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Link: https://patch.msgid.link/20260519115529.2980421-1-radhey.shyam.pandey@amd.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/dwc3-xilinx.c |   26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/dwc3/dwc3-xilinx.c
++++ b/drivers/usb/dwc3/dwc3-xilinx.c
+@@ -170,15 +170,13 @@ static int dwc3_xlnx_init_zynqmp(struct
+       }
+       ret = phy_init(priv_data->usb3_phy);
+-      if (ret < 0) {
+-              phy_exit(priv_data->usb3_phy);
++      if (ret < 0)
+               goto err;
+-      }
+       ret = reset_control_deassert(apbrst);
+       if (ret < 0) {
+               dev_err(dev, "Failed to release APB reset\n");
+-              goto err;
++              goto err_phy_exit;
+       }
+       /* Set PIPE Power Present signal in FPD Power Present Register*/
+@@ -190,27 +188,25 @@ static int dwc3_xlnx_init_zynqmp(struct
+       ret = reset_control_deassert(crst);
+       if (ret < 0) {
+               dev_err(dev, "Failed to release core reset\n");
+-              goto err;
++              goto err_phy_exit;
+       }
+       ret = reset_control_deassert(hibrst);
+       if (ret < 0) {
+               dev_err(dev, "Failed to release hibernation reset\n");
+-              goto err;
++              goto err_phy_exit;
+       }
+       ret = phy_power_on(priv_data->usb3_phy);
+-      if (ret < 0) {
+-              phy_exit(priv_data->usb3_phy);
+-              goto err;
+-      }
++      if (ret < 0)
++              goto err_phy_exit;
+ skip_usb3_phy:
+       /* ulpi reset via gpio-modepin or gpio-framework driver */
+       reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(reset_gpio)) {
+-              return dev_err_probe(dev, PTR_ERR(reset_gpio),
+-                                   "Failed to request reset GPIO\n");
++              ret = PTR_ERR(reset_gpio);
++              goto err_phy_power_off;
+       }
+       if (reset_gpio) {
+@@ -230,6 +226,12 @@ skip_usb3_phy:
+               writel(reg, priv_data->regs + XLNX_USB_TRAFFIC_ROUTE_CONFIG);
+       }
++      return 0;
++
++err_phy_power_off:
++      phy_power_off(priv_data->usb3_phy);
++err_phy_exit:
++      phy_exit(priv_data->usb3_phy);
+ err:
+       return ret;
+ }
diff --git a/queue-6.6/usb-gadget-uvc-hold-opts-lock-across-xu-walks-in-uvc_function_bind.patch b/queue-6.6/usb-gadget-uvc-hold-opts-lock-across-xu-walks-in-uvc_function_bind.patch
new file mode 100644 (file)
index 0000000..82f946c
--- /dev/null
@@ -0,0 +1,133 @@
+From sashal@kernel.org Sat Jun  6 00:01:30 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 14:31:27 -0400
+Subject: usb: gadget: uvc: hold opts->lock across XU walks in uvc_function_bind
+To: stable@vger.kernel.org
+Cc: Kai Aizen <kai.aizen.dev@gmail.com>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605183127.2055332-1-sashal@kernel.org>
+
+From: Kai Aizen <kai.aizen.dev@gmail.com>
+
+[ Upstream commit 68aa70648b625fa684bc0b71bbfd905f4943ca20 ]
+
+uvc_function_bind() walks &opts->extension_units twice without holding
+opts->lock:
+
+  - directly, for the iExtension string-descriptor fixup loop;
+  - indirectly, four times via uvc_copy_descriptors() (once per speed),
+    where the helper iterates uvc->desc.extension_units (which aliases
+    &opts->extension_units) to size and emit XU descriptors.
+
+The configfs side (uvcg_extension_make / uvcg_extension_drop, in
+drivers/usb/gadget/function/uvc_configfs.c) takes opts->lock around its
+list_add_tail / list_del operations.  A privileged userspace process
+that holds the configfs subtree open and writes the gadget UDC name
+to bind the function while concurrently rmdir()'ing an extensions
+subdir can race uvcg_extension_drop() against the bind-time list walks
+and dereference a freed struct uvcg_extension.
+
+Hold opts->lock from the start of the XU string-descriptor fixup
+through the last uvc_copy_descriptors() call, releasing on the
+descriptor-error path via a new error_unlock label that drops the
+lock before falling through to the existing error label.  This
+matches the locking discipline of the configfs callbacks and removes
+the only remaining unsynchronised reader of the XU list during bind.
+
+Reachability: only privileged processes that can mount configfs and
+write to gadget UDC files can trigger the race, so this is a
+correctness fix rather than a security boundary.
+
+Fixes: 0525210c9840 ("usb: gadget: uvc: Allow definition of XUs in configfs")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kai Aizen <kai.aizen.dev@gmail.com>
+Link: https://patch.msgid.link/20260430175643.67120-1-kai.aizen.dev@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_uvc.c |   26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_uvc.c
++++ b/drivers/usb/gadget/function/f_uvc.c
+@@ -763,6 +763,16 @@ uvc_function_bind(struct usb_configurati
+       uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+       /*
++       * Hold opts->lock across both the XU string-descriptor fixup below and
++       * the descriptor-copy block further down.  Without this, configfs
++       * uvcg_extension_drop() (which takes opts->lock) can race with the
++       * list_for_each_entry() walks here and inside uvc_copy_descriptors(),
++       * leading to a UAF on a freed struct uvcg_extension.  See
++       * drivers/usb/gadget/function/uvc_configfs.c::uvcg_extension_drop().
++       */
++      mutex_lock(&opts->lock);
++
++      /*
+        * XUs can have an arbitrary string descriptor describing them. If they
+        * have one pick up the ID.
+        */
+@@ -779,7 +789,7 @@ uvc_function_bind(struct usb_configurati
+                                ARRAY_SIZE(uvc_en_us_strings));
+       if (IS_ERR(us)) {
+               ret = PTR_ERR(us);
+-              goto error;
++              goto error_unlock;
+       }
+       uvc_iad.iFunction = opts->iad_index ? cdev->usb_strings[opts->iad_index].id :
+@@ -793,14 +803,14 @@ uvc_function_bind(struct usb_configurati
+       /* Allocate interface IDs. */
+       if ((ret = usb_interface_id(c, f)) < 0)
+-              goto error;
++              goto error_unlock;
+       uvc_iad.bFirstInterface = ret;
+       uvc_control_intf.bInterfaceNumber = ret;
+       uvc->control_intf = ret;
+       opts->control_interface = ret;
+       if ((ret = usb_interface_id(c, f)) < 0)
+-              goto error;
++              goto error_unlock;
+       uvc_streaming_intf_alt0.bInterfaceNumber = ret;
+       uvc_streaming_intf_alt1.bInterfaceNumber = ret;
+       uvc->streaming_intf = ret;
+@@ -811,23 +821,25 @@ uvc_function_bind(struct usb_configurati
+       if (IS_ERR(f->fs_descriptors)) {
+               ret = PTR_ERR(f->fs_descriptors);
+               f->fs_descriptors = NULL;
+-              goto error;
++              goto error_unlock;
+       }
+       f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+       if (IS_ERR(f->hs_descriptors)) {
+               ret = PTR_ERR(f->hs_descriptors);
+               f->hs_descriptors = NULL;
+-              goto error;
++              goto error_unlock;
+       }
+       f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
+       if (IS_ERR(f->ss_descriptors)) {
+               ret = PTR_ERR(f->ss_descriptors);
+               f->ss_descriptors = NULL;
+-              goto error;
++              goto error_unlock;
+       }
++      mutex_unlock(&opts->lock);
++
+       /* Preallocate control endpoint request. */
+       uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
+       uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
+@@ -859,6 +871,8 @@ uvc_function_bind(struct usb_configurati
+       return 0;
++error_unlock:
++      mutex_unlock(&opts->lock);
+ v4l2_error:
+       v4l2_device_unregister(&uvc->v4l2_dev);
+ error:
diff --git a/queue-6.6/usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch b/queue-6.6/usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch
new file mode 100644 (file)
index 0000000..b0d0f64
--- /dev/null
@@ -0,0 +1,54 @@
+From sashal@kernel.org Fri Jun  5 21:01:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 11:31:07 -0400
+Subject: usb: musb: omap2430: Fix use-after-free in omap2430_probe()
+To: stable@vger.kernel.org
+Cc: Wentao Liang <vulab@iscas.ac.cn>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605153108.1929169-1-sashal@kernel.org>
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit e194ce048f5a6c549b3a23a8c568c6470f40f772 ]
+
+In omap2430_probe(), of_node_put(np) is called prematurely before the
+last access to np, leading to a use-after-free if the node's reference
+count drops to zero. Move the of_node_put() calls after the last use of
+np in both the success and error paths.
+
+Fixes: ffbe2feac59b ("usb: musb: omap2430: Fix probe regression for missing resources")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Link: https://patch.msgid.link/20260409101104.480623-1-vulab@iscas.ac.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/omap2430.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -340,7 +340,6 @@ static int omap2430_probe(struct platfor
+       } else {
+               device_set_of_node_from_dev(&musb->dev, &pdev->dev);
+       }
+-      of_node_put(np);
+       glue->dev                       = &pdev->dev;
+       glue->musb                      = musb;
+@@ -458,6 +457,7 @@ static int omap2430_probe(struct platfor
+               dev_err(&pdev->dev, "failed to register musb device\n");
+               goto err3;
+       }
++      of_node_put(np);
+       return 0;
+@@ -467,6 +467,7 @@ err_put_control_otghs:
+       if (!IS_ERR(glue->control_otghs))
+               put_device(glue->control_otghs);
+ err2:
++      of_node_put(np);
+       platform_device_put(musb);
+ err0:
diff --git a/queue-6.6/usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch b/queue-6.6/usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch
new file mode 100644 (file)
index 0000000..583fb9b
--- /dev/null
@@ -0,0 +1,68 @@
+From sashal@kernel.org Sat Jun  6 00:47:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  5 Jun 2026 15:17:16 -0400
+Subject: usb: typec: ucsi: Check if power role change actually happened before handling
+To: stable@vger.kernel.org
+Cc: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>, stable <stable@kernel.org>, Sergey Senozhatsky <senozhatsky@chromium.org>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605191716.2134705-1-sashal@kernel.org>
+
+From: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+
+[ Upstream commit b80e7d34c7ea6a564525119d6138fbb577a23dba ]
+
+The CrOS EC may send a connector status change event with the power
+direction changed flag set even if the power direction hasn't actually
+changed after initiating a SET_PDR command internally [1]. In practice
+this happens on every system suspend due to other changes performed by
+the EC [2][3][4], causing suspend to fail.
+
+Fix this by checking if the power role change actually happened before
+handling it.
+
+[1]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=1689;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+[2]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=3923;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+[3]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=5094;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+[4]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=2229;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+
+Cc: stable <stable@kernel.org>
+Fixes: 7616f006db07 ("usb: typec: ucsi: Update power_supply on power role change")
+Signed-off-by: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+Reported-and-tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://patch.msgid.link/20260519-ucsi-fix-2-v1-1-6f1239535187@qtmlabs.xyz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -884,7 +884,7 @@ static void ucsi_handle_connector_change
+       struct ucsi_connector *con = container_of(work, struct ucsi_connector,
+                                                 work);
+       struct ucsi *ucsi = con->ucsi;
+-      enum typec_role role;
++      enum typec_role role, prev_role;
+       u64 command;
+       int ret;
+@@ -892,6 +892,8 @@ static void ucsi_handle_connector_change
+       command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
++      prev_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
++
+       ret = ucsi_send_command_common(ucsi, command, &con->status,
+                                      sizeof(con->status), true);
+       if (ret < 0) {
+@@ -908,7 +910,7 @@ static void ucsi_handle_connector_change
+       role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
+-      if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
++      if ((con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) && role != prev_role) {
+               typec_set_pwr_role(con->port, role);
+               ucsi_port_psy_changed(con);
diff --git a/queue-6.6/usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch b/queue-6.6/usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch
new file mode 100644 (file)
index 0000000..2ad3378
--- /dev/null
@@ -0,0 +1,45 @@
+From stable+bounces-260881-greg=kroah.com@vger.kernel.org Sat Jun  6 18:37:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  6 Jun 2026 09:05:38 -0400
+Subject: usb: typec: ucsi: Don't update power_supply on power role change if not connected
+To: stable@vger.kernel.org
+Cc: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>, stable <stable@kernel.org>, Sergey Senozhatsky <senozhatsky@chromium.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260606130538.2924564-1-sashal@kernel.org>
+
+From: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+
+[ Upstream commit d98d413ca65d0790a8f3695d0a5845538958ab84 ]
+
+We only need to update the power_supply on power role change if the port
+is connected, because otherwise the online status should be the same for
+both cases.
+
+Cc: stable <stable@kernel.org>
+Fixes: 7616f006db07 ("usb: typec: ucsi: Update power_supply on power role change")
+Signed-off-by: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+Reported-and-tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Link: https://patch.msgid.link/20260519-ucsi-fix-2-v1-2-6f1239535187@qtmlabs.xyz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ changed `UCSI_CONSTAT(con, CONNECTED)` accessor macro to `con->status.flags & UCSI_CONSTAT_CONNECTED` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -912,7 +912,12 @@ static void ucsi_handle_connector_change
+       if ((con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) && role != prev_role) {
+               typec_set_pwr_role(con->port, role);
+-              ucsi_port_psy_changed(con);
++
++              /* Some power_supply properties vary depending on the power direction when
++               * connected
++               */
++              if (con->status.flags & UCSI_CONSTAT_CONNECTED)
++                      ucsi_port_psy_changed(con);
+               /* Complete pending power role swap */
+               if (!completion_done(&con->complete))