From: Greg Kroah-Hartman Date: Sun, 7 Jun 2026 07:38:03 +0000 (+0200) Subject: 6.12-stable patches X-Git-Tag: v6.12.93~19 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=8eb401cb923233c686b400733487f2276c6c04ba;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch alsa-scarlett2-allow-flash-writes-ending-at-segment-boundary.patch alsa-scarlett2-return-enospc-for-out-of-bounds-flash-writes.patch arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch ice-fix-vf-queue-configuration-with-low-mtu-values.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 mm-damon-sysfs-schemes-delete-tried-region-in-regions_rmdirs.patch mm-memory-fix-spurious-warning-when-unmapping-device-private-exclusive-pages.patch mptcp-cleanup-fallback-dummy-mapping-generation.patch mptcp-do-not-drop-partial-packets.patch mptcp-handle-first-subflow-closing-consistently.patch mptcp-introduce-the-mptcp_init_skb-helper.patch mptcp-pm-fix-add_addr-timer-infinite-retry-on-option-space-insufficient.patch mptcp-reset-rcv-wnd-on-disconnect.patch net-hsr-defer-node-table-free-until-after-rcu-readers.patch octeontx2-pf-avoid-double-free-of-pool-stack-on-aq-init-failure.patch platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch ring-buffer-flush-and-stop-persistent-ring-buffer-on-panic.patch rxrpc-fix-data-decrypt-vs-splice-by-copying-data-to-buffer-in-recvmsg.patch rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch selftests-mptcp-drop-nanoseconds-width-specifier.patch serdev-provide-a-bustype-shutdown-function.patch thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.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 x86-alternatives-rename-apply_relocation-to-text_poke_apply_relocation.patch x86-ftrace-relocate-rip-relative-percpu-refs-in-dynamic-trampolines.patch --- diff --git a/queue-6.12/alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch b/queue-6.12/alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch new file mode 100644 index 0000000000..50a01874c6 --- /dev/null +++ b/queue-6.12/alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch @@ -0,0 +1,74 @@ +From stable+bounces-260595-greg=kroah.com@vger.kernel.org Fri Jun 5 03:04:24 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 20:59:03 -0400 +Subject: ALSA: firewire-motu: Protect register DSP event queue positions +To: stable@vger.kernel.org +Cc: "Cássio Gabriel" , "Takashi Sakamoto" , "Takashi Iwai" , "Sasha Levin" +Message-ID: <20260605005903.2802313-1-sashal@kernel.org> + +From: Cássio Gabriel + +[ 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 +Reviewed-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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.12/alsa-scarlett2-allow-flash-writes-ending-at-segment-boundary.patch b/queue-6.12/alsa-scarlett2-allow-flash-writes-ending-at-segment-boundary.patch new file mode 100644 index 0000000000..7e0557c691 --- /dev/null +++ b/queue-6.12/alsa-scarlett2-allow-flash-writes-ending-at-segment-boundary.patch @@ -0,0 +1,53 @@ +From stable+bounces-256678-greg=kroah.com@vger.kernel.org Fri May 29 20:05:15 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 13:25:00 -0400 +Subject: ALSA: scarlett2: Allow flash writes ending at segment boundary +To: stable@vger.kernel.org +Cc: "Cássio Gabriel" , "Takashi Iwai" , "Sasha Levin" +Message-ID: <20260529172500.1327796-2-sashal@kernel.org> + +From: Cássio Gabriel + +[ Upstream commit a69b677e47a80319ce148d61cc29a2b57006e78d ] + +scarlett2_hwdep_write() rejects writes when offset + count is greater than +or equal to the selected flash segment size. That incorrectly treats a +write ending exactly at the end of the segment as out of space, although +the last byte written is still within the segment. + +Split invalid argument checks from the segment-space check, keep +zero-length writes as no-ops, and compare count against the remaining +segment size. This permits exact-end writes and avoids relying on +offset + count before deciding whether the request is in bounds. + +Fixes: 1abfbd3c9527 ("ALSA: scarlett2: Add support for uploading new firmware") +Cc: stable@vger.kernel.org +Signed-off-by: Cássio Gabriel +Link: https://patch.msgid.link/20260519-alsa-scarlett2-flash-write-boundary-v1-1-b550480e92da@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/mixer_scarlett2.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/sound/usb/mixer_scarlett2.c ++++ b/sound/usb/mixer_scarlett2.c +@@ -9549,12 +9549,15 @@ static long scarlett2_hwdep_write(struct + flash_size = private->flash_segment_blocks[segment_id] * + SCARLETT2_FLASH_BLOCK_SIZE; + +- if (count < 0 || *offset < 0 || *offset + count >= flash_size) +- return -ENOSPC; ++ if (count < 0 || *offset < 0) ++ return -EINVAL; + + if (!count) + return 0; + ++ if (*offset >= flash_size || count > flash_size - *offset) ++ return -ENOSPC; ++ + /* Limit the *req size to SCARLETT2_FLASH_RW_MAX */ + if (count > max_data_size) + count = max_data_size; diff --git a/queue-6.12/alsa-scarlett2-return-enospc-for-out-of-bounds-flash-writes.patch b/queue-6.12/alsa-scarlett2-return-enospc-for-out-of-bounds-flash-writes.patch new file mode 100644 index 0000000000..216929b16c --- /dev/null +++ b/queue-6.12/alsa-scarlett2-return-enospc-for-out-of-bounds-flash-writes.patch @@ -0,0 +1,36 @@ +From stable+bounces-256677-greg=kroah.com@vger.kernel.org Fri May 29 20:05:12 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 13:24:59 -0400 +Subject: ALSA: scarlett2: Return ENOSPC for out-of-bounds flash writes +To: stable@vger.kernel.org +Cc: "Geoffrey D. Bennett" , Takashi Iwai , Sasha Levin +Message-ID: <20260529172500.1327796-1-sashal@kernel.org> + +From: "Geoffrey D. Bennett" + +[ Upstream commit 74641bfcbf4e698b770b1b62a74e73934843e90e ] + +When writing to flash, return ENOSPC instead of EINVAL if the requested +write would exceed the size of the flash segment. + +Signed-off-by: Geoffrey D. Bennett +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/3a4af07b0329bed5ffb6994594e4f7bd202aad0f.1727971672.git.g@b4.vu +Stable-dep-of: a69b677e47a8 ("ALSA: scarlett2: Allow flash writes ending at segment boundary") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/mixer_scarlett2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/usb/mixer_scarlett2.c ++++ b/sound/usb/mixer_scarlett2.c +@@ -9550,7 +9550,7 @@ static long scarlett2_hwdep_write(struct + SCARLETT2_FLASH_BLOCK_SIZE; + + if (count < 0 || *offset < 0 || *offset + count >= flash_size) +- return -EINVAL; ++ return -ENOSPC; + + if (!count) + return 0; diff --git a/queue-6.12/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch b/queue-6.12/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch new file mode 100644 index 0000000000..b2bb04af60 --- /dev/null +++ b/queue-6.12/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch @@ -0,0 +1,55 @@ +From stable+bounces-259395-greg=kroah.com@vger.kernel.org Mon Jun 1 02:44:23 2026 +From: Sasha Levin +Date: Sun, 31 May 2026 20:44:17 -0400 +Subject: arm64: tlb: Flush walk cache when unsharing PMD tables +To: stable@vger.kernel.org +Cc: Zeng Heng , Catalin Marinas , Sasha Levin +Message-ID: <20260601004417.90834-1-sashal@kernel.org> + +From: Zeng Heng + +[ Upstream commit c2ff4764e03e7a8d758352f4aceb8fe1be6ac971 ] + +When huge_pmd_unshare() is called to unshare a PMD table, the +tlb_unshare_pmd_ptdesc() function sets tlb->unshared_tables=true +but the aarch64 tlb_flush() only checked tlb->freed_tables to +determine whether to use TLBF_NONE (vae1is, invalidates walk +cache) or TLBF_NOWALKCACHE (vale1is, leaf-only). + +This caused the stale PMD page table entry to remain in the walk cache +after unshare, potentially leading to incorrect page table walks. + +Fix by including unshared_tables in the check, so that when +unsharing tables, TLBF_NONE is used and the walk cache is properly +invalidated. + +Here is the detailed distinction between vae1is and vale1is: + +| Instruction Combination | Actual Invalidation Scope | +| ------------------------ | --------------------------------------------------| +| `VAE1IS` + TTL=`0` | All entries at all levels (full invalidation) | +| `VAE1IS` + TTL=`2` (L2) | Non-leaf at Level 0/1 + leaf at Level 2 | +| `VALE1IS` + TTL=`0` | Leaf entries at all levels (non-leaf not cleared) | +| `VALE1IS` + TTL=`2` (L2) | Leaf entry at Level 2 only | + +Signed-off-by: Zeng Heng +Fixes: 8ce720d5bd91 ("mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather") +Cc: +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/include/asm/tlb.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/include/asm/tlb.h ++++ b/arch/arm64/include/asm/tlb.h +@@ -58,7 +58,7 @@ static inline int tlb_get_level(struct m + static inline void tlb_flush(struct mmu_gather *tlb) + { + struct vm_area_struct vma = TLB_FLUSH_VMA(tlb->mm, 0); +- bool last_level = !tlb->freed_tables; ++ bool last_level = !(tlb->freed_tables || tlb->unshared_tables); + unsigned long stride = tlb_get_unmap_size(tlb); + int tlb_level = tlb_get_level(tlb); + diff --git a/queue-6.12/bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch b/queue-6.12/bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch new file mode 100644 index 0000000000..7301c3cd5f --- /dev/null +++ b/queue-6.12/bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch @@ -0,0 +1,154 @@ +From stable+bounces-256740-greg=kroah.com@vger.kernel.org Fri May 29 21:31:27 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 15:27:56 -0400 +Subject: Bluetooth: hci_qca: Convert timeout from jiffies to ms +To: stable@vger.kernel.org +Cc: Shuai Zhang , Paul Menzel , Bartosz Golaszewski , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260529192756.1699014-3-sashal@kernel.org> + +From: Shuai Zhang + +[ Upstream commit 375ba7484132662a4a8c7547d088fb6275c00282 ] + +Since the timer uses jiffies as its unit rather than ms, the timeout value +must be converted from ms to jiffies when configuring the timer. Otherwise, +the intended 8s timeout is incorrectly set to approximately 33s. + +To improve readability, embed msecs_to_jiffies() directly in the macro +definitions and drop the _MS suffix from macros that now yield jiffies +values: MEMDUMP_TIMEOUT, FW_DOWNLOAD_TIMEOUT, IBS_DISABLE_SSR_TIMEOUT, +CMD_TRANS_TIMEOUT, and IBS_BTSOC_TX_IDLE_TIMEOUT. + +IBS_WAKE_RETRANS_TIMEOUT_MS and IBS_HOST_TX_IDLE_TIMEOUT_MS are +intentionally left unchanged. Their values are stored in the struct fields +wake_retrans and tx_idle_delay, which hold ms values at runtime and can be +modified via debugfs. The msecs_to_jiffies() conversion happens at each +call site against the field value, so it cannot be embedded in the macro. + +Wake timer depends on commit c347ca17d62a + +Cc: stable@vger.kernel.org +Fixes: d841502c79e3 ("Bluetooth: hci_qca: Collect controller memory dump during SSR") +Reviewed-by: Paul Menzel +Acked-by: Bartosz Golaszewski +Signed-off-by: Shuai Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/hci_qca.c | 33 ++++++++++++++++----------------- + 1 file changed, 16 insertions(+), 17 deletions(-) + +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -47,13 +47,12 @@ + #define HCI_MAX_IBS_SIZE 10 + + #define IBS_WAKE_RETRANS_TIMEOUT_MS 100 +-#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS 200 ++#define IBS_BTSOC_TX_IDLE_TIMEOUT msecs_to_jiffies(200) + #define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000 +-#define CMD_TRANS_TIMEOUT_MS 100 +-#define MEMDUMP_TIMEOUT_MS 8000 +-#define IBS_DISABLE_SSR_TIMEOUT_MS \ +- (MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS) +-#define FW_DOWNLOAD_TIMEOUT_MS 3000 ++#define CMD_TRANS_TIMEOUT msecs_to_jiffies(100) ++#define MEMDUMP_TIMEOUT msecs_to_jiffies(8000) ++#define FW_DOWNLOAD_TIMEOUT msecs_to_jiffies(3000) ++#define IBS_DISABLE_SSR_TIMEOUT (MEMDUMP_TIMEOUT + FW_DOWNLOAD_TIMEOUT) + + /* susclk rate */ + #define SUSCLK_RATE_32KHZ 32768 +@@ -1078,7 +1077,7 @@ static void qca_controller_memdump(struc + + queue_delayed_work(qca->workqueue, + &qca->ctrl_memdump_timeout, +- msecs_to_jiffies(MEMDUMP_TIMEOUT_MS)); ++ MEMDUMP_TIMEOUT); + skb_pull(skb, sizeof(qca_memdump->ram_dump_size)); + qca_memdump->current_seq_no = 0; + qca_memdump->received_dump = 0; +@@ -1350,7 +1349,7 @@ static int qca_set_baudrate(struct hci_d + + if (hu->serdev) + serdev_device_wait_until_sent(hu->serdev, +- msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); ++ CMD_TRANS_TIMEOUT); + + /* Give the controller time to process the request */ + switch (qca_soc_type(hu)) { +@@ -1381,8 +1380,8 @@ static inline void host_set_baudrate(str + + static int qca_send_power_pulse(struct hci_uart *hu, bool on) + { ++ int timeout = CMD_TRANS_TIMEOUT; + int ret; +- int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); + u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE; + + /* These power pulses are single byte command which are sent +@@ -1584,7 +1583,7 @@ static void qca_wait_for_dump_collection + struct qca_data *qca = hu->priv; + + wait_on_bit_timeout(&qca->flags, QCA_MEMDUMP_COLLECTION, +- TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT_MS); ++ TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT); + + clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); + } +@@ -2519,7 +2518,7 @@ static void qca_serdev_remove(struct ser + static void qca_serdev_shutdown(struct serdev_device *serdev) + { + int ret; +- int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); ++ int timeout = CMD_TRANS_TIMEOUT; + struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + struct hci_uart *hu = &qcadev->serdev_hu; + struct hci_dev *hdev = hu->hdev; +@@ -2576,7 +2575,7 @@ static int __maybe_unused qca_suspend(st + bool tx_pending = false; + int ret = 0; + u8 cmd; +- u32 wait_timeout = 0; ++ unsigned long wait_timeout = 0; + + set_bit(QCA_SUSPENDING, &qca->flags); + +@@ -2597,15 +2596,15 @@ static int __maybe_unused qca_suspend(st + if (test_bit(QCA_IBS_DISABLED, &qca->flags) || + test_bit(QCA_SSR_TRIGGERED, &qca->flags)) { + wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ? +- IBS_DISABLE_SSR_TIMEOUT_MS : +- FW_DOWNLOAD_TIMEOUT_MS; ++ IBS_DISABLE_SSR_TIMEOUT : ++ FW_DOWNLOAD_TIMEOUT; + + /* QCA_IBS_DISABLED flag is set to true, During FW download + * and during memory dump collection. It is reset to false, + * After FW download complete. + */ + wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED, +- TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout)); ++ TASK_UNINTERRUPTIBLE, wait_timeout); + + if (test_bit(QCA_IBS_DISABLED, &qca->flags)) { + bt_dev_err(hu->hdev, "SSR or FW download time out"); +@@ -2657,7 +2656,7 @@ static int __maybe_unused qca_suspend(st + + if (tx_pending) { + serdev_device_wait_until_sent(hu->serdev, +- msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); ++ CMD_TRANS_TIMEOUT); + serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu); + } + +@@ -2666,7 +2665,7 @@ static int __maybe_unused qca_suspend(st + */ + ret = wait_event_interruptible_timeout(qca->suspend_wait_q, + qca->rx_ibs_state == HCI_IBS_RX_ASLEEP, +- msecs_to_jiffies(IBS_BTSOC_TX_IDLE_TIMEOUT_MS)); ++ IBS_BTSOC_TX_IDLE_TIMEOUT); + if (ret == 0) { + ret = -ETIMEDOUT; + goto error; diff --git a/queue-6.12/bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch b/queue-6.12/bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch new file mode 100644 index 0000000000..8e8efb422d --- /dev/null +++ b/queue-6.12/bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch @@ -0,0 +1,53 @@ +From stable+bounces-256739-greg=kroah.com@vger.kernel.org Fri May 29 21:28:06 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 15:27:55 -0400 +Subject: Bluetooth: hci_qca: Migrate to serdev specific shutdown function +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20260529192756.1699014-2-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit 12a6a5726c515455935982429ac35dee2307233d ] + +This saves a cast in the driver. The motivation is stop using the callback +.shutdown in qca_serdev_driver.driver to make it possible to drop that. + +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/261a3384e25c4837d4efee87958805f15d7d4e3c.1765526117.git.u.kleine-koenig@baylibre.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 375ba7484132 ("Bluetooth: hci_qca: Convert timeout from jiffies to ms") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/hci_qca.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -2516,11 +2516,10 @@ static void qca_serdev_remove(struct ser + hci_uart_unregister_device(&qcadev->serdev_hu); + } + +-static void qca_serdev_shutdown(struct device *dev) ++static void qca_serdev_shutdown(struct serdev_device *serdev) + { + int ret; + int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); +- struct serdev_device *serdev = to_serdev_device(dev); + struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + struct hci_uart *hu = &qcadev->serdev_hu; + struct hci_dev *hdev = hu->hdev; +@@ -2741,11 +2740,11 @@ static void hciqca_coredump(struct devic + static struct serdev_device_driver qca_serdev_driver = { + .probe = qca_serdev_probe, + .remove = qca_serdev_remove, ++ .shutdown = qca_serdev_shutdown, + .driver = { + .name = "hci_uart_qca", + .of_match_table = of_match_ptr(qca_bluetooth_of_match), + .acpi_match_table = ACPI_PTR(qca_bluetooth_acpi_match), +- .shutdown = qca_serdev_shutdown, + .pm = &qca_pm_ops, + #ifdef CONFIG_DEV_COREDUMP + .coredump = hciqca_coredump, diff --git a/queue-6.12/ice-fix-vf-queue-configuration-with-low-mtu-values.patch b/queue-6.12/ice-fix-vf-queue-configuration-with-low-mtu-values.patch new file mode 100644 index 0000000000..fd3b937dbc --- /dev/null +++ b/queue-6.12/ice-fix-vf-queue-configuration-with-low-mtu-values.patch @@ -0,0 +1,63 @@ +From stable+bounces-256848-greg=kroah.com@vger.kernel.org Sat May 30 03:23:24 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 21:17:49 -0400 +Subject: ice: fix VF queue configuration with low MTU values +To: stable@vger.kernel.org +Cc: Jose Ignacio Tornos Martinez , Jacob Keller , Michal Swiatkowski , Paul Menzel , Rafal Romanowski , Tony Nguyen , Jakub Kicinski , Sasha Levin +Message-ID: <20260530011749.2555710-1-sashal@kernel.org> + +From: Jose Ignacio Tornos Martinez + +[ Upstream commit 3ba4dd024d26372733d1c02e13e076c6016e3320 ] + +The ice driver's VF queue configuration validation rejects +databuffer_size values below 1024 bytes, which prevents VFs from +using MTU values below 871 bytes. + +The iavf driver calculates databuffer_size based on the MTU using: + databuffer_size = ALIGN(MTU + LIBETH_RX_LL_LEN, 128) + +where LIBETH_RX_LL_LEN = 26 (ETH_HLEN + 2*VLAN_HLEN + ETH_FCS_LEN). + +For MTU values below 871: + MTU 870: 870 + 26 = 896, aligned to 128 = 896 (< 1024, rejected) + MTU 871: 871 + 26 = 897, aligned to 128 = 1024 (>= 1024, accepted) + +The 1024-byte minimum seems unnecessarily restrictive, because the hardware +supports databuffer_size as low as 128 bytes (the alignment boundary), +which should allow MTU values down to the standard minimum of 68 bytes. + +I haven't found the reason why the limit was configured in the commit +9c7dd7566d18 ("ice: add validation in OP_CONFIG_VSI_QUEUES VF message"), so +with no more information and since it is working, change the minimum +databuffer_size validation from 1024 to 128 bytes to allow standard low +MTU values while still preventing invalid configurations. + +Fixes: 9c7dd7566d18 ("ice: add validation in OP_CONFIG_VSI_QUEUES VF message") +cc: stable@vger.kernel.org +Signed-off-by: Jose Ignacio Tornos Martinez +Reviewed-by: Jacob Keller +Reviewed-by: Michal Swiatkowski +Reviewed-by: Paul Menzel +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260515182419.1597859-3-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +[ applied the change to ice_virtchnl.c ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +@@ -1746,7 +1746,7 @@ static int ice_vc_cfg_qs_msg(struct ice_ + + if (qpi->rxq.databuffer_size != 0 && + (qpi->rxq.databuffer_size > ((16 * 1024) - 128) || +- qpi->rxq.databuffer_size < 1024)) ++ qpi->rxq.databuffer_size < 128)) + goto error_param; + ring->rx_buf_len = qpi->rxq.databuffer_size; + if (qpi->rxq.max_pkt_size > max_frame_size || diff --git a/queue-6.12/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch b/queue-6.12/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch new file mode 100644 index 0000000000..99cbcec39b --- /dev/null +++ b/queue-6.12/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch @@ -0,0 +1,38 @@ +From stable+bounces-260549-greg=kroah.com@vger.kernel.org Thu Jun 4 19:50:28 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 13:38:04 -0400 +Subject: iio: chemical: scd30: fix division by zero in write_raw +To: stable@vger.kernel.org +Cc: Antoniu Miclaus , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260604173804.26980-2-sashal@kernel.org> + +From: Antoniu Miclaus + +[ 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 +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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.12/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch b/queue-6.12/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch new file mode 100644 index 0000000000..6a0aede03b --- /dev/null +++ b/queue-6.12/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch @@ -0,0 +1,178 @@ +From stable+bounces-260548-greg=kroah.com@vger.kernel.org Thu Jun 4 19:40:26 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 13:38:03 -0400 +Subject: iio: chemical: scd30: Use guard(mutex) to allow early returns +To: stable@vger.kernel.org +Cc: Jonathan Cameron , David Lechner , Tomasz Duszynski , Sasha Levin +Message-ID: <20260604173804.26980-1-sashal@kernel.org> + +From: Jonathan Cameron + +[ 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 +Cc: Tomasz Duszynski +Reviewed-by: David Lechner +Link: https://patch.msgid.link/20250209180624.701140-3-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 5aba4f94b225 ("iio: chemical: scd30: fix division by zero in write_raw") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + */ + #include ++#include + #include + #include + #include +@@ -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.12/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch b/queue-6.12/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch new file mode 100644 index 0000000000..32595b9a72 --- /dev/null +++ b/queue-6.12/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch @@ -0,0 +1,65 @@ +From stable+bounces-260589-greg=kroah.com@vger.kernel.org Fri Jun 5 01:49:38 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 19:49:27 -0400 +Subject: iio: dac: ad5686: fix ref bit initialization for single-channel parts +To: stable@vger.kernel.org +Cc: Rodrigo Alencar , Andy Shevchenko , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260604234928.2470788-1-sashal@kernel.org> + +From: Rodrigo Alencar + +[ 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 +Signed-off-by: Rodrigo Alencar +Cc: +Signed-off-by: Jonathan Cameron +[ adapted `has_external_vref` to the in-tree equivalent `voltage_uv` variable in the `val =` computation ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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.12/mm-damon-sysfs-schemes-delete-tried-region-in-regions_rmdirs.patch b/queue-6.12/mm-damon-sysfs-schemes-delete-tried-region-in-regions_rmdirs.patch new file mode 100644 index 0000000000..a0802d27f9 --- /dev/null +++ b/queue-6.12/mm-damon-sysfs-schemes-delete-tried-region-in-regions_rmdirs.patch @@ -0,0 +1,94 @@ +From stable+bounces-260508-greg=kroah.com@vger.kernel.org Thu Jun 4 16:17:49 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 09:58:16 -0400 +Subject: mm/damon/sysfs-schemes: delete tried region in regions_rmdirs() +To: stable@vger.kernel.org +Cc: SeongJae Park , Andrew Morton , Sasha Levin +Message-ID: <20260604135816.3505741-1-sashal@kernel.org> + +From: SeongJae Park + +[ Upstream commit 441f92f7d386b85bad16de49db95a307cba048a2 ] + +DAMON sysfs maintains the DAMOS tried region directory objects via a +linked list. When the user requests refresh of the directories, DAMON +sysfs removes all the region directories first, and then generate updated +regions directory on the empty space. The removal function +(damon_sysfs_scheme_regions_rm_dirs()) only puts the kobj objects. +Deletion of the container region object from the linked list is done +inside the kobj release callback function. + +If somehow the callback invocation is delayed, the list will contain +regions list that gonna be freed. If the updated region directories +creation is started in this situation, the list can be corrupted and +use-after-free can happen. + +Because the kobj objects are managed by only DAMON sysfs, the issue cannot +happen in normal situation. But, such delays can be made on kernels that +built with CONFIG_DEBUG_KOBJECT_RELEASE. On the kernel, the issue can +indeed be reproduced like below. + + # damo start --damos_action stat + # cd /sys/kernel/mm/damon/admin/kdamonds/0/ + # for i in {1..10}; do echo update_schemes_tried_regions > state; done + # dmesg | grep underflow + [ 89.296152] refcount_t: underflow; use-after-free. + +Fix the issue by removing the region object from the list when +decrementing the reference count. + +Also update damos_sysfs_populate_region_dir() to add the region object to +the list only after the kobject_init_and_add() is success, so that fail of +kobject_init_and_add() is not leaving the deallocated object on the list. + +The issue was discovered [1] by Sashiko. + +Link: https://lore.kernel.org/20260518152559.93038-1-sj@kernel.org +Link: https://lore.kernel.org/20260513011920.119183-1-sj@kernel.org [1] +Fixes: 9277d0367ba1 ("mm/damon/sysfs-schemes: implement scheme region directory") +Signed-off-by: SeongJae Park +Cc: # 6.2.x +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/sysfs-schemes.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/mm/damon/sysfs-schemes.c ++++ b/mm/damon/sysfs-schemes.c +@@ -79,7 +79,6 @@ static void damon_sysfs_scheme_region_re + struct damon_sysfs_scheme_region *region = container_of(kobj, + struct damon_sysfs_scheme_region, kobj); + +- list_del(®ion->list); + kfree(region); + } + +@@ -197,7 +196,7 @@ static void damon_sysfs_scheme_regions_r + struct damon_sysfs_scheme_region *r, *next; + + list_for_each_entry_safe(r, next, ®ions->regions_list, list) { +- /* release function deletes it from the list */ ++ list_del(&r->list); + kobject_put(&r->kobj); + regions->nr_regions--; + } +@@ -2186,14 +2185,15 @@ static int damon_sysfs_before_damos_appl + region = damon_sysfs_scheme_region_alloc(r); + if (!region) + return 0; +- list_add_tail(®ion->list, &sysfs_regions->regions_list); +- sysfs_regions->nr_regions++; + if (kobject_init_and_add(®ion->kobj, + &damon_sysfs_scheme_region_ktype, + &sysfs_regions->kobj, "%d", + damon_sysfs_schemes_region_idx++)) { + kobject_put(®ion->kobj); ++ return 0; + } ++ list_add_tail(®ion->list, &sysfs_regions->regions_list); ++ sysfs_regions->nr_regions++; + return 0; + } + diff --git a/queue-6.12/mm-memory-fix-spurious-warning-when-unmapping-device-private-exclusive-pages.patch b/queue-6.12/mm-memory-fix-spurious-warning-when-unmapping-device-private-exclusive-pages.patch new file mode 100644 index 0000000000..084a33d54e --- /dev/null +++ b/queue-6.12/mm-memory-fix-spurious-warning-when-unmapping-device-private-exclusive-pages.patch @@ -0,0 +1,192 @@ +From stable+bounces-256682-greg=kroah.com@vger.kernel.org Fri May 29 19:55:56 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 13:47:59 -0400 +Subject: mm/memory: fix spurious warning when unmapping device-private/exclusive pages +To: stable@vger.kernel.org +Cc: "Alistair Popple" , "Arsen Arsenović" , "Balbir Singh" , "David Hildenbrand" , "Jason Gunthorpe" , "John Hubbard" , "Leon Romanovsky" , "Liam R. Howlett" , "Lorenzo Stoakes" , "Peter Xu" , "Matthew Brost" , "Michal Hocko" , "Mike Rapoport" , "Shuah Khan" , "Suren Baghdasaryan" , "Thomas Hellström" , "Vlastimil Babka" , "Andrew Morton" , "Sasha Levin" +Message-ID: <20260529174800.1443622-1-sashal@kernel.org> + +From: Alistair Popple + +[ Upstream commit be3f38d05cc5a7c3f13e51994c5dd043ab604d28 ] + +Device private and exclusive entries are only supported for anonymous +folios. This condition is tested in __migrate_device_pages() and +make_device_exclusive() using folio_test_anon(). However the unmap path +tests this assumption using vma_is_anonymous(). + +This is wrong because whilst anonymous VMAs can only contain folios where +folio_test_anon() is true the opposite relation does not hold. A folio +for which folio_test_anon() is true does not imply vma_is_anonymous() is +true. Such a condition can occur if for example a folio is part of a +private filebacked mapping. + +In this case vma_is_anonymous() is false as the mapping is filebacked, but +folio_test_anon() may be true, thus permitting devices to migrate the +folio to device private memory. This can lead to the following spurious +warnings during process teardown: + +[ 772.737706] ------------[ cut here ]------------ +[ 772.739201] WARNING: mm/memory.c:1754 at unmap_page_range.cold+0x26/0x18a, CPU#17: hmm-tests/2041 +[ 772.742050] Modules linked in: test_hmm nvidia_uvm(O) nvidia(O) +[ 772.743959] CPU: 17 UID: 0 PID: 2041 Comm: hmm-tests Tainted: G W O 7.0.0+ #387 PREEMPT(full) +[ 772.747104] Tainted: [W]=WARN, [O]=OOT_MODULE +[ 772.748509] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 +[ 772.752117] RIP: 0010:unmap_page_range.cold+0x26/0x18a +[ 772.753780] Code: 7e fe ff ff 48 89 4c 24 78 4c 89 44 24 38 e8 f2 ff b1 00 48 8b 4c 24 78 4c 8b 44 24 38 48 8b 44 24 18 48 83 78 48 00 74 04 90 <0f> 0b 90 48 89 ca b8 ff ff 37 00 48 c1 ea 03 48 c1 e0 2a 80 3c 02 +[ 772.759602] RSP: 0018:ffff888112607550 EFLAGS: 00010286 +[ 772.761310] RAX: ffff88811bbf4dc0 RBX: dffffc0000000000 RCX: ffffea03e9bfffd8 +[ 772.763583] RDX: 1ffff1102377e9c1 RSI: 0000000000000008 RDI: ffff88811bbf4e08 +[ 772.765914] RBP: 0000000000000006 R08: ffff8881059f7448 R09: ffffed10224c0e68 +[ 772.768184] R10: ffff888112607347 R11: 0000000000000001 R12: 0000000000000001 +[ 772.770461] R13: ffffea03e9bfffc0 R14: ffff888112607908 R15: ffffea03e9bfffc0 +[ 772.772782] FS: 00007f327caa2780(0000) GS:ffff888427b7d000(0000) knlGS:0000000000000000 +[ 772.775328] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 772.777187] CR2: 00007f327ca89000 CR3: 00000001994d5000 CR4: 00000000000006f0 +[ 772.779135] Call Trace: +[ 772.779792] +[ 772.780317] ? dmirror_interval_invalidate+0x1a3/0x290 [test_hmm] +[ 772.781873] ? vm_normal_page_pud+0x2b0/0x2b0 +[ 772.782992] ? __rwlock_init+0x150/0x150 +[ 772.784006] ? lock_release+0x216/0x2b0 +[ 772.785008] ? __mmu_notifier_invalidate_range_start+0x505/0x6e0 +[ 772.786522] ? lock_release+0x216/0x2b0 +[ 772.787498] ? unmap_single_vma+0xb6/0x210 +[ 772.788573] unmap_vmas+0x27d/0x520 +[ 772.789506] ? unmap_single_vma+0x210/0x210 +[ 772.790607] ? mas_update_gap.part.0+0x620/0x620 +[ 772.791834] unmap_region+0x19e/0x350 +[ 772.792769] ? remove_vma+0x130/0x130 +[ 772.793684] ? mas_alloc_nodes+0x1f2/0x300 +[ 772.794730] vms_complete_munmap_vmas+0x8c1/0xe20 +[ 772.795926] ? unmap_region+0x350/0x350 +[ 772.796917] do_vmi_align_munmap+0x36a/0x4e0 +[ 772.798018] ? lock_release+0x216/0x2b0 +[ 772.799024] ? vma_shrink+0x620/0x620 +[ 772.799983] do_vmi_munmap+0x150/0x2c0 +[ 772.800939] __vm_munmap+0x161/0x2c0 +[ 772.801872] ? expand_downwards+0xd60/0xd60 +[ 772.802948] ? clockevents_program_event+0x1ef/0x540 +[ 772.804217] ? lock_release+0x216/0x2b0 +[ 772.805158] __x64_sys_munmap+0x59/0x80 +[ 772.805776] do_syscall_64+0xfc/0x670 +[ 772.806336] ? irqentry_exit+0xda/0x580 +[ 772.806976] entry_SYSCALL_64_after_hwframe+0x4b/0x53 +[ 772.807772] RIP: 0033:0x7f327cbb2717 +[ 772.808323] Code: 73 01 c3 48 8b 0d f9 76 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 b8 0b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c9 76 0d 00 f7 d8 64 89 01 48 +[ 772.811337] RSP: 002b:00007ffde7f57d38 EFLAGS: 00000202 ORIG_RAX: 000000000000000b +[ 772.812564] RAX: ffffffffffffffda RBX: 00007f327cc9c000 RCX: 00007f327cbb2717 +[ 772.813733] RDX: 0000000000000000 RSI: 0000000000400000 RDI: 00007f327c289000 +[ 772.814867] RBP: 0000000000421360 R08: 000000000000001a R09: 0000000000000000 +[ 772.815991] R10: 0000000000000003 R11: 0000000000000202 R12: 00007ffde7f57d74 +[ 772.817121] R13: 00007f327c689010 R14: 0000000000100000 R15: 00007f327c289000 +[ 772.818272] +[ 772.818614] irq event stamp: 0 +[ 772.819159] hardirqs last enabled at (0): [<0000000000000000>] 0x0 +[ 772.820174] hardirqs last disabled at (0): [] copy_process+0x19f3/0x6440 +[ 772.821511] softirqs last enabled at (0): [] copy_process+0x1a40/0x6440 +[ 772.822869] softirqs last disabled at (0): [<0000000000000000>] 0x0 +[ 772.823871] ---[ end trace 0000000000000000 ]--- + +Fix this by using the same check for folio_test_anon() in +zap_nonpresent_ptes(). Also add a hmm-test case for this. + +Link: https://lore.kernel.org/20260501065116.2057242-1-apopple@nvidia.com +Fixes: 999dad824c39 ("mm/shmem: persist uffd-wp bit across zapping for file-backed") +Signed-off-by: Alistair Popple +Reported-by: Arsen Arsenović +Reviewed-by: Balbir Singh +Cc: David Hildenbrand +Cc: Jason Gunthorpe +Cc: John Hubbard +Cc: Leon Romanovsky +Cc: Liam R. Howlett +Cc: Lorenzo Stoakes +Cc: Peter Xu +Cc: Matthew Brost +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shuah Khan +Cc: Suren Baghdasaryan +Cc: Thomas Hellström +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +[ applied the change in `zap_pte_range()` instead of `zap_nonpresent_ptes()` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + mm/memory.c | 2 - + tools/testing/selftests/mm/hmm-tests.c | 50 +++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 1 deletion(-) + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1639,7 +1639,7 @@ static unsigned long zap_pte_range(struc + * consider uffd-wp bit when zap. For more information, + * see zap_install_uffd_wp_if_needed(). + */ +- WARN_ON_ONCE(!vma_is_anonymous(vma)); ++ WARN_ON_ONCE(!folio_test_anon(folio)); + rss[mm_counter(folio)]--; + if (is_device_private_entry(entry)) + folio_remove_rmap_pte(folio, page, vma); +--- a/tools/testing/selftests/mm/hmm-tests.c ++++ b/tools/testing/selftests/mm/hmm-tests.c +@@ -999,6 +999,56 @@ TEST_F(hmm, migrate) + } + + /* ++ * Migrate private file memory to device private memory. ++ */ ++TEST_F(hmm, migrate_file_private) ++{ ++ struct hmm_buffer *buffer; ++ unsigned long npages; ++ unsigned long size; ++ unsigned long i; ++ int *ptr; ++ int ret; ++ int fd; ++ ++ npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift; ++ ASSERT_NE(npages, 0); ++ size = npages << self->page_shift; ++ ++ fd = hmm_create_file(size); ++ ASSERT_GE(fd, 0); ++ ++ buffer = malloc(sizeof(*buffer)); ++ ASSERT_NE(buffer, NULL); ++ ++ buffer->fd = fd; ++ buffer->size = size; ++ buffer->mirror = malloc(size); ++ ASSERT_NE(buffer->mirror, NULL); ++ ++ buffer->ptr = mmap(NULL, size, ++ PROT_READ | PROT_WRITE, ++ MAP_PRIVATE, ++ buffer->fd, 0); ++ ASSERT_NE(buffer->ptr, MAP_FAILED); ++ ++ /* Initialize buffer in system memory. */ ++ for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i) ++ ptr[i] = i; ++ ++ /* Migrate memory to device. */ ++ ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages); ++ ASSERT_EQ(ret, 0); ++ ASSERT_EQ(buffer->cpages, npages); ++ ++ /* Check what the device read. */ ++ for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i) ++ ASSERT_EQ(ptr[i], i); ++ ++ hmm_buffer_free(buffer); ++} ++ ++/* + * Migrate anonymous memory to device private memory and fault some of it back + * to system memory, then try migrating the resulting mix of system and device + * private memory to the device. diff --git a/queue-6.12/mptcp-cleanup-fallback-dummy-mapping-generation.patch b/queue-6.12/mptcp-cleanup-fallback-dummy-mapping-generation.patch new file mode 100644 index 0000000000..22d557b05f --- /dev/null +++ b/queue-6.12/mptcp-cleanup-fallback-dummy-mapping-generation.patch @@ -0,0 +1,74 @@ +From stable+bounces-256888-greg=kroah.com@vger.kernel.org Sat May 30 13:52:52 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 07:50:51 -0400 +Subject: mptcp: cleanup fallback dummy mapping generation +To: stable@vger.kernel.org +Cc: Paolo Abeni , Geliang Tang , Mat Martineau , "Matthieu Baerts (NGI0)" , Jakub Kicinski , Sasha Levin +Message-ID: <20260530115052.1973393-1-sashal@kernel.org> + +From: Paolo Abeni + +[ Upstream commit 2834f8edd74d5dda368087a654c0e52b141e9893 ] + +MPTCP currently access ack_seq outside the msk socket log scope to +generate the dummy mapping for fallback socket. Soon we are going +to introduce backlog usage and even for fallback socket the ack_seq +value will be significantly off outside of the msk socket lock scope. + +Avoid relying on ack_seq for dummy mapping generation, using instead +the subflow sequence number. Note that in case of disconnect() and +(re)connect() we must ensure that any previous state is re-set. + +Signed-off-by: Paolo Abeni +Reviewed-by: Geliang Tang +Tested-by: Geliang Tang +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20251121-net-next-mptcp-memcg-backlog-imp-v1-6-1f34b6c1e0b1@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 0981f90e1a05 ("mptcp: reset rcv wnd on disconnect") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 3 +++ + net/mptcp/subflow.c | 8 +++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3369,6 +3369,9 @@ static int mptcp_disconnect(struct sock + msk->rcvspace_init = 0; + msk->fastclosing = 0; + ++ /* for fallback's sake */ ++ WRITE_ONCE(msk->ack_seq, 0); ++ + WRITE_ONCE(sk->sk_shutdown, 0); + sk_error_report(sk); + return 0; +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -490,6 +490,9 @@ static void subflow_set_remote_key(struc + mptcp_crypto_key_sha(subflow->remote_key, NULL, &subflow->iasn); + subflow->iasn++; + ++ /* for fallback's sake */ ++ subflow->map_seq = subflow->iasn; ++ + WRITE_ONCE(msk->remote_key, subflow->remote_key); + WRITE_ONCE(msk->ack_seq, subflow->iasn); + WRITE_ONCE(msk->can_ack, true); +@@ -1415,9 +1418,12 @@ reset: + + skb = skb_peek(&ssk->sk_receive_queue); + subflow->map_valid = 1; +- subflow->map_seq = READ_ONCE(msk->ack_seq); + subflow->map_data_len = skb->len; + subflow->map_subflow_seq = tcp_sk(ssk)->copied_seq - subflow->ssn_offset; ++ subflow->map_seq = __mptcp_expand_seq(subflow->map_seq, ++ subflow->iasn + ++ TCP_SKB_CB(skb)->seq - ++ subflow->ssn_offset - 1); + WRITE_ONCE(subflow->data_avail, true); + return true; + } diff --git a/queue-6.12/mptcp-do-not-drop-partial-packets.patch b/queue-6.12/mptcp-do-not-drop-partial-packets.patch new file mode 100644 index 0000000000..f336bb4eb6 --- /dev/null +++ b/queue-6.12/mptcp-do-not-drop-partial-packets.patch @@ -0,0 +1,78 @@ +From stable+bounces-256908-greg=kroah.com@vger.kernel.org Sat May 30 16:21:08 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 10:19:32 -0400 +Subject: mptcp: do not drop partial packets +To: stable@vger.kernel.org +Cc: Shardul Bankar , Paolo Abeni , "Matthieu Baerts (NGI0)" , Sasha Levin +Message-ID: <20260530141932.2407122-3-sashal@kernel.org> + +From: Shardul Bankar + +[ Upstream commit 50c2d91c5dfa0e465826ec1f8dbad9cdc254bd85 ] + +When a packet arrives with map_seq < ack_seq < end_seq, the beginning +of the packet has already been acknowledged but the end contains new +data. Currently the entire packet is dropped as "old data," forcing +the sender to retransmit. + +Instead, skip the already-acked bytes by adjusting the skb offset and +enqueue only the new portion. Update bytes_received and ack_seq to +reflect the new data consumed. + +A previous attempt at this fix has been sent by Paolo Abeni [1], but had +issues [2]: it also added a zero-window check and changed rcv_wnd_sent +initialization, which caused test regressions. This version addresses +only the partial packet handling without modifying receive window +accounting. + +Fixes: ab174ad8ef76 ("mptcp: move ooo skbs into msk out of order queue.") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/c9b426a4e163aa3c4fe8b80c79f1a610f47ae7d8.1763075056.git.pabeni@redhat.com [1] +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/600 [2] +Signed-off-by: Shardul Bankar +[pabeni@redhat.com: update map] +Signed-off-by: Paolo Abeni +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260515-net-mptcp-misc-fixes-7-1-rc4-v2-1-701e96419f2f@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -390,12 +390,26 @@ static bool __mptcp_move_skb(struct sock + return false; + } + +- /* old data, keep it simple and drop the whole pkt, sender +- * will retransmit as needed, if needed. ++ /* Completely old data? */ ++ if (!after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) { ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); ++ mptcp_drop(sk, skb); ++ return false; ++ } ++ ++ /* Partial packet: map_seq < ack_seq < end_seq. ++ * Skip the already-acked bytes and enqueue the new data. + */ +- MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); +- mptcp_drop(sk, skb); +- return false; ++ copy_len = MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq; ++ MPTCP_SKB_CB(skb)->offset += msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq; ++ MPTCP_SKB_CB(skb)->map_seq += msk->ack_seq - ++ MPTCP_SKB_CB(skb)->map_seq; ++ msk->bytes_received += copy_len; ++ WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len); ++ ++ skb_set_owner_r(skb, sk); ++ __skb_queue_tail(&sk->sk_receive_queue, skb); ++ return true; + } + + static void mptcp_stop_rtx_timer(struct sock *sk) diff --git a/queue-6.12/mptcp-handle-first-subflow-closing-consistently.patch b/queue-6.12/mptcp-handle-first-subflow-closing-consistently.patch new file mode 100644 index 0000000000..d0daca1b95 --- /dev/null +++ b/queue-6.12/mptcp-handle-first-subflow-closing-consistently.patch @@ -0,0 +1,104 @@ +From stable+bounces-256907-greg=kroah.com@vger.kernel.org Sat May 30 16:21:07 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 10:19:31 -0400 +Subject: mptcp: handle first subflow closing consistently +To: stable@vger.kernel.org +Cc: Paolo Abeni , Mat Martineau , "Matthieu Baerts (NGI0)" , Jakub Kicinski , Sasha Levin +Message-ID: <20260530141932.2407122-2-sashal@kernel.org> + +From: Paolo Abeni + +[ Upstream commit 0eeb372deebce6c25b9afc09e35d6c75a744299a ] + +Currently, as soon as the PM closes a subflow, the msk stops accepting +data from it, even if the TCP socket could be still formally open in the +incoming direction, with the notable exception of the first subflow. + +The root cause of such behavior is that code currently piggy back two +separate semantic on the subflow->disposable bit: the subflow context +must be released and that the subflow must stop accepting incoming +data. + +The first subflow is never disposed, so it also never stop accepting +incoming data. Use a separate bit to mark the latter status and set such +bit in __mptcp_close_ssk() for all subflows. + +Beyond making per subflow behaviour more consistent this will also +simplify the next patch. + +Signed-off-by: Paolo Abeni +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20251121-net-next-mptcp-memcg-backlog-imp-v1-11-1f34b6c1e0b1@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 50c2d91c5dfa ("mptcp: do not drop partial packets") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 14 +++++++++----- + net/mptcp/protocol.h | 3 ++- + 2 files changed, 11 insertions(+), 6 deletions(-) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -877,10 +877,10 @@ void mptcp_data_ready(struct sock *sk, s + int sk_rbuf, ssk_rbuf; + + /* The peer can send data while we are shutting down this +- * subflow at msk destruction time, but we must avoid enqueuing ++ * subflow at subflow destruction time, but we must avoid enqueuing + * more data to the msk receive queue + */ +- if (unlikely(subflow->disposable)) ++ if (unlikely(subflow->closing)) + return; + + ssk_rbuf = READ_ONCE(ssk->sk_rcvbuf); +@@ -2514,6 +2514,13 @@ static void __mptcp_close_ssk(struct soc + struct mptcp_sock *msk = mptcp_sk(sk); + bool dispose_it, need_push = false; + ++ /* Do not pass RX data to the msk, even if the subflow socket is not ++ * going to be freed (i.e. even for the first subflow on graceful ++ * subflow close. ++ */ ++ lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); ++ subflow->closing = 1; ++ + /* If the first subflow moved to a close state before accept, e.g. due + * to an incoming reset or listener shutdown, the subflow socket is + * already deleted by inet_child_forget() and the mptcp socket can't +@@ -2524,7 +2531,6 @@ static void __mptcp_close_ssk(struct soc + /* ensure later check in mptcp_worker() will dispose the msk */ + sock_set_flag(sk, SOCK_DEAD); + mptcp_set_close_tout(sk, tcp_jiffies32 - (mptcp_close_timeout(sk) + 1)); +- lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); + mptcp_subflow_drop_ctx(ssk); + goto out_release; + } +@@ -2533,8 +2539,6 @@ static void __mptcp_close_ssk(struct soc + if (dispose_it) + list_del(&subflow->node); + +- lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); +- + if (subflow->send_fastclose && ssk->sk_state != TCP_CLOSE) + tcp_set_state(ssk, TCP_CLOSE); + +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -537,12 +537,13 @@ struct mptcp_subflow_context { + send_infinite_map : 1, + remote_key_valid : 1, /* received the peer key from */ + disposable : 1, /* ctx can be free at ulp release time */ ++ closing : 1, /* must not pass rx data to msk anymore */ + stale : 1, /* unable to snd/rcv data, do not use for xmit */ + valid_csum_seen : 1, /* at least one csum validated */ + is_mptfo : 1, /* subflow is doing TFO */ + close_event_done : 1, /* has done the post-closed part */ + mpc_drop : 1, /* the MPC option has been dropped in a rtx */ +- __unused : 9; ++ __unused : 8; + bool data_avail; + bool scheduled; + bool pm_listener; /* a listener managed by the kernel PM? */ diff --git a/queue-6.12/mptcp-introduce-the-mptcp_init_skb-helper.patch b/queue-6.12/mptcp-introduce-the-mptcp_init_skb-helper.patch new file mode 100644 index 0000000000..47c28722cd --- /dev/null +++ b/queue-6.12/mptcp-introduce-the-mptcp_init_skb-helper.patch @@ -0,0 +1,119 @@ +From stable+bounces-256906-greg=kroah.com@vger.kernel.org Sat May 30 16:23:06 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 10:19:30 -0400 +Subject: mptcp: introduce the mptcp_init_skb helper +To: stable@vger.kernel.org +Cc: Paolo Abeni , "Matthieu Baerts (NGI0)" , Geliang Tang , Jakub Kicinski , Sasha Levin +Message-ID: <20260530141932.2407122-1-sashal@kernel.org> + +From: Paolo Abeni + +[ Upstream commit 9a0afe0db46720ce1a009c7dac168aa0584bd732 ] + +Factor out all the skb initialization step in a new helper and +use it. Note that this change moves the MPTCP CB initialization +earlier: we can do such step as soon as the skb leaves the +subflow socket receive queues. + +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Paolo Abeni +Reviewed-by: Geliang Tang +Tested-by: Geliang Tang +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20250927-net-next-mptcp-rcv-path-imp-v1-4-5da266aa9c1a@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 50c2d91c5dfa ("mptcp: do not drop partial packets") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 50 +++++++++++++++++++++++++++----------------------- + 1 file changed, 27 insertions(+), 23 deletions(-) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -321,7 +321,7 @@ end: + mptcp_set_owner_r(skb, sk); + } + +-static bool mptcp_rmem_schedule(struct sock *sk, struct sock *ssk, int size) ++static bool mptcp_rmem_schedule(struct sock *sk, int size) + { + struct mptcp_sock *msk = mptcp_sk(sk); + int amt, amount; +@@ -339,27 +339,11 @@ static bool mptcp_rmem_schedule(struct s + return true; + } + +-static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk, +- struct sk_buff *skb, unsigned int offset, +- size_t copy_len) ++static void mptcp_init_skb(struct sock *ssk, struct sk_buff *skb, int offset, ++ int copy_len) + { +- struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); +- struct sock *sk = (struct sock *)msk; +- struct sk_buff *tail; +- bool has_rxtstamp; +- +- __skb_unlink(skb, &ssk->sk_receive_queue); +- +- skb_ext_reset(skb); +- skb_orphan(skb); +- +- /* try to fetch required memory from subflow */ +- if (!mptcp_rmem_schedule(sk, ssk, skb->truesize)) { +- MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); +- goto drop; +- } +- +- has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp; ++ const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); ++ bool has_rxtstamp = TCP_SKB_CB(skb)->has_rxtstamp; + + /* the skb map_seq accounts for the skb offset: + * mptcp_subflow_get_mapped_dsn() is based on the current tp->copied_seq +@@ -371,6 +355,25 @@ static bool __mptcp_move_skb(struct mptc + MPTCP_SKB_CB(skb)->has_rxtstamp = has_rxtstamp; + MPTCP_SKB_CB(skb)->cant_coalesce = 0; + ++ __skb_unlink(skb, &ssk->sk_receive_queue); ++ ++ skb_ext_reset(skb); ++ skb_dst_drop(skb); ++} ++ ++static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb) ++{ ++ u64 copy_len = MPTCP_SKB_CB(skb)->end_seq - MPTCP_SKB_CB(skb)->map_seq; ++ struct mptcp_sock *msk = mptcp_sk(sk); ++ struct sk_buff *tail; ++ ++ /* try to fetch required memory from subflow */ ++ if (!mptcp_rmem_schedule(sk, skb->truesize)) { ++ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); ++ mptcp_drop(sk, skb); ++ return false; ++ } ++ + if (MPTCP_SKB_CB(skb)->map_seq == msk->ack_seq) { + /* in sequence */ + msk->bytes_received += copy_len; +@@ -391,7 +394,6 @@ static bool __mptcp_move_skb(struct mptc + * will retransmit as needed, if needed. + */ + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); +-drop: + mptcp_drop(sk, skb); + return false; + } +@@ -720,7 +722,9 @@ static bool __mptcp_move_skbs_from_subfl + if (tp->urg_data) + done = true; + +- if (__mptcp_move_skb(msk, ssk, skb, offset, len)) ++ mptcp_init_skb(ssk, skb, offset, len); ++ skb_orphan(skb); ++ if (__mptcp_move_skb(sk, skb)) + moved += len; + seq += len; + diff --git a/queue-6.12/mptcp-pm-fix-add_addr-timer-infinite-retry-on-option-space-insufficient.patch b/queue-6.12/mptcp-pm-fix-add_addr-timer-infinite-retry-on-option-space-insufficient.patch new file mode 100644 index 0000000000..013be802e5 --- /dev/null +++ b/queue-6.12/mptcp-pm-fix-add_addr-timer-infinite-retry-on-option-space-insufficient.patch @@ -0,0 +1,150 @@ +From stable+bounces-256843-greg=kroah.com@vger.kernel.org Sat May 30 02:57:02 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 20:50:21 -0400 +Subject: mptcp: pm: fix ADD_ADDR timer infinite retry on option space insufficient +To: stable@vger.kernel.org +Cc: Li Xiasong , "Matthieu Baerts (NGI0)" , Paolo Abeni , Sasha Levin +Message-ID: <20260530005022.2387154-1-sashal@kernel.org> + +From: Li Xiasong + +[ Upstream commit 51e398a3b8961b26a8c0a4ba9a777c5339791707 ] + +When TCP option space is insufficient (e.g., when sending ADD_ADDR with an +IPv6 address and port while tcp_timestamps is enabled), the original code +jumped to out_unlock without clearing the addr_signal flag. This caused +mptcp_pm_add_timer to keep rescheduling indefinitely, not sending ADD_ADDR, +preventing subsequent addresses in the endpoint list from being announced. + +Handle this case by clearing the ADD_ADDR signal and skipping the matching +ADD_ADDR retransmission entry. The skip path cancels the matching timer +(with id check) and advances PM state progression, preserving forward +progress to subsequent PM work. + +This cancellation is inherently best-effort. A concurrent add_timer +callback may already be running and may acquire pm.lock before the +cancel path updates entry state. In that case, one final ADD_ADDR +transmit attempt can still be executed. + +Once the cancel path sets entry->retrans_times to ADD_ADDR_RETRANS_MAX, +the callback-side retrans_times check suppresses further ADD_ADDR +retransmissions. + +Note that when an ADD_ADDR is being prepared, a pure-ACK is queued. On +the output side, it means that it is fine to skip non-pure-ACK packets, +when drop_other_suboptions is set: a pure-ACK will be processed soon +after. + +Fixes: 00cfd77b9063 ("mptcp: retransmit ADD_ADDR when timeout") +Cc: stable@vger.kernel.org +Signed-off-by: Li Xiasong +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260515-net-mptcp-misc-fixes-7-1-rc4-v2-2-701e96419f2f@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm.c | 40 +++++++++++++++++++++++++++++++++------- + net/mptcp/pm_netlink.c | 16 +++++++++++++--- + 2 files changed, 46 insertions(+), 10 deletions(-) + +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -334,6 +334,7 @@ bool mptcp_pm_add_addr_signal(struct mpt + struct mptcp_addr_info *addr, bool *echo, + bool *drop_other_suboptions) + { ++ bool skip_add_addr = false; + int ret = false; + u8 add_addr; + u8 family; +@@ -355,24 +356,49 @@ bool mptcp_pm_add_addr_signal(struct mpt + } + + *echo = mptcp_pm_should_add_signal_echo(msk); +- port = !!(*echo ? msk->pm.remote.port : msk->pm.local.port); +- +- family = *echo ? msk->pm.remote.family : msk->pm.local.family; +- if (remaining < mptcp_add_addr_len(family, *echo, port)) +- goto out_unlock; +- + if (*echo) { + *addr = msk->pm.remote; + add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_ECHO); ++ port = !!msk->pm.remote.port; ++ family = msk->pm.remote.family; + } else { + *addr = msk->pm.local; + add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_SIGNAL); ++ port = !!msk->pm.local.port; ++ family = msk->pm.local.family; + } +- WRITE_ONCE(msk->pm.addr_signal, add_addr); ++ ++ if (remaining < mptcp_add_addr_len(family, *echo, port)) { ++ struct net *net = sock_net((struct sock *)msk); ++ ++ if (!*drop_other_suboptions) ++ goto out_unlock; ++ ++ if (*echo) { ++ MPTCP_INC_STATS(net, MPTCP_MIB_ECHOADDTXDROP); ++ } else { ++ skip_add_addr = true; ++ MPTCP_INC_STATS(net, MPTCP_MIB_ADDADDRTXDROP); ++ } ++ goto drop_signal_mark; ++ } ++ + ret = true; + ++drop_signal_mark: ++ WRITE_ONCE(msk->pm.addr_signal, add_addr); ++ + out_unlock: + spin_unlock_bh(&msk->pm.lock); ++ ++ /* On pure-ACK option-space exhaustion, stop retrying this ADD_ADDR: ++ * clear the signal bit, cancel the matching retransmission timer, and ++ * let the PM state machine progress. ++ */ ++ if (skip_add_addr) { ++ mptcp_pm_del_add_timer(msk, addr, true); ++ mptcp_pm_subflow_established(msk); ++ } + return ret; + } + +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -320,7 +320,13 @@ static void mptcp_pm_add_timer(struct ti + + spin_lock_bh(&msk->pm.lock); + +- if (!mptcp_pm_should_add_signal_addr(msk)) { ++ /* The cancel path (mptcp_pm_del_add_timer()) can race with this ++ * callback. Once cancel updates retrans_times to MAX, suppress further ++ * retransmissions here. If this callback acquires pm.lock first, one ++ * final transmit attempt is still possible. ++ */ ++ if (entry->retrans_times < ADD_ADDR_RETRANS_MAX && ++ !mptcp_pm_should_add_signal_addr(msk)) { + pr_debug("retransmit ADD_ADDR id=%d\n", entry->addr.id); + mptcp_pm_announce_addr(msk, &entry->addr, false); + mptcp_pm_add_addr_send_ack(msk); +@@ -368,8 +374,12 @@ mptcp_pm_del_add_timer(struct mptcp_sock + /* Note: entry might have been removed by another thread. + * We hold rcu_read_lock() to ensure it is not freed under us. + */ +- if (stop_timer) +- sk_stop_timer_sync(sk, &entry->add_timer); ++ if (stop_timer) { ++ if (check_id) ++ sk_stop_timer(sk, &entry->add_timer); ++ else ++ sk_stop_timer_sync(sk, &entry->add_timer); ++ } + + rcu_read_unlock(); + return entry; diff --git a/queue-6.12/mptcp-reset-rcv-wnd-on-disconnect.patch b/queue-6.12/mptcp-reset-rcv-wnd-on-disconnect.patch new file mode 100644 index 0000000000..5fa37d366a --- /dev/null +++ b/queue-6.12/mptcp-reset-rcv-wnd-on-disconnect.patch @@ -0,0 +1,47 @@ +From stable+bounces-256889-greg=kroah.com@vger.kernel.org Sat May 30 13:52:57 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 07:50:52 -0400 +Subject: mptcp: reset rcv wnd on disconnect +To: stable@vger.kernel.org +Cc: Paolo Abeni , "Matthieu Baerts (NGI0)" , Sasha Levin +Message-ID: <20260530115052.1973393-2-sashal@kernel.org> + +From: Paolo Abeni + +[ Upstream commit 0981f90e1a05773a4c29c6e720f5ea1e3c8f1876 ] + +If the MPTCP socket fallback to TCP before the MP handshake completion, +the IASN remain 0, and the rcv_wnd_sent field is not explicitly +initialized, just incremented over time with the data transfer. + +At disconnect time such value is not cleared. If the next connection falls +back to TCP before the MP handshake completion, the data transfer will +keep incrementing the receive window end sequence starting from the last +value used in the previous connection: the announced window will be +unrelated from the actual receiver buffer size and likely too big. + +Address the issue zeroing the field at disconnect time. + +Fixes: b29fcfb54cd7 ("mptcp: full disconnect implementation") +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Abeni +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260515-net-mptcp-misc-fixes-7-1-rc4-v2-4-701e96419f2f@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3371,6 +3371,7 @@ static int mptcp_disconnect(struct sock + + /* for fallback's sake */ + WRITE_ONCE(msk->ack_seq, 0); ++ atomic64_set(&msk->rcv_wnd_sent, 0); + + WRITE_ONCE(sk->sk_shutdown, 0); + sk_error_report(sk); diff --git a/queue-6.12/net-hsr-defer-node-table-free-until-after-rcu-readers.patch b/queue-6.12/net-hsr-defer-node-table-free-until-after-rcu-readers.patch new file mode 100644 index 0000000000..0b0607457d --- /dev/null +++ b/queue-6.12/net-hsr-defer-node-table-free-until-after-rcu-readers.patch @@ -0,0 +1,55 @@ +From stable+bounces-256827-greg=kroah.com@vger.kernel.org Sat May 30 01:44:53 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 19:39:22 -0400 +Subject: net: hsr: defer node table free until after RCU readers +To: stable@vger.kernel.org +Cc: Michael Bommarito , Jakub Kicinski , Sasha Levin +Message-ID: <20260529233922.1913663-1-sashal@kernel.org> + +From: Michael Bommarito + +[ Upstream commit aaec7096f9961eb223b5b149abe9495525c205d9 ] + +HSR node-list and node-status generic-netlink operations run under +rcu_read_lock(). They walk hsr->node_db through hsr_get_next_node() and +hsr_get_node_data(), but RTM_DELLINK teardown removes the same node table +with plain list_del() and frees each node immediately. + +That lets a generic-netlink reader hold a struct hsr_node pointer across +hsr_dellink(). In a KASAN build, widening the reader window after +hsr_get_next_node() obtains the node reproduces a slab-use-after-free +when the reader copies node->macaddress_A; the freeing stack is +hsr_del_nodes() from hsr_dellink(). + +Use list_del_rcu() and defer the free through the existing +hsr_free_node_rcu() callback. This matches the lifetime rule used by the +HSR prune paths, which already delete nodes with list_del_rcu() and +call_rcu(). + +Fixes: b9a1e627405d ("hsr: implement dellink to clean up resources") +Cc: stable@vger.kernel.org # v5.3+ +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/20260513233838.3064715-2-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +[ replaced `list_del`+`call_rcu(hsr_free_node_rcu)` with `list_del_rcu`+`kfree_rcu(node, rcu_head)` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/hsr/hsr_framereg.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -131,8 +131,10 @@ void hsr_del_nodes(struct list_head *nod + struct hsr_node *node; + struct hsr_node *tmp; + +- list_for_each_entry_safe(node, tmp, node_db, mac_list) +- kfree(node); ++ list_for_each_entry_safe(node, tmp, node_db, mac_list) { ++ list_del_rcu(&node->mac_list); ++ kfree_rcu(node, rcu_head); ++ } + } + + void prp_handle_san_frame(bool san, enum hsr_port_type port, diff --git a/queue-6.12/octeontx2-pf-avoid-double-free-of-pool-stack-on-aq-init-failure.patch b/queue-6.12/octeontx2-pf-avoid-double-free-of-pool-stack-on-aq-init-failure.patch new file mode 100644 index 0000000000..f262886337 --- /dev/null +++ b/queue-6.12/octeontx2-pf-avoid-double-free-of-pool-stack-on-aq-init-failure.patch @@ -0,0 +1,62 @@ +From stable+bounces-257321-greg=kroah.com@vger.kernel.org Sat May 30 19:13:10 2026 +From: Sasha Levin +Date: Sat, 30 May 2026 13:03:20 -0400 +Subject: octeontx2-pf: avoid double free of pool->stack on AQ init failure +To: stable@vger.kernel.org +Cc: Dawei Feng , Zilin Guan , Simon Horman , Jakub Kicinski , Sasha Levin +Message-ID: <20260530170320.3036620-1-sashal@kernel.org> + +From: Dawei Feng + +[ Upstream commit 9b244c242bec48b37e82b89787afd6a4c43457e1 ] + +otx2_pool_aq_init() frees pool->stack when mailbox sync or retry +allocation fails, but leaves the pointer unchanged. Later, +otx2_sq_aura_pool_init() unwinds the partial setup through +otx2_aura_pool_free(), which frees pool->stack again. The CN20K-specific +cn20k_pool_aq_init() implementation has the same bug in +its corresponding error path. + +Set pool->stack to NULL immediately after the local free so the shared +cleanup path does not free the same stack again while cleaning up +partially initialized pool state. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still present in +v7.1-rc3. + +Runtime validation was not performed because reproducing this path +requires OcteonTX2/CN20K hardware. + +Fixes: caa2da34fd25 ("octeontx2-pf: Initialize and config queues") +Fixes: d322fbd17203 ("octeontx2-pf: Initialize cn20k specific aura and pool contexts") +Cc: stable@vger.kernel.org +Signed-off-by: Zilin Guan +Signed-off-by: Dawei Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260515151826.1005397-1-dawei.feng@seu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +@@ -1386,11 +1386,13 @@ int otx2_pool_init(struct otx2_nic *pfvf + err = otx2_sync_mbox_msg(&pfvf->mbox); + if (err) { + qmem_free(pfvf->dev, pool->stack); ++ pool->stack = NULL; + return err; + } + aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox); + if (!aq) { + qmem_free(pfvf->dev, pool->stack); ++ pool->stack = NULL; + return -ENOMEM; + } + } diff --git a/queue-6.12/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch b/queue-6.12/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch new file mode 100644 index 0000000000..05ccb21a74 --- /dev/null +++ b/queue-6.12/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch @@ -0,0 +1,113 @@ +From stable+bounces-256791-greg=kroah.com@vger.kernel.org Fri May 29 23:43:40 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 17:42:44 -0400 +Subject: platform/x86/intel/vsec: Fix enable_cnt imbalance on PCIe error recovery +To: stable@vger.kernel.org +Cc: "Lukas Wunner" , "Ilpo Järvinen" , "Sasha Levin" +Message-ID: <20260529214244.1795477-1-sashal@kernel.org> + +From: Lukas Wunner + +[ Upstream commit 348ccc754d8939e21ca5956ff45720b81d6e407f ] + +After a PCIe Uncorrectable Error has been reported by a device with +Intel Vendor Specific Extended Capabilities and has been recovered +through a Secondary Bus Reset, its driver calls intel_vsec_pci_probe() +to rescan and reinitialize VSECs. + +intel_vsec_pci_probe() invokes pcim_enable_device() and thereby adds +another devm action which calls pcim_disable_device() on driver unbind. + +So once the driver unbinds, pcim_disable_device() will be called as many +times as an Uncorrectable Error occurred, plus one. This will lead to +an enable_cnt imbalance on driver unbind. + +Additionally, since commit dc957ab6aa05 ("platform/x86/intel/vsec: Add +private data for per-device data"), a devm_kzalloc() allocation is +leaked on every Uncorrectable Error. + +Avoid by splitting the VSEC rescan out of intel_vsec_pci_probe() into a +separate helper and calling that on PCIe error recovery. + +Fixes: 936874b77dd0 ("platform/x86/intel/vsec: Add PCI error recovery support to Intel PMT") +Signed-off-by: Lukas Wunner +Cc: stable@vger.kernel.org # v6.0+ +Link: https://patch.msgid.link/bd594d09fa866dc51dddc9a447c3b23f9b1402cc.1778736835.git.lukas@wunner.de +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/platform/x86/intel/vsec.c | 36 ++++++++++++++++++++++-------------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +--- a/drivers/platform/x86/intel/vsec.c ++++ b/drivers/platform/x86/intel/vsec.c +@@ -348,20 +348,10 @@ void intel_vsec_register(struct pci_dev + } + EXPORT_SYMBOL_NS_GPL(intel_vsec_register, INTEL_VSEC); + +-static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++static int intel_vsec_pci_init(struct pci_dev *pdev, ++ struct intel_vsec_platform_info *info) + { +- struct intel_vsec_platform_info *info; + bool have_devices = false; +- int ret; +- +- ret = pcim_enable_device(pdev); +- if (ret) +- return ret; +- +- pci_save_state(pdev); +- info = (struct intel_vsec_platform_info *)id->driver_data; +- if (!info) +- return -EINVAL; + + if (intel_vsec_walk_dvsec(pdev, info)) + have_devices = true; +@@ -379,6 +369,23 @@ static int intel_vsec_pci_probe(struct p + return 0; + } + ++static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ struct intel_vsec_platform_info *info; ++ int ret; ++ ++ ret = pcim_enable_device(pdev); ++ if (ret) ++ return ret; ++ ++ pci_save_state(pdev); ++ info = (struct intel_vsec_platform_info *)id->driver_data; ++ if (!info) ++ return -EINVAL; ++ ++ return intel_vsec_pci_init(pdev, info); ++} ++ + /* DG1 info */ + static struct intel_vsec_header dg1_header = { + .length = 0x10, +@@ -467,6 +474,7 @@ static pci_ers_result_t intel_vsec_pci_e + static pci_ers_result_t intel_vsec_pci_slot_reset(struct pci_dev *pdev) + { + struct intel_vsec_device *intel_vsec_dev; ++ struct intel_vsec_platform_info *info; + pci_ers_result_t status = PCI_ERS_RESULT_DISCONNECT; + const struct pci_device_id *pci_dev_id; + unsigned long index; +@@ -489,10 +497,10 @@ static pci_ers_result_t intel_vsec_pci_s + devm_release_action(&pdev->dev, intel_vsec_remove_aux, + &intel_vsec_dev->auxdev); + } +- pci_disable_device(pdev); + pci_restore_state(pdev); + pci_dev_id = pci_match_id(intel_vsec_pci_ids, pdev); +- intel_vsec_pci_probe(pdev, pci_dev_id); ++ info = (struct intel_vsec_platform_info *)pci_dev_id->driver_data; ++ intel_vsec_pci_init(pdev, info); + + out: + return status; diff --git a/queue-6.12/ring-buffer-flush-and-stop-persistent-ring-buffer-on-panic.patch b/queue-6.12/ring-buffer-flush-and-stop-persistent-ring-buffer-on-panic.patch new file mode 100644 index 0000000000..839a2b4c1c --- /dev/null +++ b/queue-6.12/ring-buffer-flush-and-stop-persistent-ring-buffer-on-panic.patch @@ -0,0 +1,321 @@ +From stable+bounces-256847-greg=kroah.com@vger.kernel.org Sat May 30 03:06:28 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 21:02:19 -0400 +Subject: ring-buffer: Flush and stop persistent ring buffer on panic +To: stable@vger.kernel.org +Cc: "Masami Hiramatsu (Google)" , Will Deacon , Mathieu Desnoyers , Ian Rogers , Catalin Marinas , Geert Uytterhoeven , Steven Rostedt , Sasha Levin +Message-ID: <20260530010219.2456798-1-sashal@kernel.org> + +From: "Masami Hiramatsu (Google)" + +[ Upstream commit a494d3c8d5392bcdff83c2a593df0c160ff9f322 ] + +On real hardware, panic and machine reboot may not flush hardware cache +to memory. This means the persistent ring buffer, which relies on a +coherent state of memory, may not have its events written to the buffer +and they may be lost. Moreover, there may be inconsistency with the +counters which are used for validation of the integrity of the +persistent ring buffer which may cause all data to be discarded. + +To avoid this issue, stop recording of the ring buffer on panic and +flush the cache of the ring buffer's memory. + +Fixes: e645535a954a ("tracing: Add option to use memmapped memory for trace boot instance") +Cc: stable@vger.kernel.org +Cc: Will Deacon +Cc: Mathieu Desnoyers +Cc: Ian Rogers +Link: https://patch.msgid.link/177751969602.2136606.12031934362587643488.stgit@mhiramat.tok.corp.google.com +Signed-off-by: Masami Hiramatsu (Google) +Acked-by: Catalin Marinas +Acked-by: Geert Uytterhoeven +Signed-off-by: Steven Rostedt +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/alpha/include/asm/Kbuild | 1 + + arch/arc/include/asm/Kbuild | 1 + + arch/arm/include/asm/Kbuild | 1 + + arch/arm64/include/asm/ring_buffer.h | 10 ++++++++++ + arch/csky/include/asm/Kbuild | 1 + + arch/hexagon/include/asm/Kbuild | 1 + + arch/loongarch/include/asm/Kbuild | 1 + + arch/m68k/include/asm/Kbuild | 1 + + arch/microblaze/include/asm/Kbuild | 1 + + arch/mips/include/asm/Kbuild | 1 + + arch/nios2/include/asm/Kbuild | 1 + + arch/openrisc/include/asm/Kbuild | 1 + + arch/parisc/include/asm/Kbuild | 1 + + arch/powerpc/include/asm/Kbuild | 1 + + arch/riscv/include/asm/Kbuild | 1 + + arch/s390/include/asm/Kbuild | 1 + + arch/sh/include/asm/Kbuild | 1 + + arch/sparc/include/asm/Kbuild | 1 + + arch/um/include/asm/Kbuild | 1 + + arch/x86/include/asm/Kbuild | 1 + + arch/xtensa/include/asm/Kbuild | 1 + + include/asm-generic/ring_buffer.h | 13 +++++++++++++ + kernel/trace/ring_buffer.c | 22 ++++++++++++++++++++++ + 23 files changed, 65 insertions(+) + create mode 100644 arch/arm64/include/asm/ring_buffer.h + create mode 100644 include/asm-generic/ring_buffer.h + +--- a/arch/alpha/include/asm/Kbuild ++++ b/arch/alpha/include/asm/Kbuild +@@ -5,3 +5,4 @@ generic-y += agp.h + generic-y += asm-offsets.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h ++generic-y += ring_buffer.h +--- a/arch/arc/include/asm/Kbuild ++++ b/arch/arc/include/asm/Kbuild +@@ -5,4 +5,5 @@ generic-y += extable.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h + generic-y += parport.h ++generic-y += ring_buffer.h + generic-y += user.h +--- a/arch/arm/include/asm/Kbuild ++++ b/arch/arm/include/asm/Kbuild +@@ -3,6 +3,7 @@ generic-y += early_ioremap.h + generic-y += extable.h + generic-y += flat.h + generic-y += parport.h ++generic-y += ring_buffer.h + + generated-y += mach-types.h + generated-y += unistd-nr.h +--- /dev/null ++++ b/arch/arm64/include/asm/ring_buffer.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++#ifndef _ASM_ARM64_RING_BUFFER_H ++#define _ASM_ARM64_RING_BUFFER_H ++ ++#include ++ ++/* Flush D-cache on persistent ring buffer */ ++#define arch_ring_buffer_flush_range(start, end) dcache_clean_pop(start, end) ++ ++#endif /* _ASM_ARM64_RING_BUFFER_H */ +--- a/arch/csky/include/asm/Kbuild ++++ b/arch/csky/include/asm/Kbuild +@@ -9,5 +9,6 @@ generic-y += qrwlock.h + generic-y += qrwlock_types.h + generic-y += qspinlock.h + generic-y += parport.h ++generic-y += ring_buffer.h + generic-y += user.h + generic-y += vmlinux.lds.h +--- a/arch/hexagon/include/asm/Kbuild ++++ b/arch/hexagon/include/asm/Kbuild +@@ -5,3 +5,4 @@ generic-y += extable.h + generic-y += iomap.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h ++generic-y += ring_buffer.h +--- a/arch/loongarch/include/asm/Kbuild ++++ b/arch/loongarch/include/asm/Kbuild +@@ -9,5 +9,6 @@ generic-y += qrwlock.h + generic-y += user.h + generic-y += ioctl.h + generic-y += mmzone.h ++generic-y += ring_buffer.h + generic-y += statfs.h + generic-y += param.h +--- a/arch/m68k/include/asm/Kbuild ++++ b/arch/m68k/include/asm/Kbuild +@@ -3,4 +3,5 @@ generated-y += syscall_table.h + generic-y += extable.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h ++generic-y += ring_buffer.h + generic-y += spinlock.h +--- a/arch/microblaze/include/asm/Kbuild ++++ b/arch/microblaze/include/asm/Kbuild +@@ -5,6 +5,7 @@ generic-y += extable.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h + generic-y += parport.h ++generic-y += ring_buffer.h + generic-y += syscalls.h + generic-y += tlb.h + generic-y += user.h +--- a/arch/mips/include/asm/Kbuild ++++ b/arch/mips/include/asm/Kbuild +@@ -12,4 +12,5 @@ generic-y += mcs_spinlock.h + generic-y += parport.h + generic-y += qrwlock.h + generic-y += qspinlock.h ++generic-y += ring_buffer.h + generic-y += user.h +--- a/arch/nios2/include/asm/Kbuild ++++ b/arch/nios2/include/asm/Kbuild +@@ -5,5 +5,6 @@ generic-y += cmpxchg.h + generic-y += extable.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h ++generic-y += ring_buffer.h + generic-y += spinlock.h + generic-y += user.h +--- a/arch/openrisc/include/asm/Kbuild ++++ b/arch/openrisc/include/asm/Kbuild +@@ -8,4 +8,5 @@ generic-y += spinlock_types.h + generic-y += spinlock.h + generic-y += qrwlock_types.h + generic-y += qrwlock.h ++generic-y += ring_buffer.h + generic-y += user.h +--- a/arch/parisc/include/asm/Kbuild ++++ b/arch/parisc/include/asm/Kbuild +@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h + generic-y += agp.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h ++generic-y += ring_buffer.h + generic-y += user.h +--- a/arch/powerpc/include/asm/Kbuild ++++ b/arch/powerpc/include/asm/Kbuild +@@ -6,4 +6,5 @@ generic-y += agp.h + generic-y += kvm_types.h + generic-y += mcs_spinlock.h + generic-y += qrwlock.h ++generic-y += ring_buffer.h + generic-y += early_ioremap.h +--- a/arch/riscv/include/asm/Kbuild ++++ b/arch/riscv/include/asm/Kbuild +@@ -11,5 +11,6 @@ generic-y += spinlock.h + generic-y += spinlock_types.h + generic-y += qrwlock.h + generic-y += qrwlock_types.h ++generic-y += ring_buffer.h + generic-y += user.h + generic-y += vmlinux.lds.h +--- a/arch/s390/include/asm/Kbuild ++++ b/arch/s390/include/asm/Kbuild +@@ -8,3 +8,4 @@ generic-y += asm-offsets.h + generic-y += kvm_types.h + generic-y += mcs_spinlock.h + generic-y += mmzone.h ++generic-y += ring_buffer.h +--- a/arch/sh/include/asm/Kbuild ++++ b/arch/sh/include/asm/Kbuild +@@ -3,3 +3,4 @@ generated-y += syscall_table.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h + generic-y += parport.h ++generic-y += ring_buffer.h +--- a/arch/sparc/include/asm/Kbuild ++++ b/arch/sparc/include/asm/Kbuild +@@ -4,3 +4,4 @@ generated-y += syscall_table_64.h + generic-y += agp.h + generic-y += kvm_para.h + generic-y += mcs_spinlock.h ++generic-y += ring_buffer.h +--- a/arch/um/include/asm/Kbuild ++++ b/arch/um/include/asm/Kbuild +@@ -19,6 +19,7 @@ generic-y += param.h + generic-y += parport.h + generic-y += percpu.h + generic-y += preempt.h ++generic-y += ring_buffer.h + generic-y += runtime-const.h + generic-y += softirq_stack.h + generic-y += switch_to.h +--- a/arch/x86/include/asm/Kbuild ++++ b/arch/x86/include/asm/Kbuild +@@ -12,3 +12,4 @@ generated-y += xen-hypercalls.h + generic-y += early_ioremap.h + generic-y += mcs_spinlock.h + generic-y += mmzone.h ++generic-y += ring_buffer.h +--- a/arch/xtensa/include/asm/Kbuild ++++ b/arch/xtensa/include/asm/Kbuild +@@ -7,4 +7,5 @@ generic-y += param.h + generic-y += parport.h + generic-y += qrwlock.h + generic-y += qspinlock.h ++generic-y += ring_buffer.h + generic-y += user.h +--- /dev/null ++++ b/include/asm-generic/ring_buffer.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Generic arch dependent ring_buffer macros. ++ */ ++#ifndef __ASM_GENERIC_RING_BUFFER_H__ ++#define __ASM_GENERIC_RING_BUFFER_H__ ++ ++#include ++ ++/* Flush cache on ring buffer range if needed. Do nothing by default. */ ++#define arch_ring_buffer_flush_range(start, end) do { } while (0) ++ ++#endif /* __ASM_GENERIC_RING_BUFFER_H__ */ +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -5,6 +5,7 @@ + * Copyright (C) 2008 Steven Rostedt + */ + #include ++#include + #include + #include + #include +@@ -29,6 +30,7 @@ + #include + #include + ++#include + #include + #include + +@@ -549,6 +551,7 @@ struct trace_buffer { + + unsigned long range_addr_start; + unsigned long range_addr_end; ++ struct notifier_block flush_nb; + + long last_text_delta; + long last_data_delta; +@@ -2316,6 +2319,16 @@ static void rb_free_cpu_buffer(struct ri + kfree(cpu_buffer); + } + ++/* Stop recording on a persistent buffer and flush cache if needed. */ ++static int rb_flush_buffer_cb(struct notifier_block *nb, unsigned long event, void *data) ++{ ++ struct trace_buffer *buffer = container_of(nb, struct trace_buffer, flush_nb); ++ ++ ring_buffer_record_off(buffer); ++ arch_ring_buffer_flush_range(buffer->range_addr_start, buffer->range_addr_end); ++ return NOTIFY_DONE; ++} ++ + static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, + int order, unsigned long start, + unsigned long end, +@@ -2421,6 +2434,12 @@ static struct trace_buffer *alloc_buffer + + mutex_init(&buffer->mutex); + ++ /* Persistent ring buffer needs to flush cache before reboot. */ ++ if (start && end) { ++ buffer->flush_nb.notifier_call = rb_flush_buffer_cb; ++ atomic_notifier_chain_register(&panic_notifier_list, &buffer->flush_nb); ++ } ++ + return buffer; + + fail_free_buffers: +@@ -2512,6 +2531,9 @@ ring_buffer_free(struct trace_buffer *bu + { + int cpu; + ++ if (buffer->range_addr_start && buffer->range_addr_end) ++ atomic_notifier_chain_unregister(&panic_notifier_list, &buffer->flush_nb); ++ + cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node); + + irq_work_sync(&buffer->irq_work.work); diff --git a/queue-6.12/rxrpc-fix-data-decrypt-vs-splice-by-copying-data-to-buffer-in-recvmsg.patch b/queue-6.12/rxrpc-fix-data-decrypt-vs-splice-by-copying-data-to-buffer-in-recvmsg.patch new file mode 100644 index 0000000000..160fd1f5cc --- /dev/null +++ b/queue-6.12/rxrpc-fix-data-decrypt-vs-splice-by-copying-data-to-buffer-in-recvmsg.patch @@ -0,0 +1,443 @@ +From stable+bounces-256788-greg=kroah.com@vger.kernel.org Fri May 29 23:42:17 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 17:42:07 -0400 +Subject: rxrpc: Fix DATA decrypt vs splice() by copying data to buffer in recvmsg +To: stable@vger.kernel.org +Cc: David Howells , Hyunwoo Kim , Simon Horman , Jiayuan Chen , linux-afs@lists.infradead.org, Jeffrey Altman , Marc Dionne , Jakub Kicinski , Sasha Levin +Message-ID: <20260529214208.1792984-1-sashal@kernel.org> + +From: David Howells + +[ Upstream commit d2bc90cf6c75cb96d2ce549be6c35efa3099d25b ] + +This improves the fix for CVE-2026-43500. + +Fix the pagecache corruption from in-place decryption of a DATA packet +transmitted locally by splice() by getting rid of the packet sharing in the +I/O thread and unconditionally extracting the packet content into a bounce +buffer in which the buffer is decrypted. recvmsg() (or the kernel +equivalent) then copies the data from the bounce buffer to the destination +buffer. The sk_buff then remains unmodified. + +This has an additional advantage in that the packet is then arranged in the +buffer with the correct alignment required for the crypto algorithms to +process directly. The performance of the crypto does seem to be a little +faster and, surprisingly, the unencrypted performance doesn't seem to +change much - possibly due to removing complexity from the I/O thread. + +Yet another advantage is that the I/O thread doesn't have to copy packets +which would slow down packet distribution, ACK generation, etc.. + +The buffer belongs to the call and is allocated initially at 2K, +sufficiently large to hold a whole jumbo subpacket, but the buffer will be +increased in size if needed. However, to take this work, MSG_PEEK may +cause a later packet to be decrypted into the buffer, in which case the +earlier one will need re-decrypting for a subsequent recvmsg(). + +Note that rx_pkt_offset may legitimately see 0 as a valid offset now, so +switch to using USHRT_MAX to indicate an invalid offset. + +Note also that I would generally prefer to replace the buffers of the +current sk_buff with a new kmalloc'd buffer of the right size, ditching the +old data and frags as this makes the handling of MSG_PEEK easier and +removes the re-decryption issue, but this looks like quite a complicated +thing to achieve. skb_morph() looks half way to what I want, but I don't +want to have to allocate a new sk_buff. + +Fixes: d0d5c0cd1e71 ("rxrpc: Use skb_unshare() rather than skb_cow_data()") +Reported-by: Hyunwoo Kim +Closes: https://lore.kernel.org/r/afKV2zGR6rrelPC7@v4bel/ +Signed-off-by: David Howells +cc: Simon Horman +cc: Jiayuan Chen +cc: linux-afs@lists.infradead.org +Reviewed-by: Jeffrey Altman +Tested-by: Marc Dionne +Link: https://patch.msgid.link/20260515230516.2718212-3-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 8bfab4b6ffc2 ("rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/ar-internal.h | 7 ++- + net/rxrpc/call_event.c | 27 +-------------- + net/rxrpc/call_object.c | 2 + + net/rxrpc/insecure.c | 3 - + net/rxrpc/recvmsg.c | 68 ++++++++++++++++++++++++++++++------- + net/rxrpc/rxkad.c | 86 +++++++++++++++++------------------------------- + 6 files changed, 96 insertions(+), 97 deletions(-) + +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -203,8 +203,6 @@ struct rxrpc_skb_priv { + struct { + u16 offset; /* Offset of data */ + u16 len; /* Length of data */ +- u8 flags; +-#define RXRPC_RX_VERIFIED 0x01 + }; + struct { + rxrpc_seq_t first_ack; /* First packet in acks table */ +@@ -686,6 +684,11 @@ struct rxrpc_call { + /* Received data tracking */ + struct sk_buff_head recvmsg_queue; /* Queue of packets ready for recvmsg() */ + struct sk_buff_head rx_oos_queue; /* Queue of out of sequence packets */ ++ void *rx_dec_buffer; /* Decryption buffer */ ++ unsigned short rx_dec_bsize; /* rx_dec_buffer size */ ++ unsigned short rx_dec_offset; /* Decrypted packet data offset */ ++ unsigned short rx_dec_len; /* Decrypted packet data len */ ++ rxrpc_seq_t rx_dec_seq; /* Packet in decryption buffer */ + + rxrpc_seq_t rx_highest_seq; /* Higest sequence number received */ + rxrpc_seq_t rx_consumed; /* Highest packet consumed */ +--- a/net/rxrpc/call_event.c ++++ b/net/rxrpc/call_event.c +@@ -342,31 +342,8 @@ bool rxrpc_input_call_event(struct rxrpc + if (skb && skb->mark == RXRPC_SKB_MARK_ERROR) + goto out; + +- if (skb) { +- struct rxrpc_skb_priv *sp = rxrpc_skb(skb); +- +- if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && +- sp->hdr.securityIndex != 0 && +- (skb_cloned(skb) || +- skb_has_frag_list(skb) || +- skb_has_shared_frag(skb))) { +- /* Unshare the packet so that it can be modified for +- * in-place decryption. +- */ +- struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); +- +- if (nskb) { +- rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); +- rxrpc_input_call_packet(call, nskb); +- rxrpc_free_skb(nskb, rxrpc_skb_put_input); +- } else { +- /* OOM - Drop the packet. */ +- rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); +- } +- } else { +- rxrpc_input_call_packet(call, skb); +- } +- } ++ if (skb) ++ rxrpc_input_call_packet(call, skb); + + /* If we see our async-event poke, check for timeout trippage. */ + now = ktime_get_real(); +--- a/net/rxrpc/call_object.c ++++ b/net/rxrpc/call_object.c +@@ -154,6 +154,7 @@ struct rxrpc_call *rxrpc_alloc_call(stru + spin_lock_init(&call->tx_lock); + refcount_set(&call->ref, 1); + call->debug_id = debug_id; ++ call->rx_pkt_offset = USHRT_MAX; + call->tx_total_len = -1; + call->next_rx_timo = 20 * HZ; + call->next_req_timo = 1 * HZ; +@@ -535,6 +536,7 @@ static void rxrpc_cleanup_ring(struct rx + { + rxrpc_purge_queue(&call->recvmsg_queue); + rxrpc_purge_queue(&call->rx_oos_queue); ++ kfree(call->rx_dec_buffer); + } + + /* +--- a/net/rxrpc/insecure.c ++++ b/net/rxrpc/insecure.c +@@ -29,9 +29,6 @@ static int none_secure_packet(struct rxr + + static int none_verify_packet(struct rxrpc_call *call, struct sk_buff *skb) + { +- struct rxrpc_skb_priv *sp = rxrpc_skb(skb); +- +- sp->flags |= RXRPC_RX_VERIFIED; + return 0; + } + +--- a/net/rxrpc/recvmsg.c ++++ b/net/rxrpc/recvmsg.c +@@ -143,15 +143,52 @@ static void rxrpc_rotate_rx_window(struc + } + + /* +- * Decrypt and verify a DATA packet. ++ * Decrypt and verify a DATA packet. The content of the packet is pulled out ++ * into a flat buffer rather than decrypting in place in the skbuff. This also ++ * has the advantage of aligning the buffer correctly for the crypto routines. ++ * ++ * We keep track of the sequence number of the packet currently decrypted into ++ * the buffer in ->rx_dec_seq. If MSG_PEEK is used and steps onto a new ++ * packet, subsequent recvmsg() calls will have to go back and re-decrypt the ++ * current packet. + */ + static int rxrpc_verify_data(struct rxrpc_call *call, struct sk_buff *skb) + { + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); ++ int ret; + +- if (sp->flags & RXRPC_RX_VERIFIED) +- return 0; +- return call->security->verify_packet(call, skb); ++ if (sp->len > call->rx_dec_bsize) { ++ /* Make sure we can hold a 1412-byte jumbo subpacket and make ++ * sure that the buffer size is aligned to a crypto blocksize. ++ */ ++ size_t size = clamp(round_up(sp->len, 32), 2048, 65535); ++ void *buffer = krealloc(call->rx_dec_buffer, size, GFP_NOFS); ++ ++ if (!buffer) ++ return -ENOMEM; ++ call->rx_dec_buffer = buffer; ++ call->rx_dec_bsize = size; ++ } ++ ++ ret = -EFAULT; ++ if (skb_copy_bits(skb, sp->offset, call->rx_dec_buffer, sp->len) < 0) ++ goto err; ++ ++ call->rx_dec_offset = 0; ++ call->rx_dec_len = sp->len; ++ call->rx_dec_seq = sp->hdr.seq; ++ ret = call->security->verify_packet(call, skb); ++ if (ret < 0) ++ goto err; ++ return 0; ++ ++err: ++ kfree(call->rx_dec_buffer); ++ call->rx_dec_buffer = NULL; ++ call->rx_dec_bsize = 0; ++ call->rx_dec_offset = 0; ++ call->rx_dec_len = 0; ++ return ret; + } + + /* +@@ -202,17 +239,22 @@ static int rxrpc_recvmsg_data(struct soc + if (msg) + sock_recv_timestamp(msg, sock->sk, skb); + +- if (rx_pkt_offset == 0) { ++ if (call->rx_dec_seq != sp->hdr.seq || ++ !call->rx_dec_buffer) { + ret2 = rxrpc_verify_data(call, skb); + trace_rxrpc_recvdata(call, rxrpc_recvmsg_next, seq, +- sp->offset, sp->len, ret2); ++ call->rx_dec_offset, ++ call->rx_dec_len, ret2); + if (ret2 < 0) { + kdebug("verify = %d", ret2); + ret = ret2; + goto out; + } +- rx_pkt_offset = sp->offset; +- rx_pkt_len = sp->len; ++ } ++ ++ if (rx_pkt_offset == USHRT_MAX) { ++ rx_pkt_offset = call->rx_dec_offset; ++ rx_pkt_len = call->rx_dec_len; + } else { + trace_rxrpc_recvdata(call, rxrpc_recvmsg_cont, seq, + rx_pkt_offset, rx_pkt_len, 0); +@@ -224,10 +266,10 @@ static int rxrpc_recvmsg_data(struct soc + if (copy > remain) + copy = remain; + if (copy > 0) { +- ret2 = skb_copy_datagram_iter(skb, rx_pkt_offset, iter, +- copy); +- if (ret2 < 0) { +- ret = ret2; ++ ret2 = copy_to_iter(call->rx_dec_buffer + rx_pkt_offset, ++ copy, iter); ++ if (ret2 != copy) { ++ ret = -EFAULT; + goto out; + } + +@@ -248,7 +290,7 @@ static int rxrpc_recvmsg_data(struct soc + /* The whole packet has been transferred. */ + if (sp->hdr.flags & RXRPC_LAST_PACKET) + ret = 1; +- rx_pkt_offset = 0; ++ rx_pkt_offset = USHRT_MAX; + rx_pkt_len = 0; + + skb = skb_peek_next(skb, &call->recvmsg_queue); +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -414,27 +414,25 @@ static int rxkad_verify_packet_1(struct + rxrpc_seq_t seq, + struct skcipher_request *req) + { +- struct rxkad_level1_hdr sechdr; ++ struct rxkad_level1_hdr *sechdr; + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); + struct rxrpc_crypt iv; +- struct scatterlist sg[16]; +- u32 data_size, buf; ++ struct scatterlist sg[1]; ++ void *data = call->rx_dec_buffer; ++ u32 len = sp->len, data_size, buf; + u16 check; + int ret; + + _enter(""); + +- if (sp->len < 8) ++ if (len < 8) + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxkad_abort_1_short_header); + + /* Decrypt the skbuff in-place. TODO: We really want to decrypt + * directly into the target buffer. + */ +- sg_init_table(sg, ARRAY_SIZE(sg)); +- ret = skb_to_sgvec(skb, sg, sp->offset, 8); +- if (unlikely(ret < 0)) +- return ret; ++ sg_init_one(sg, data, len); + + /* start the decryption afresh */ + memset(&iv, 0, sizeof(iv)); +@@ -448,13 +446,11 @@ static int rxkad_verify_packet_1(struct + return ret; + + /* Extract the decrypted packet length */ +- if (skb_copy_bits(skb, sp->offset, &sechdr, sizeof(sechdr)) < 0) +- return rxrpc_abort_eproto(call, skb, RXKADDATALEN, +- rxkad_abort_1_short_encdata); +- sp->offset += sizeof(sechdr); +- sp->len -= sizeof(sechdr); ++ sechdr = data; ++ call->rx_dec_offset = sizeof(*sechdr); ++ len -= sizeof(*sechdr); + +- buf = ntohl(sechdr.data_size); ++ buf = ntohl(sechdr->data_size); + data_size = buf & 0xffff; + + check = buf >> 16; +@@ -463,10 +459,10 @@ static int rxkad_verify_packet_1(struct + if (check != 0) + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxkad_abort_1_short_check); +- if (data_size > sp->len) ++ if (data_size > len) + return rxrpc_abort_eproto(call, skb, RXKADDATALEN, + rxkad_abort_1_short_data); +- sp->len = data_size; ++ call->rx_dec_len = data_size; + + _leave(" = 0 [dlen=%x]", data_size); + return 0; +@@ -480,43 +476,28 @@ static int rxkad_verify_packet_2(struct + struct skcipher_request *req) + { + const struct rxrpc_key_token *token; +- struct rxkad_level2_hdr sechdr; ++ struct rxkad_level2_hdr *sechdr; + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); + struct rxrpc_crypt iv; +- struct scatterlist _sg[4], *sg; +- u32 data_size, buf; ++ struct scatterlist sg[1]; ++ void *data = call->rx_dec_buffer; ++ u32 len = sp->len, data_size, buf; + u16 check; +- int nsg, ret; ++ int ret; + +- _enter(",{%d}", sp->len); ++ _enter(",{%d}", len); + +- if (sp->len < 8) ++ if (len < 8) + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxkad_abort_2_short_header); + + /* Don't let the crypto algo see a misaligned length. */ +- sp->len = round_down(sp->len, 8); ++ len = round_down(len, 8); + +- /* Decrypt the skbuff in-place. TODO: We really want to decrypt +- * directly into the target buffer. ++ /* Decrypt in place in the call's decryption buffer. TODO: We really ++ * want to decrypt directly into the target buffer. + */ +- sg = _sg; +- nsg = skb_shinfo(skb)->nr_frags + 1; +- if (nsg <= 4) { +- nsg = 4; +- } else { +- sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO); +- if (!sg) +- return -ENOMEM; +- } +- +- sg_init_table(sg, nsg); +- ret = skb_to_sgvec(skb, sg, sp->offset, sp->len); +- if (unlikely(ret < 0)) { +- if (sg != _sg) +- kfree(sg); +- return ret; +- } ++ sg_init_one(sg, data, len); + + /* decrypt from the session key */ + token = call->conn->key->payload.data[0]; +@@ -524,11 +505,9 @@ static int rxkad_verify_packet_2(struct + + skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); +- skcipher_request_set_crypt(req, sg, sg, sp->len, iv.x); ++ skcipher_request_set_crypt(req, sg, sg, len, iv.x); + ret = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); +- if (sg != _sg) +- kfree(sg); + if (ret < 0) { + if (ret == -ENOMEM) + return ret; +@@ -537,13 +516,11 @@ static int rxkad_verify_packet_2(struct + } + + /* Extract the decrypted packet length */ +- if (skb_copy_bits(skb, sp->offset, &sechdr, sizeof(sechdr)) < 0) +- return rxrpc_abort_eproto(call, skb, RXKADDATALEN, +- rxkad_abort_2_short_len); +- sp->offset += sizeof(sechdr); +- sp->len -= sizeof(sechdr); ++ sechdr = data; ++ call->rx_dec_offset = sizeof(*sechdr); ++ len -= sizeof(*sechdr); + +- buf = ntohl(sechdr.data_size); ++ buf = ntohl(sechdr->data_size); + data_size = buf & 0xffff; + + check = buf >> 16; +@@ -553,17 +530,18 @@ static int rxkad_verify_packet_2(struct + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxkad_abort_2_short_check); + +- if (data_size > sp->len) ++ if (data_size > len) + return rxrpc_abort_eproto(call, skb, RXKADDATALEN, + rxkad_abort_2_short_data); + +- sp->len = data_size; ++ call->rx_dec_len = data_size; + _leave(" = 0 [dlen=%x]", data_size); + return 0; + } + + /* +- * Verify the security on a received packet and the subpackets therein. ++ * Verify the security on a received (sub)packet. If the packet needs ++ * modifying (e.g. decrypting), it must be copied. + */ + static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb) + { diff --git a/queue-6.12/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch b/queue-6.12/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch new file mode 100644 index 0000000000..37549debc9 --- /dev/null +++ b/queue-6.12/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch @@ -0,0 +1,192 @@ +From stable+bounces-256789-greg=kroah.com@vger.kernel.org Fri May 29 23:42:18 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 17:42:08 -0400 +Subject: rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer +To: stable@vger.kernel.org +Cc: David Howells , Hyunwoo Kim , Simon Horman , Jiayuan Chen , linux-afs@lists.infradead.org, stable@kernel.org, Jeffrey Altman , Marc Dionne , Jakub Kicinski , Sasha Levin +Message-ID: <20260529214208.1792984-2-sashal@kernel.org> + +From: David Howells + +[ Upstream commit 8bfab4b6ffc2fe92da86300728fc8c3c7ebffb56 ] + +This improves the fix for CVE-2026-43500. + +Fix the verification of RESPONSE packets to avoid the problem of +overwriting a RESPONSE packet sent via splice to a local address by +extracting the contents of the UDP packet into a kmalloc'd linear buffer +rather than decrypting the data in place in the sk_buff (which may corrupt +the original buffer). + +Fixes: 24481a7f5733 ("rxrpc: Fix conn-level packet handling to unshare RESPONSE packets") +Reported-by: Hyunwoo Kim +Closes: https://lore.kernel.org/r/afKV2zGR6rrelPC7@v4bel/ +Signed-off-by: David Howells +cc: Simon Horman +cc: Jiayuan Chen +cc: linux-afs@lists.infradead.org +cc: stable@kernel.org +Reviewed-by: Jeffrey Altman +Tested-by: Marc Dionne +Link: https://patch.msgid.link/20260515230516.2718212-4-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/ar-internal.h | 5 +++-- + net/rxrpc/conn_event.c | 30 ++++++++++++------------------ + net/rxrpc/insecure.c | 5 +++-- + net/rxrpc/rxkad.c | 29 ++++++++++------------------- + 4 files changed, 28 insertions(+), 41 deletions(-) + +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -270,8 +270,9 @@ struct rxrpc_security { + struct sk_buff *); + + /* verify a response */ +- int (*verify_response)(struct rxrpc_connection *, +- struct sk_buff *); ++ int (*verify_response)(struct rxrpc_connection *conn, ++ struct sk_buff *response_skb, ++ void *response, unsigned int len); + + /* clear connection security */ + void (*clear)(struct rxrpc_connection *); +--- a/net/rxrpc/conn_event.c ++++ b/net/rxrpc/conn_event.c +@@ -229,28 +229,22 @@ static void rxrpc_call_is_secure(struct + static int rxrpc_verify_response(struct rxrpc_connection *conn, + struct sk_buff *skb) + { ++ unsigned int len = skb->len - sizeof(struct rxrpc_wire_header); ++ void *buffer; + int ret; + +- if (skb_cloned(skb) || skb_has_frag_list(skb) || +- skb_has_shared_frag(skb)) { +- /* Copy the packet if shared so that we can do in-place +- * decryption. +- */ +- struct sk_buff *nskb = skb_copy(skb, GFP_NOFS); ++ buffer = kmalloc(len, GFP_NOFS); ++ if (!buffer) ++ return -ENOMEM; + +- if (nskb) { +- rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); +- ret = conn->security->verify_response(conn, nskb); +- rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy); +- } else { +- /* OOM - Drop the packet. */ +- rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); +- ret = -ENOMEM; +- } +- } else { +- ret = conn->security->verify_response(conn, skb); +- } ++ ret = skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), buffer, len); ++ if (ret < 0) ++ goto out; + ++ ret = conn->security->verify_response(conn, skb, buffer, len); ++ ++out: ++ kfree(buffer); + return ret; + } + +--- a/net/rxrpc/insecure.c ++++ b/net/rxrpc/insecure.c +@@ -44,9 +44,10 @@ static int none_respond_to_challenge(str + } + + static int none_verify_response(struct rxrpc_connection *conn, +- struct sk_buff *skb) ++ struct sk_buff *response_skb, ++ void *response, unsigned int len) + { +- return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO, ++ return rxrpc_abort_conn(conn, response_skb, RX_PROTOCOL_ERROR, -EPROTO, + rxrpc_eproto_rxnull_response); + } + +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -875,7 +875,6 @@ static int rxkad_decrypt_ticket(struct r + *_expiry = 0; + + ASSERT(server_key->payload.data[0] != NULL); +- ASSERTCMP((unsigned long) ticket & 7UL, ==, 0); + + memcpy(&iv, &server_key->payload.data[2], sizeof(iv)); + +@@ -1024,14 +1023,15 @@ unlock: + * verify a response + */ + static int rxkad_verify_response(struct rxrpc_connection *conn, +- struct sk_buff *skb) ++ struct sk_buff *skb, ++ void *buffer, unsigned int len) + { + struct rxkad_response *response; + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); + struct rxrpc_crypt session_key; + struct key *server_key; + time64_t expiry; +- void *ticket = NULL; ++ void *ticket; + u32 version, kvno, ticket_len, level; + __be32 csum; + int ret, i; +@@ -1054,13 +1054,8 @@ static int rxkad_verify_response(struct + } + } + +- ret = -ENOMEM; +- response = kzalloc(sizeof(struct rxkad_response), GFP_NOFS); +- if (!response) +- goto error; +- +- if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), +- response, sizeof(*response)) < 0) { ++ response = buffer; ++ if (len < sizeof(*response)) { + ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, + rxkad_abort_resp_short); + goto error; +@@ -1072,6 +1067,9 @@ static int rxkad_verify_response(struct + + trace_rxrpc_rx_response(conn, sp->hdr.serial, version, kvno, ticket_len); + ++ buffer += sizeof(*response); ++ len -= sizeof(*response); ++ + if (version != RXKAD_VERSION) { + ret = rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO, + rxkad_abort_resp_version); +@@ -1091,13 +1089,8 @@ static int rxkad_verify_response(struct + } + + /* extract the kerberos ticket and decrypt and decode it */ +- ret = -ENOMEM; +- ticket = kmalloc(ticket_len, GFP_NOFS); +- if (!ticket) +- goto error; +- +- if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + sizeof(*response), +- ticket, ticket_len) < 0) { ++ ticket = buffer; ++ if (ticket_len > len) { + ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, + rxkad_abort_resp_short_tkt); + goto error; +@@ -1177,8 +1170,6 @@ static int rxkad_verify_response(struct + ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno); + + error: +- kfree(ticket); +- kfree(response); + key_put(server_key); + _leave(" = %d", ret); + return ret; diff --git a/queue-6.12/scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch b/queue-6.12/scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch new file mode 100644 index 0000000000..1dbda187fb --- /dev/null +++ b/queue-6.12/scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch @@ -0,0 +1,124 @@ +From stable+bounces-260848-greg=kroah.com@vger.kernel.org Sat Jun 6 04:47:30 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 22:47:23 -0400 +Subject: scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd() +To: stable@vger.kernel.org +Cc: Michael Bommarito , John Garry , "Martin K. Petersen" , Sasha Levin +Message-ID: <20260606024723.2515163-1-sashal@kernel.org> + +From: Michael Bommarito + +[ 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 +Tested-by: John Garry +Reviewed-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -2329,8 +2329,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" +@@ -2350,6 +2351,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.12/selftests-mptcp-drop-nanoseconds-width-specifier.patch b/queue-6.12/selftests-mptcp-drop-nanoseconds-width-specifier.patch new file mode 100644 index 0000000000..f8202fc44a --- /dev/null +++ b/queue-6.12/selftests-mptcp-drop-nanoseconds-width-specifier.patch @@ -0,0 +1,112 @@ +From stable+bounces-256841-greg=kroah.com@vger.kernel.org Sat May 30 02:30:25 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 20:25:46 -0400 +Subject: selftests: mptcp: drop nanoseconds width specifier +To: stable@vger.kernel.org +Cc: "Matthieu Baerts (NGI0)" , Paolo Abeni , Sasha Levin +Message-ID: <20260530002546.2210747-1-sashal@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +[ Upstream commit 01ff78e4b3d98689184c52d97f9575dfbdc3b10f ] + +Using the format specifier +%s%3N with GNU date is honoured, and only +prints 3 digits of the nanoseconds portion of the seconds since epoch, +which corresponds to the milliseconds. + +The uutils implementation of date currently does not honour this, and +always prints all 9 digits. This is a known issue [1], but can be worked +around by adapting this test to use nanoseconds instead of microseconds, +and then divide it by 1e6. + +This fix is similar to what has been done on systemd side [2], and it is +needed to run the selftests on Ubuntu 26.04, containing uutils 0.8.0. + +Note that the Fixes tag is there even if this patch doesn't fix an issue +in the kernel selftests, but it is useful for those using uutils 0.8.0. + +Fixes: 048d19d444be ("mptcp: add basic kselftest for mptcp") +Cc: stable@vger.kernel.org +Link: https://github.com/uutils/coreutils/issues/11658 [1] +Link: https://github.com/systemd/systemd/pull/41627 [2] +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260515-net-mptcp-misc-fixes-7-1-rc4-v2-6-701e96419f2f@kernel.org +Signed-off-by: Paolo Abeni +[ kept `timeout ${timeout_test}` wrapper in do_transfer() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/net/mptcp/mptcp_connect.sh | 6 +++--- + tools/testing/selftests/net/mptcp/mptcp_lib.sh | 10 +++++----- + 2 files changed, 8 insertions(+), 8 deletions(-) + +--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh +@@ -412,7 +412,7 @@ do_transfer() + mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}" + + local start +- start=$(date +%s%3N) ++ start=$(date +%s%N) + timeout ${timeout_test} \ + ip netns exec ${connector_ns} \ + ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ +@@ -425,7 +425,7 @@ do_transfer() + local rets=$? + + local stop +- stop=$(date +%s%3N) ++ stop=$(date +%s%N) + + if $capture; then + sleep 1 +@@ -441,7 +441,7 @@ do_transfer() + fi + + local duration +- duration=$((stop-start)) ++ duration=$(((stop-start) / 1000000)) + printf "(duration %05sms) " "${duration}" + if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then + mptcp_lib_pr_fail "client exit code $retc, server $rets" +--- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh +@@ -29,7 +29,7 @@ declare -rx MPTCP_LIB_AF_INET6=10 + MPTCP_LIB_SUBTESTS=() + MPTCP_LIB_SUBTESTS_DUPLICATED=0 + MPTCP_LIB_SUBTEST_FLAKY=0 +-MPTCP_LIB_SUBTESTS_LAST_TS_MS= ++MPTCP_LIB_SUBTESTS_LAST_TS_NS= + MPTCP_LIB_TEST_COUNTER=0 + MPTCP_LIB_TEST_FORMAT="%02u %-50s" + MPTCP_LIB_IP_MPTCP=0 +@@ -207,7 +207,7 @@ mptcp_lib_kversion_ge() { + } + + mptcp_lib_subtests_last_ts_reset() { +- MPTCP_LIB_SUBTESTS_LAST_TS_MS="$(date +%s%3N)" ++ MPTCP_LIB_SUBTESTS_LAST_TS_NS="$(date +%s%N)" + } + mptcp_lib_subtests_last_ts_reset + +@@ -226,7 +226,7 @@ __mptcp_lib_result_check_duplicated() { + __mptcp_lib_result_add() { + local result="${1}" + local time="time=" +- local ts_prev_ms ++ local ts_prev_ns + shift + + local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1)) +@@ -236,9 +236,9 @@ __mptcp_lib_result_add() { + # not to add two '#' + [[ "${*}" != *"#"* ]] && time="# ${time}" + +- ts_prev_ms="${MPTCP_LIB_SUBTESTS_LAST_TS_MS}" ++ ts_prev_ns="${MPTCP_LIB_SUBTESTS_LAST_TS_NS}" + mptcp_lib_subtests_last_ts_reset +- time+="$((MPTCP_LIB_SUBTESTS_LAST_TS_MS - ts_prev_ms))ms" ++ time+="$(((MPTCP_LIB_SUBTESTS_LAST_TS_NS - ts_prev_ns) / 1000000))ms" + + MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*} ${time}") + } diff --git a/queue-6.12/serdev-provide-a-bustype-shutdown-function.patch b/queue-6.12/serdev-provide-a-bustype-shutdown-function.patch new file mode 100644 index 0000000000..83fb39ce96 --- /dev/null +++ b/queue-6.12/serdev-provide-a-bustype-shutdown-function.patch @@ -0,0 +1,88 @@ +From stable+bounces-256738-greg=kroah.com@vger.kernel.org Fri May 29 21:28:03 2026 +From: Sasha Levin +Date: Fri, 29 May 2026 15:27:54 -0400 +Subject: serdev: Provide a bustype shutdown function +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20260529192756.1699014-1-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit 6d71c62b13c33ea858ab298fe20beaec5736edc7 ] + +To prepare serdev driver to migrate away from struct device_driver::shutdown +(and then eventually remove that callback) create a serdev driver shutdown +callback and migration code to keep the existing behaviour. Note this +introduces a warning for each driver at register time that isn't converted +yet to that callback. + +Signed-off-by: Uwe Kleine-König +Link: https://patch.msgid.link/ab518883e3ed0976a19cb5b5b5faf42bd3a655b7.1765526117.git.u.kleine-koenig@baylibre.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 375ba7484132 ("Bluetooth: hci_qca: Convert timeout from jiffies to ms") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serdev/core.c | 21 +++++++++++++++++++++ + include/linux/serdev.h | 1 + + 2 files changed, 22 insertions(+) + +--- a/drivers/tty/serdev/core.c ++++ b/drivers/tty/serdev/core.c +@@ -431,11 +431,21 @@ static void serdev_drv_remove(struct dev + dev_pm_domain_detach(dev, true); + } + ++static void serdev_drv_shutdown(struct device *dev) ++{ ++ const struct serdev_device_driver *sdrv = ++ to_serdev_device_driver(dev->driver); ++ ++ if (dev->driver && sdrv->shutdown) ++ sdrv->shutdown(to_serdev_device(dev)); ++} ++ + static const struct bus_type serdev_bus_type = { + .name = "serial", + .match = serdev_device_match, + .probe = serdev_drv_probe, + .remove = serdev_drv_remove, ++ .shutdown = serdev_drv_shutdown, + }; + + /** +@@ -832,6 +842,14 @@ void serdev_controller_remove(struct ser + } + EXPORT_SYMBOL_GPL(serdev_controller_remove); + ++static void serdev_legacy_shutdown(struct serdev_device *serdev) ++{ ++ struct device *dev = &serdev->dev; ++ struct device_driver *driver = dev->driver; ++ ++ driver->shutdown(dev); ++} ++ + /** + * __serdev_device_driver_register() - Register client driver with serdev core + * @sdrv: client driver to be associated with client-device. +@@ -848,6 +866,9 @@ int __serdev_device_driver_register(stru + /* force drivers to async probe so I/O is possible in probe */ + sdrv->driver.probe_type = PROBE_PREFER_ASYNCHRONOUS; + ++ if (!sdrv->shutdown && sdrv->driver.shutdown) ++ sdrv->shutdown = serdev_legacy_shutdown; ++ + return driver_register(&sdrv->driver); + } + EXPORT_SYMBOL_GPL(__serdev_device_driver_register); +--- a/include/linux/serdev.h ++++ b/include/linux/serdev.h +@@ -65,6 +65,7 @@ struct serdev_device_driver { + struct device_driver driver; + int (*probe)(struct serdev_device *); + void (*remove)(struct serdev_device *); ++ void (*shutdown)(struct serdev_device *); + }; + + static inline struct serdev_device_driver *to_serdev_device_driver(struct device_driver *d) diff --git a/queue-6.12/series b/queue-6.12/series index 2699626d3a..332f4ae5cf 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -265,3 +265,37 @@ xhci-tegra-fix-ghost-usb-device-on-dual-role-port-un.patch iommu-skip-pasid-validation-for-devices-without-pasi.patch x86-boot-disable-stack-protector-for-early-boot-code.patch x86-kexec-disable-kcov-instrumentation-after-load_se.patch +rxrpc-fix-data-decrypt-vs-splice-by-copying-data-to-buffer-in-recvmsg.patch +rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch +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 +alsa-scarlett2-return-enospc-for-out-of-bounds-flash-writes.patch +alsa-scarlett2-allow-flash-writes-ending-at-segment-boundary.patch +mm-memory-fix-spurious-warning-when-unmapping-device-private-exclusive-pages.patch +platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch +net-hsr-defer-node-table-free-until-after-rcu-readers.patch +selftests-mptcp-drop-nanoseconds-width-specifier.patch +mptcp-pm-fix-add_addr-timer-infinite-retry-on-option-space-insufficient.patch +ice-fix-vf-queue-configuration-with-low-mtu-values.patch +ring-buffer-flush-and-stop-persistent-ring-buffer-on-panic.patch +mptcp-cleanup-fallback-dummy-mapping-generation.patch +mptcp-reset-rcv-wnd-on-disconnect.patch +arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch +octeontx2-pf-avoid-double-free-of-pool-stack-on-aq-init-failure.patch +mptcp-introduce-the-mptcp_init_skb-helper.patch +mptcp-handle-first-subflow-closing-consistently.patch +mptcp-do-not-drop-partial-packets.patch +mm-damon-sysfs-schemes-delete-tried-region-in-regions_rmdirs.patch +iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch +iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch +iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch +alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch +usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.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 +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 +usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch +x86-alternatives-rename-apply_relocation-to-text_poke_apply_relocation.patch +x86-ftrace-relocate-rip-relative-percpu-refs-in-dynamic-trampolines.patch diff --git a/queue-6.12/thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch b/queue-6.12/thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch new file mode 100644 index 0000000000..08603d97d6 --- /dev/null +++ b/queue-6.12/thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch @@ -0,0 +1,112 @@ +From stable+bounces-260780-greg=kroah.com@vger.kernel.org Fri Jun 5 21:34:21 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 15:33:10 -0400 +Subject: thunderbolt: property: Cap recursion depth in __tb_property_parse_dir() +To: stable@vger.kernel.org +Cc: Michael Bommarito , Mika Westerberg , Sasha Levin +Message-ID: <20260605193310.2159165-1-sashal@kernel.org> + +From: Michael Bommarito + +[ 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 +Signed-off-by: Mika Westerberg +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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) + { +@@ -97,7 +98,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; +@@ -118,7 +120,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; +@@ -163,13 +165,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; +@@ -200,7 +206,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; +@@ -237,7 +243,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.12/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch b/queue-6.12/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch new file mode 100644 index 0000000000..68ee684a05 --- /dev/null +++ b/queue-6.12/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch @@ -0,0 +1,95 @@ +From sashal@kernel.org Fri Jun 5 15:53:35 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 09:53:32 -0400 +Subject: usb: dwc3: xilinx: fix error handling in zynqmp init error paths +To: stable@vger.kernel.org +Cc: Radhey Shyam Pandey , Thinh Nguyen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605135332.930021-1-sashal@kernel.org> + +From: Radhey Shyam Pandey + +[ 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 +Signed-off-by: Radhey Shyam Pandey +Link: https://patch.msgid.link/20260519115529.2980421-1-radhey.shyam.pandey@amd.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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.12/usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch b/queue-6.12/usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch new file mode 100644 index 0000000000..d0321ba05f --- /dev/null +++ b/queue-6.12/usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch @@ -0,0 +1,54 @@ +From sashal@kernel.org Fri Jun 5 15:57:47 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 09:57:44 -0400 +Subject: usb: musb: omap2430: Fix use-after-free in omap2430_probe() +To: stable@vger.kernel.org +Cc: Wentao Liang , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605135745.975090-1-sashal@kernel.org> + +From: Wentao Liang + +[ 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 +Signed-off-by: Wentao Liang +Link: https://patch.msgid.link/20260409101104.480623-1-vulab@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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.12/usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch b/queue-6.12/usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch new file mode 100644 index 0000000000..2059d638fb --- /dev/null +++ b/queue-6.12/usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch @@ -0,0 +1,68 @@ +From stable+bounces-260765-greg=kroah.com@vger.kernel.org Fri Jun 5 20:32:15 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 14:31:35 -0400 +Subject: usb: typec: ucsi: Check if power role change actually happened before handling +To: stable@vger.kernel.org +Cc: Myrrh Periwinkle , stable , Sergey Senozhatsky , Heikki Krogerus , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605183135.2056737-1-sashal@kernel.org> + +From: Myrrh Periwinkle + +[ 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 +Fixes: 7616f006db07 ("usb: typec: ucsi: Update power_supply on power role change") +Signed-off-by: Myrrh Periwinkle +Reported-and-tested-by: Sergey Senozhatsky +Reviewed-by: Heikki Krogerus +Link: https://patch.msgid.link/20260519-ucsi-fix-2-v1-1-6f1239535187@qtmlabs.xyz +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -1201,7 +1201,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; + +@@ -1211,6 +1211,8 @@ static void ucsi_handle_connector_change + dev_err_once(ucsi->dev, "%s entered without EVENT_PENDING\n", + __func__); + ++ prev_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); ++ + command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); + + ret = ucsi_send_command_common(ucsi, command, &con->status, +@@ -1229,7 +1231,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.12/usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch b/queue-6.12/usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch new file mode 100644 index 0000000000..6da4e3f48f --- /dev/null +++ b/queue-6.12/usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch @@ -0,0 +1,47 @@ +From stable+bounces-260867-greg=kroah.com@vger.kernel.org Sat Jun 6 14:20:06 2026 +From: Sasha Levin +Date: Sat, 6 Jun 2026 08:18:59 -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 , stable , Sergey Senozhatsky , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260606121900.2851177-1-sashal@kernel.org> + +From: Myrrh Periwinkle + +[ 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 +Fixes: 7616f006db07 ("usb: typec: ucsi: Update power_supply on power role change") +Signed-off-by: Myrrh Periwinkle +Reported-and-tested-by: Sergey Senozhatsky +Link: https://patch.msgid.link/20260519-ucsi-fix-2-v1-2-6f1239535187@qtmlabs.xyz +Signed-off-by: Greg Kroah-Hartman +[ This is documentation for an already-completed backport. The change is described clearly. + +"translated upstream `UCSI_CONSTAT(con, CONNECTED)` accessor macro to in-tree idiom `con->status.flags & UCSI_CONSTAT_CONNECTED`" ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -1233,7 +1233,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)) diff --git a/queue-6.12/x86-alternatives-rename-apply_relocation-to-text_poke_apply_relocation.patch b/queue-6.12/x86-alternatives-rename-apply_relocation-to-text_poke_apply_relocation.patch new file mode 100644 index 0000000000..c023390a0a --- /dev/null +++ b/queue-6.12/x86-alternatives-rename-apply_relocation-to-text_poke_apply_relocation.patch @@ -0,0 +1,98 @@ +From stable+bounces-260869-greg=kroah.com@vger.kernel.org Sat Jun 6 14:20:14 2026 +From: Sasha Levin +Date: Sat, 6 Jun 2026 08:19:05 -0400 +Subject: x86/alternatives: Rename 'apply_relocation()' to 'text_poke_apply_relocation()' +To: stable@vger.kernel.org +Cc: Ingo Molnar , Juergen Gross , "H . Peter Anvin" , Linus Torvalds , Peter Zijlstra , Sasha Levin +Message-ID: <20260606121906.2851584-1-sashal@kernel.org> + +From: Ingo Molnar + +[ Upstream commit 023f42dd59203be8ad2fc0574af32d3b4ad041ec ] + +Join the text_poke_*() API namespace. + +Signed-off-by: Ingo Molnar +Cc: Juergen Gross +Cc: "H . Peter Anvin" +Cc: Linus Torvalds +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20250411054105.2341982-52-mingo@kernel.org +Stable-dep-of: a17dc12bfed8 ("x86/ftrace: Relocate %rip-relative percpu refs in dynamic trampolines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/text-patching.h | 2 +- + arch/x86/kernel/alternative.c | 6 +++--- + arch/x86/kernel/callthunks.c | 6 +++--- + 3 files changed, 7 insertions(+), 7 deletions(-) + +--- a/arch/x86/include/asm/text-patching.h ++++ b/arch/x86/include/asm/text-patching.h +@@ -15,7 +15,7 @@ + + extern void text_poke_early(void *addr, const void *opcode, size_t len); + +-extern void apply_relocation(u8 *buf, const u8 * const instr, size_t instrlen, u8 *repl, size_t repl_len); ++extern void text_poke_apply_relocation(u8 *buf, const u8 * const instr, size_t instrlen, u8 *repl, size_t repl_len); + + /* + * Clear and restore the kernel write-protection flag on the local CPU. +--- a/arch/x86/kernel/alternative.c ++++ b/arch/x86/kernel/alternative.c +@@ -502,7 +502,7 @@ static void __apply_relocation(u8 *buf, + } + } + +-void apply_relocation(u8 *buf, const u8 * const instr, size_t instrlen, u8 *repl, size_t repl_len) ++void text_poke_apply_relocation(u8 *buf, const u8 * const instr, size_t instrlen, u8 *repl, size_t repl_len) + { + __apply_relocation(buf, instr, instrlen, repl, repl_len); + optimize_nops(instr, buf, instrlen); +@@ -658,7 +658,7 @@ void __init_or_module noinline apply_alt + for (; insn_buff_sz < a->instrlen; insn_buff_sz++) + insn_buff[insn_buff_sz] = 0x90; + +- apply_relocation(insn_buff, instr, a->instrlen, replacement, a->replacementlen); ++ text_poke_apply_relocation(insn_buff, instr, a->instrlen, replacement, a->replacementlen); + + DUMP_BYTES(ALT, instr, a->instrlen, "%px: old_insn: ", instr); + DUMP_BYTES(ALT, replacement, a->replacementlen, "%px: rpl_insn: ", replacement); +@@ -1865,7 +1865,7 @@ __visible noinline void __init __alt_rel + static noinline void __init alt_reloc_selftest(void) + { + /* +- * Tests apply_relocation(). ++ * Tests text_poke_apply_relocation(). + * + * This has a relative immediate (CALL) in a place other than the first + * instruction and additionally on x86_64 we get a RIP-relative LEA: +--- a/arch/x86/kernel/callthunks.c ++++ b/arch/x86/kernel/callthunks.c +@@ -180,7 +180,7 @@ static void *patch_dest(void *dest, bool + u8 *pad = dest - tsize; + + memcpy(insn_buff, skl_call_thunk_template, tsize); +- apply_relocation(insn_buff, pad, tsize, skl_call_thunk_template, tsize); ++ text_poke_apply_relocation(insn_buff, pad, tsize, skl_call_thunk_template, tsize); + + /* Already patched? */ + if (!bcmp(pad, insn_buff, tsize)) +@@ -302,7 +302,7 @@ static bool is_callthunk(void *addr) + pad = (void *)(dest - tmpl_size); + + memcpy(insn_buff, skl_call_thunk_template, tmpl_size); +- apply_relocation(insn_buff, pad, tmpl_size, skl_call_thunk_template, tmpl_size); ++ text_poke_apply_relocation(insn_buff, pad, tmpl_size, skl_call_thunk_template, tmpl_size); + + return !bcmp(pad, insn_buff, tmpl_size); + } +@@ -320,7 +320,7 @@ int x86_call_depth_emit_accounting(u8 ** + return 0; + + memcpy(insn_buff, skl_call_thunk_template, tmpl_size); +- apply_relocation(insn_buff, ip, tmpl_size, skl_call_thunk_template, tmpl_size); ++ text_poke_apply_relocation(insn_buff, ip, tmpl_size, skl_call_thunk_template, tmpl_size); + + memcpy(*pprog, insn_buff, tmpl_size); + *pprog += tmpl_size; diff --git a/queue-6.12/x86-ftrace-relocate-rip-relative-percpu-refs-in-dynamic-trampolines.patch b/queue-6.12/x86-ftrace-relocate-rip-relative-percpu-refs-in-dynamic-trampolines.patch new file mode 100644 index 0000000000..8de983eb9f --- /dev/null +++ b/queue-6.12/x86-ftrace-relocate-rip-relative-percpu-refs-in-dynamic-trampolines.patch @@ -0,0 +1,102 @@ +From stable+bounces-260870-greg=kroah.com@vger.kernel.org Sat Jun 6 14:20:49 2026 +From: Sasha Levin +Date: Sat, 6 Jun 2026 08:19:06 -0400 +Subject: x86/ftrace: Relocate %rip-relative percpu refs in dynamic trampolines +To: stable@vger.kernel.org +Cc: "Alexis Lothoré (eBPF Foundation)" , "Borislav Petkov (AMD)" , "Peter Zijlstra (Intel)" , "Steven Rostedt" , stable@kernel.org, "Sasha Levin" +Message-ID: <20260606121906.2851584-2-sashal@kernel.org> + +From: Alexis Lothoré (eBPF Foundation) + +[ Upstream commit a17dc12bfed8868e6a86f3b45c16065a70641acb ] + +With CONFIG_CALL_DEPTH_TRACKING enabled on an x86 retbleed-affected platform +(eg: Skylake), with retbleed=stuff, registering a dynamic ftrace trampoline +crashes on the first call into the traced function: + + BUG: unable to handle page fault for address: ffff88817ae18880 + #PF: supervisor write access in kernel mode + #PF: error_code(0x0002) - not-present page + PGD 4b53067 P4D 4b53067 PUD 0 + Oops: Oops: 0002 [#1] SMP PTI + CPU: 3 UID: 0 PID: 187 Comm: usleep Not tainted 7.0.10 #243 PREEMPT(full) + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.17.0-2-2 04/01/2014 + Code: 24 78 00 00 00 00 48 89 ea 48 89 54 24 20 48 8b b4 24 b8 00 00 00 48 8b bc 24 b0 00 00 00 48 89 bc 24 80 00 00 00 48 83 ef 05 <65> 48 c1 3d 1f a8 b6 02 05 48 8b 15 f6 00 00 00 4c 89 3c 24 4c 89 + Call Trace: + + ? find_held_lock + ? exc_page_fault + ? lock_release + ? __x64_sys_clock_nanosleep + ? lockdep_hardirqs_on_prepare + ? trace_hardirqs_on + __x64_sys_clock_nanosleep + do_syscall_64 + ? exc_page_fault + ? call_depth_return_thunk + entry_SYSCALL_64_after_hwframe + ... + Kernel panic - not syncing: Fatal exception + +This small reproducer allows to easily trigger the crash: + + # echo 'p __x64_sys_clock_nanosleep' > /sys/kernel/tracing/kprobe_events + # echo 1 > /sys/kernel/tracing/events/kprobes/p___x64_sys_clock_nanosleep_0/enable + # usleep 1 + +Monitoring the crash under GDB points to the exact instruction in charge of +incrementing the call depth: + + sarq $5, %gs:__x86_call_depth(%rip) + +This instruction matches the one inserted by the ftrace_regs_caller from +ftrace_64.S. This emitted code was likely working fine until the introduction +of + + 59bec00ace28 ("x86/percpu: Introduce %rip-relative addressing to PER_CPU_VAR()"): + +it has made the call depth accounting addressing relative to $rip, instead of +being based on an absolute address. + +As this code exact location depends on where the trampoline lives in memory, +the corresponding displacement needs to be adjusted at runtime to actually +correctly find the per-cpu __x86_call_depth value, otherwise the targeted +address is wrong, leading to the page fault seen above. + +Fix the %rip-relative displacement of the copied CALL_DEPTH_ACCOUNT +instruction (from ftrace_regs_caller) by calling text_poke_apply_relocation(), +as it is done for example by the x86 BPF JIT compiler through +x86_call_depth_emit_accounting(). This corrects both CALL_DEPTH_ACCOUNT slots, +in ftrace_caller and ftrace_regs_caller. + + [ bp: Massage. ] + +Fixes: 59bec00ace28 ("x86/percpu: Introduce %rip-relative addressing to PER_CPU_VAR()") +Signed-off-by: Alexis Lothoré (eBPF Foundation) +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Peter Zijlstra (Intel) +Acked-by: Steven Rostedt +Cc: +Link: https://patch.msgid.link/20260527-fix_call_depth_in_trampoline-v1-1-1c1abc8ae310@bootlin.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/ftrace.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/x86/kernel/ftrace.c ++++ b/arch/x86/kernel/ftrace.c +@@ -371,6 +371,13 @@ create_trampoline(struct ftrace_ops *ops + } + + /* ++ * Generated trampoline may contain rIP-relative addressing which ++ * displacement needs to be fixed. ++ */ ++ text_poke_apply_relocation(trampoline, trampoline, size, ++ (void *)start_offset, size); ++ ++ /* + * The address of the ftrace_ops that is used for this trampoline + * is stored at the end of the trampoline. This will be used to + * load the third parameter for the callback. Basically, that