From: Greg Kroah-Hartman Date: Wed, 8 Apr 2026 13:30:51 +0000 (+0200) Subject: 6.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=041486faf9ae7063f0de332244e6c2011abcaade;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: bluetooth-eir-fix-possible-crashes-on-eir_create_adv_data.patch erofs-fix-psi-memstall-accounting.patch erofs-fix-the-slab-out-of-bounds-in-drop_buffers.patch erofs-handle-overlapped-pclusters-out-of-crafted-images-properly.patch gfs2-fix-unlikely-race-in-gdlm_put_lock.patch mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch net-phy-allow-mdio-bus-pm-ops-to-start-stop-state-machine-for-phylink-controlled-phy.patch net-phy-fix-phy_uses_state_machine.patch net-phy-move-phy_link_change-prior-to-mdio_bus_phy_may_suspend.patch selftests-mptcp-join-check-removing-signal-subflow-endp.patch selftests-mptcp-join-implicit-stop-transfer-after-last-check.patch xfs-avoid-dereferencing-log-items-after-push-callbacks.patch xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch --- diff --git a/queue-6.1/bluetooth-eir-fix-possible-crashes-on-eir_create_adv_data.patch b/queue-6.1/bluetooth-eir-fix-possible-crashes-on-eir_create_adv_data.patch new file mode 100644 index 0000000000..7f5cd06d9c --- /dev/null +++ b/queue-6.1/bluetooth-eir-fix-possible-crashes-on-eir_create_adv_data.patch @@ -0,0 +1,90 @@ +From stable+bounces-230046-greg=kroah.com@vger.kernel.org Tue Mar 24 03:39:42 2026 +From: Robert Garcia +Date: Tue, 24 Mar 2026 10:34:02 +0800 +Subject: Bluetooth: eir: Fix possible crashes on eir_create_adv_data +To: stable@vger.kernel.org, Luiz Augusto von Dentz +Cc: Marcel Holtmann , Robert Garcia , Johan Hedberg , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , linux-bluetooth@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org +Message-ID: <20260324023402.2607704-1-rob_garcia@163.com> + +From: Luiz Augusto von Dentz + +[ Upstream commit 47c03902269aff377f959dc3fd94a9733aa31d6e ] + +eir_create_adv_data may attempt to add EIR_FLAGS and EIR_TX_POWER +without checking if that would fit. + +Link: https://github.com/bluez/bluez/issues/1117#issuecomment-2958244066 +Fixes: 01ce70b0a274 ("Bluetooth: eir: Move EIR/Adv Data functions to its own file") +Signed-off-by: Luiz Augusto von Dentz +[ Use pdu.data instead of pdu->data in hci_set_ext_adv_data_sync() + to keep context consistency. ] +Signed-off-by: Robert Garcia +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/eir.c | 7 ++++--- + net/bluetooth/eir.h | 2 +- + net/bluetooth/hci_sync.c | 5 +++-- + 3 files changed, 8 insertions(+), 6 deletions(-) + +--- a/net/bluetooth/eir.c ++++ b/net/bluetooth/eir.c +@@ -242,7 +242,7 @@ u8 eir_create_per_adv_data(struct hci_de + return ad_len; + } + +-u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) ++u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size) + { + struct adv_info *adv = NULL; + u8 ad_len = 0, flags = 0; +@@ -286,7 +286,7 @@ u8 eir_create_adv_data(struct hci_dev *h + /* If flags would still be empty, then there is no need to + * include the "Flags" AD field". + */ +- if (flags) { ++ if (flags && (ad_len + eir_precalc_len(1) <= size)) { + ptr[0] = 0x02; + ptr[1] = EIR_FLAGS; + ptr[2] = flags; +@@ -316,7 +316,8 @@ skip_flags: + } + + /* Provide Tx Power only if we can provide a valid value for it */ +- if (adv_tx_power != HCI_TX_POWER_INVALID) { ++ if (adv_tx_power != HCI_TX_POWER_INVALID && ++ (ad_len + eir_precalc_len(1) <= size)) { + ptr[0] = 0x02; + ptr[1] = EIR_TX_POWER; + ptr[2] = (u8)adv_tx_power; +--- a/net/bluetooth/eir.h ++++ b/net/bluetooth/eir.h +@@ -9,7 +9,7 @@ + + void eir_create(struct hci_dev *hdev, u8 *data); + +-u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); ++u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size); + u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr); + u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); + +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1248,7 +1248,8 @@ static int hci_set_ext_adv_data_sync(str + return 0; + } + +- len = eir_create_adv_data(hdev, instance, pdu.data); ++ len = eir_create_adv_data(hdev, instance, pdu.data, ++ HCI_MAX_EXT_AD_LENGTH); + + pdu.cp.length = len; + pdu.cp.handle = instance; +@@ -1279,7 +1280,7 @@ static int hci_set_adv_data_sync(struct + + memset(&cp, 0, sizeof(cp)); + +- len = eir_create_adv_data(hdev, instance, cp.data); ++ len = eir_create_adv_data(hdev, instance, cp.data, sizeof(cp.data)); + + /* There's nothing to do if the data hasn't changed */ + if (hdev->adv_data_len == len && diff --git a/queue-6.1/erofs-fix-psi-memstall-accounting.patch b/queue-6.1/erofs-fix-psi-memstall-accounting.patch new file mode 100644 index 0000000000..af17801bcb --- /dev/null +++ b/queue-6.1/erofs-fix-psi-memstall-accounting.patch @@ -0,0 +1,52 @@ +From stable+bounces-230584-greg=kroah.com@vger.kernel.org Fri Mar 27 05:34:18 2026 +From: Gao Xiang +Date: Fri, 27 Mar 2026 12:33:59 +0800 +Subject: erofs: fix PSI memstall accounting +To: stable@vger.kernel.org, Greg Kroah-Hartman +Cc: linux-erofs@lists.ozlabs.org, Gao Xiang , Max Kellermann , Chao Yu , Alexey Panov +Message-ID: <20260327043359.1121251-1-hsiangkao@linux.alibaba.com> + +From: Gao Xiang + +commit 1a2180f6859c73c674809f9f82e36c94084682ba upstream. + +Max Kellermann recently reported psi_group_cpu.tasks[NR_MEMSTALL] is +incorrect in the 6.11.9 kernel. + +The root cause appears to be that, since the problematic commit, bio +can be NULL, causing psi_memstall_leave() to be skipped in +z_erofs_submit_queue(). + +Reported-by: Max Kellermann +Closes: https://lore.kernel.org/r/CAKPOu+8tvSowiJADW2RuKyofL_CSkm_SuyZA7ME5vMLWmL6pqw@mail.gmail.com +Fixes: 9e2f9d34dd12 ("erofs: handle overlapped pclusters out of crafted images properly") +Reviewed-by: Chao Yu +Link: https://lore.kernel.org/r/20241127085236.3538334-1-hsiangkao@linux.alibaba.com +Signed-off-by: Alexey Panov +Link: https://lore.kernel.org/r/20250304110558.8315-3-apanov@astralinux.ru +Link: https://lore.kernel.org/r/20250304110558.8315-1-apanov@astralinux.ru +[ Gao Xiang: re-address the previous Alexey's backport. ] +CVE: CVE-2024-47736 +Signed-off-by: Gao Xiang +Signed-off-by: Greg Kroah-Hartman +--- + fs/erofs/zdata.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -1574,11 +1574,10 @@ drain_io: + move_to_bypass_jobqueue(pcl, qtail, owned_head); + } while (owned_head != Z_EROFS_PCLUSTER_TAIL); + +- if (bio) { ++ if (bio) + submit_bio(bio); +- if (memstall) +- psi_memstall_leave(&pflags); +- } ++ if (memstall) ++ psi_memstall_leave(&pflags); + + /* + * although background is preferred, no one is pending for submission. diff --git a/queue-6.1/erofs-fix-the-slab-out-of-bounds-in-drop_buffers.patch b/queue-6.1/erofs-fix-the-slab-out-of-bounds-in-drop_buffers.patch new file mode 100644 index 0000000000..3531a9a348 --- /dev/null +++ b/queue-6.1/erofs-fix-the-slab-out-of-bounds-in-drop_buffers.patch @@ -0,0 +1,55 @@ +From arefev@swemel.ru Mon Mar 23 14:59:38 2026 +From: Denis Arefev +Date: Mon, 23 Mar 2026 16:59:35 +0300 +Subject: erofs: Fix the slab-out-of-bounds in drop_buffers() +To: stable@vger.kernel.org, Greg Kroah-Hartman +Cc: Gao Xiang , Chao Yu , Jeffle Xu , linux-erofs@lists.ozlabs.org, linux-kernel@vger.kernel.org, lvc-project@linuxtesting.org, syzbot+5b886a2e03529dbcef81@syzkaller.appspotmail.com +Message-ID: <20260323135936.15070-1-arefev@swemel.ru> + +From: Denis Arefev + +commit ce529cc25b184e93397b94a8a322128fc0095cbb upstream. + +This was accidentally fixed in commit ce529cc25b18, but it's not possible +to accept all the changes, due to the lack of large folios support for +Linux 6.1 kernels, so this is only the actual bug fix that's needed. + +[Background] + +Syzbot reported that a KASAN slab-out-of-bounds bug was discovered in +the drop_buffers() function [1]. + +The root cause is that erofs_raw_access_aops does not define .release_folio +and .invalidate_folio. When using iomap-based operations, folio->private +may contain iomap-specific data rather than buffer_heads. Without special +handlers, the kernel may fall back to generic functions (such as +drop_buffers), which incorrectly treat folio->private as a list of +buffer_head structures, leading to incorrect memory interpretation and +out-of-bounds access. + +Fix this by explicitly setting .release_folio and .invalidate_folio to the +values of iomap_release_folio and iomap_invalidate_folio, respectively. + +[1] https://syzkaller.appspot.com/x/report.txt?x=12e5a142580000 + +Fixes: 7479c505b4ab ("fs: Convert iomap_readpage to iomap_read_folio") +Reported-by: syzbot+5b886a2e03529dbcef81@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?id=c6aeabd0c4ad2466f63a274faf2a123103f8fbf7 +Signed-off-by: Denis Arefev +Reviewed-by: Gao Xiang +Signed-off-by: Greg Kroah-Hartman +--- + fs/erofs/data.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/erofs/data.c ++++ b/fs/erofs/data.c +@@ -406,6 +406,8 @@ const struct address_space_operations er + .readahead = erofs_readahead, + .bmap = erofs_bmap, + .direct_IO = noop_direct_IO, ++ .release_folio = iomap_release_folio, ++ .invalidate_folio = iomap_invalidate_folio, + }; + + #ifdef CONFIG_FS_DAX diff --git a/queue-6.1/erofs-handle-overlapped-pclusters-out-of-crafted-images-properly.patch b/queue-6.1/erofs-handle-overlapped-pclusters-out-of-crafted-images-properly.patch new file mode 100644 index 0000000000..e83984cb83 --- /dev/null +++ b/queue-6.1/erofs-handle-overlapped-pclusters-out-of-crafted-images-properly.patch @@ -0,0 +1,171 @@ +From stable+bounces-230583-greg=kroah.com@vger.kernel.org Fri Mar 27 05:33:33 2026 +From: Gao Xiang +Date: Fri, 27 Mar 2026 12:33:12 +0800 +Subject: erofs: handle overlapped pclusters out of crafted images properly +To: stable@vger.kernel.org, Greg Kroah-Hartman +Cc: linux-erofs@lists.ozlabs.org, Gao Xiang , syzbot+4fc98ed414ae63d1ada2@syzkaller.appspotmail.com, syzbot+de04e06b28cfecf2281c@syzkaller.appspotmail.com, syzbot+c8c8238b394be4a1087d@syzkaller.appspotmail.com, Alexey Panov +Message-ID: <20260327043312.1118901-1-hsiangkao@linux.alibaba.com> + +From: Gao Xiang + +commit 9e2f9d34dd12e6e5b244ec488bcebd0c2d566c50 upstream. + +syzbot reported a task hang issue due to a deadlock case where it is +waiting for the folio lock of a cached folio that will be used for +cache I/Os. + +After looking into the crafted fuzzed image, I found it's formed with +several overlapped big pclusters as below: + + Ext: logical offset | length : physical offset | length + 0: 0.. 16384 | 16384 : 151552.. 167936 | 16384 + 1: 16384.. 32768 | 16384 : 155648.. 172032 | 16384 + 2: 32768.. 49152 | 16384 : 537223168.. 537239552 | 16384 +... + +Here, extent 0/1 are physically overlapped although it's entirely +_impossible_ for normal filesystem images generated by mkfs. + +First, managed folios containing compressed data will be marked as +up-to-date and then unlocked immediately (unlike in-place folios) when +compressed I/Os are complete. If physical blocks are not submitted in +the incremental order, there should be separate BIOs to avoid dependency +issues. However, the current code mis-arranges z_erofs_fill_bio_vec() +and BIO submission which causes unexpected BIO waits. + +Second, managed folios will be connected to their own pclusters for +efficient inter-queries. However, this is somewhat hard to implement +easily if overlapped big pclusters exist. Again, these only appear in +fuzzed images so let's simply fall back to temporary short-lived pages +for correctness. + +Additionally, it justifies that referenced managed folios cannot be +truncated for now and reverts part of commit 2080ca1ed3e4 ("erofs: tidy +up `struct z_erofs_bvec`") for simplicity although it shouldn't be any +difference. + +[Alexey: This patch follows linux 6.6.y conflict resolution changes of +struct folio -> struct page] + +Reported-by: syzbot+4fc98ed414ae63d1ada2@syzkaller.appspotmail.com +Reported-by: syzbot+de04e06b28cfecf2281c@syzkaller.appspotmail.com +Reported-by: syzbot+c8c8238b394be4a1087d@syzkaller.appspotmail.com +Tested-by: syzbot+4fc98ed414ae63d1ada2@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/r/0000000000002fda01061e334873@google.com +Fixes: 8e6c8fa9f2e9 ("erofs: enable big pcluster feature") +Link: https://lore.kernel.org/r/20240910070847.3356592-1-hsiangkao@linux.alibaba.com +Signed-off-by: Alexey Panov +Link: https://lore.kernel.org/r/20250304110558.8315-2-apanov@astralinux.ru +Link: https://lore.kernel.org/r/20250304110558.8315-1-apanov@astralinux.ru +[ Gao Xiang: re-address the previous Alexey's backport. ] +CVE: CVE-2024-47736 +Signed-off-by: Gao Xiang +Signed-off-by: Greg Kroah-Hartman +--- + fs/erofs/zdata.c | 60 +++++++++++++++++++++++++++++-------------------------- + 1 file changed, 32 insertions(+), 28 deletions(-) + +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -1331,14 +1331,14 @@ repeat: + goto out; + + lock_page(page); +- +- /* only true if page reclaim goes wrong, should never happen */ +- DBG_BUGON(justfound && PagePrivate(page)); +- +- /* the page is still in manage cache */ +- if (page->mapping == mc) { ++ if (likely(page->mapping == mc)) { + WRITE_ONCE(pcl->compressed_bvecs[nr].page, page); ++ oldpage = page; + ++ /* ++ * The cached folio is still in managed cache but without ++ * a valid `->private` pcluster hint. Let's reconnect them. ++ */ + if (!PagePrivate(page)) { + /* + * impossible to be !PagePrivate(page) for +@@ -1352,22 +1352,24 @@ repeat: + SetPagePrivate(page); + } + +- /* no need to submit io if it is already up-to-date */ +- if (PageUptodate(page)) { +- unlock_page(page); +- page = NULL; ++ if (likely(page->private == (unsigned long)pcl)) { ++ /* don't submit cache I/Os again if already uptodate */ ++ if (PageUptodate(page)) { ++ unlock_page(page); ++ page = NULL; ++ ++ } ++ goto out; + } +- goto out; ++ /* ++ * Already linked with another pcluster, which only appears in ++ * crafted images by fuzzers for now. But handle this anyway. ++ */ ++ tocache = false; /* use temporary short-lived pages */ ++ } else { ++ DBG_BUGON(1); /* referenced managed folios can't be truncated */ ++ tocache = true; + } +- +- /* +- * the managed page has been truncated, it's unsafe to +- * reuse this one, let's allocate a new cache-managed page. +- */ +- DBG_BUGON(page->mapping); +- DBG_BUGON(!justfound); +- +- tocache = true; + unlock_page(page); + put_page(page); + out_allocpage: +@@ -1520,16 +1522,11 @@ static void z_erofs_submit_queue(struct + end = cur + pcl->pclusterpages; + + do { +- struct page *page; +- +- page = pickup_page_for_submission(pcl, i++, +- &f->pagepool, mc); +- if (!page) +- continue; ++ struct page *page = NULL; + + if (bio && (cur != last_index + 1 || + last_bdev != mdev.m_bdev)) { +-submit_bio_retry: ++drain_io: + submit_bio(bio); + if (memstall) { + psi_memstall_leave(&pflags); +@@ -1538,6 +1535,13 @@ submit_bio_retry: + bio = NULL; + } + ++ if (!page) { ++ page = pickup_page_for_submission(pcl, i++, ++ &f->pagepool, mc); ++ if (!page) ++ continue; ++ } ++ + if (unlikely(PageWorkingset(page)) && !memstall) { + psi_memstall_enter(&pflags); + memstall = 1; +@@ -1558,7 +1562,7 @@ submit_bio_retry: + } + + if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) +- goto submit_bio_retry; ++ goto drain_io; + + last_index = cur; + bypass = false; diff --git a/queue-6.1/gfs2-fix-unlikely-race-in-gdlm_put_lock.patch b/queue-6.1/gfs2-fix-unlikely-race-in-gdlm_put_lock.patch new file mode 100644 index 0000000000..55e71d49c7 --- /dev/null +++ b/queue-6.1/gfs2-fix-unlikely-race-in-gdlm_put_lock.patch @@ -0,0 +1,53 @@ +From stable+bounces-230425-greg=kroah.com@vger.kernel.org Thu Mar 26 07:40:52 2026 +From: Robert Garcia +Date: Thu, 26 Mar 2026 14:34:27 +0800 +Subject: gfs2: Fix unlikely race in gdlm_put_lock +To: stable@vger.kernel.org, Andreas Gruenbacher +Cc: Andrew Price , Robert Garcia , Bob Peterson , cluster-devel@redhat.com, linux-kernel@vger.kernel.org +Message-ID: <20260326063427.1771116-1-rob_garcia@163.com> + +From: Andreas Gruenbacher + +[ Upstream commit 28c4d9bc0708956c1a736a9e49fee71b65deee81 ] + +In gdlm_put_lock(), there is a small window of time in which the +DFL_UNMOUNT flag has been set but the lockspace hasn't been released, +yet. In that window, dlm may still call gdlm_ast() and gdlm_bast(). +To prevent it from dereferencing freed glock objects, only free the +glock if the lockspace has actually been released. + +Signed-off-by: Andreas Gruenbacher +Reviewed-by: Andrew Price +[ Minor context change fixed. ] +Signed-off-by: Robert Garcia +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/lock_dlm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/fs/gfs2/lock_dlm.c ++++ b/fs/gfs2/lock_dlm.c +@@ -301,11 +301,6 @@ static void gdlm_put_lock(struct gfs2_gl + gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); + gfs2_update_request_times(gl); + +- /* don't want to call dlm if we've unmounted the lock protocol */ +- if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) { +- gfs2_glock_free(gl); +- return; +- } + /* don't want to skip dlm_unlock writing the lvb when lock has one */ + + if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && +@@ -322,6 +317,11 @@ again: + goto again; + } + ++ if (error == -ENODEV) { ++ gfs2_glock_free(gl); ++ return; ++ } ++ + if (error) { + fs_err(sdp, "gdlm_unlock %x,%llx err=%d\n", + gl->gl_name.ln_type, diff --git a/queue-6.1/mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch b/queue-6.1/mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch new file mode 100644 index 0000000000..976f981ed7 --- /dev/null +++ b/queue-6.1/mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch @@ -0,0 +1,134 @@ +From stable+bounces-230289-greg=kroah.com@vger.kernel.org Wed Mar 25 10:29:03 2026 +From: liyin.zhang.cn@windriver.com +Date: Wed, 25 Mar 2026 17:23:14 +0800 +Subject: mtd: spi-nor: core: avoid odd length/address reads on 8D-8D-8D mode +To: stable@vger.kernel.org +Message-ID: <20260325092315.956451-2-liyin.zhang.cn@windriver.com> + +From: Pratyush Yadav + +[ Upstream commit f156b23df6a84efb2f6686156be94d4988568954 ] + +On Octal DTR capable flashes like Micron Xcella reads cannot start or +end at an odd address in Octal DTR mode. Extra bytes need to be read at +the start or end to make sure both the start address and length remain +even. + +To avoid allocating too much extra memory, thereby putting unnecessary +memory pressure on the system, the temporary buffer containing the extra +padding bytes is capped at PAGE_SIZE bytes. The rest of the 2-byte +aligned part should be read directly in the main buffer. + +Signed-off-by: Pratyush Yadav +Reviewed-by: Michael Walle +Signed-off-by: Luke Wang +Signed-off-by: Pratyush Yadav +Link: https://lore.kernel.org/r/20250708091646.292-1-ziniu.wang_1@nxp.com +[ Resolve conflict in drivers/mtd/spi-nor/core.c. + In spi_nor_read(), 6.1.y contains a spi_nor_convert_addr() call + before spi_nor_read_data(), introduced by 364995962803 ("mtd: + spi-nor: Add a ->convert_addr() method"), which does not exist in + mainline. This call is specific to Xilinx S3AN flashes, which use a + non-standard address format. In mainline, S3AN flash support was + removed entirely, and the corresponding spi_nor_convert_addr() call + was dropped by 9539d12d9f52 ("mtd: spi-nor: get rid of non-power-of-2 + page size handling"). Keep the existing spi_nor_convert_addr() call + and insert the new spi_nor_octal_dtr_read() branch after it. ] +Signed-off-by: Liyin Zhang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/spi-nor/core.c | 76 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 75 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1677,6 +1677,76 @@ static const struct flash_info *spi_nor_ + return info; + } + ++/* ++ * On Octal DTR capable flashes, reads cannot start or end at an odd ++ * address in Octal DTR mode. Extra bytes need to be read at the start ++ * or end to make sure both the start address and length remain even. ++ */ ++static int spi_nor_octal_dtr_read(struct spi_nor *nor, loff_t from, size_t len, ++ u_char *buf) ++{ ++ u_char *tmp_buf; ++ size_t tmp_len; ++ loff_t start, end; ++ int ret, bytes_read; ++ ++ if (IS_ALIGNED(from, 2) && IS_ALIGNED(len, 2)) ++ return spi_nor_read_data(nor, from, len, buf); ++ else if (IS_ALIGNED(from, 2) && len > PAGE_SIZE) ++ return spi_nor_read_data(nor, from, round_down(len, PAGE_SIZE), ++ buf); ++ ++ tmp_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ if (!tmp_buf) ++ return -ENOMEM; ++ ++ start = round_down(from, 2); ++ end = round_up(from + len, 2); ++ ++ /* ++ * Avoid allocating too much memory. The requested read length might be ++ * quite large. Allocating a buffer just as large (slightly bigger, in ++ * fact) would put unnecessary memory pressure on the system. ++ * ++ * For example if the read is from 3 to 1M, then this will read from 2 ++ * to 4098. The reads from 4098 to 1M will then not need a temporary ++ * buffer so they can proceed as normal. ++ */ ++ tmp_len = min_t(size_t, end - start, PAGE_SIZE); ++ ++ ret = spi_nor_read_data(nor, start, tmp_len, tmp_buf); ++ if (ret == 0) { ++ ret = -EIO; ++ goto out; ++ } ++ if (ret < 0) ++ goto out; ++ ++ /* ++ * More bytes are read than actually requested, but that number can't be ++ * reported to the calling function or it will confuse its calculations. ++ * Calculate how many of the _requested_ bytes were read. ++ */ ++ bytes_read = ret; ++ ++ if (from != start) ++ ret -= from - start; ++ ++ /* ++ * Only account for extra bytes at the end if they were actually read. ++ * For example, if the total length was truncated because of temporary ++ * buffer size limit then the adjustment for the extra bytes at the end ++ * is not needed. ++ */ ++ if (start + bytes_read == end) ++ ret -= end - (from + len); ++ ++ memcpy(buf, tmp_buf + (from - start), ret); ++out: ++ kfree(tmp_buf); ++ return ret; ++} ++ + static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) + { +@@ -1694,7 +1764,11 @@ static int spi_nor_read(struct mtd_info + + addr = spi_nor_convert_addr(nor, addr); + +- ret = spi_nor_read_data(nor, addr, len, buf); ++ if (nor->read_proto == SNOR_PROTO_8_8_8_DTR) ++ ret = spi_nor_octal_dtr_read(nor, addr, len, buf); ++ else ++ ret = spi_nor_read_data(nor, addr, len, buf); ++ + if (ret == 0) { + /* We shouldn't see 0-length reads */ + ret = -EIO; diff --git a/queue-6.1/mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch b/queue-6.1/mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch new file mode 100644 index 0000000000..1bc843564c --- /dev/null +++ b/queue-6.1/mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch @@ -0,0 +1,118 @@ +From stable+bounces-230291-greg=kroah.com@vger.kernel.org Wed Mar 25 10:31:34 2026 +From: liyin.zhang.cn@windriver.com +Date: Wed, 25 Mar 2026 17:23:15 +0800 +Subject: mtd: spi-nor: core: avoid odd length/address writes in 8D-8D-8D mode +To: stable@vger.kernel.org +Message-ID: <20260325092315.956451-3-liyin.zhang.cn@windriver.com> + +From: Pratyush Yadav + +[ Upstream commit 17926cd770ec837ed27d9856cf07f2da8dda4131 ] + +On Octal DTR capable flashes like Micron Xcella the writes cannot start +or end at an odd address in Octal DTR mode. Extra 0xff bytes need to be +appended or prepended to make sure the start address and end address are +even. 0xff is used because on NOR flashes a program operation can only +flip bits from 1 to 0, not the other way round. 0 to 1 flip needs to +happen via erases. + +Signed-off-by: Pratyush Yadav +Reviewed-by: Michael Walle +Signed-off-by: Luke Wang +Signed-off-by: Pratyush Yadav +Link: https://lore.kernel.org/r/20250708091646.292-2-ziniu.wang_1@nxp.com +[ Resolve conflict in drivers/mtd/spi-nor/core.c. + In spi_nor_write(), the spi_nor_lock_device() and + spi_nor_unlock_device() mechanism was not yet introduced in 6.1.y. + Drop the spi_nor_unlock_device() call from the patch. ] +Signed-off-by: Liyin Zhang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/spi-nor/core.c | 69 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 68 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -1791,6 +1791,68 @@ read_err: + } + + /* ++ * On Octal DTR capable flashes, writes cannot start or end at an odd address ++ * in Octal DTR mode. Extra 0xff bytes need to be appended or prepended to ++ * make sure the start address and end address are even. 0xff is used because ++ * on NOR flashes a program operation can only flip bits from 1 to 0, not the ++ * other way round. 0 to 1 flip needs to happen via erases. ++ */ ++static int spi_nor_octal_dtr_write(struct spi_nor *nor, loff_t to, size_t len, ++ const u8 *buf) ++{ ++ u8 *tmp_buf; ++ size_t bytes_written; ++ loff_t start, end; ++ int ret; ++ ++ if (IS_ALIGNED(to, 2) && IS_ALIGNED(len, 2)) ++ return spi_nor_write_data(nor, to, len, buf); ++ ++ tmp_buf = kmalloc(nor->params->page_size, GFP_KERNEL); ++ if (!tmp_buf) ++ return -ENOMEM; ++ ++ memset(tmp_buf, 0xff, nor->params->page_size); ++ ++ start = round_down(to, 2); ++ end = round_up(to + len, 2); ++ ++ memcpy(tmp_buf + (to - start), buf, len); ++ ++ ret = spi_nor_write_data(nor, start, end - start, tmp_buf); ++ if (ret == 0) { ++ ret = -EIO; ++ goto out; ++ } ++ if (ret < 0) ++ goto out; ++ ++ /* ++ * More bytes are written than actually requested, but that number can't ++ * be reported to the calling function or it will confuse its ++ * calculations. Calculate how many of the _requested_ bytes were ++ * written. ++ */ ++ bytes_written = ret; ++ ++ if (to != start) ++ ret -= to - start; ++ ++ /* ++ * Only account for extra bytes at the end if they were actually ++ * written. For example, if for some reason the controller could only ++ * complete a partial write then the adjustment for the extra bytes at ++ * the end is not needed. ++ */ ++ if (start + bytes_written == end) ++ ret -= end - (to + len); ++ ++out: ++ kfree(tmp_buf); ++ return ret; ++} ++ ++/* + * Write an address range to the nor chip. Data must be written in + * FLASH_PAGESIZE chunks. The address range may be any size provided + * it is within the physical boundaries. +@@ -1834,7 +1896,12 @@ static int spi_nor_write(struct mtd_info + if (ret) + goto write_err; + +- ret = spi_nor_write_data(nor, addr, page_remain, buf + i); ++ if (nor->write_proto == SNOR_PROTO_8_8_8_DTR) ++ ret = spi_nor_octal_dtr_write(nor, addr, page_remain, ++ buf + i); ++ else ++ ret = spi_nor_write_data(nor, addr, page_remain, ++ buf + i); + if (ret < 0) + goto write_err; + written = ret; diff --git a/queue-6.1/net-phy-allow-mdio-bus-pm-ops-to-start-stop-state-machine-for-phylink-controlled-phy.patch b/queue-6.1/net-phy-allow-mdio-bus-pm-ops-to-start-stop-state-machine-for-phylink-controlled-phy.patch new file mode 100644 index 0000000000..66905c3e5f --- /dev/null +++ b/queue-6.1/net-phy-allow-mdio-bus-pm-ops-to-start-stop-state-machine-for-phylink-controlled-phy.patch @@ -0,0 +1,161 @@ +From 681739313@139.com Fri Mar 27 02:52:59 2026 +From: Rajani Kantha <681739313@139.com> +Date: Fri, 27 Mar 2026 09:52:37 +0800 +Subject: net: phy: allow MDIO bus PM ops to start/stop state machine for phylink-controlled PHY +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, vladimir.oltean@nxp.com +Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, matthias.bgg@gmail.com, f.fainelli@gmail.com, netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, wei.fang@nxp.com +Message-ID: <20260327015237.1713008-1-681739313@139.com> + +From: Vladimir Oltean + +[ Upstream commit fc75ea20ffb452652f0d4033f38fe88d7cfdae35 ] + +DSA has 2 kinds of drivers: + +1. Those who call dsa_switch_suspend() and dsa_switch_resume() from + their device PM ops: qca8k-8xxx, bcm_sf2, microchip ksz +2. Those who don't: all others. The above methods should be optional. + +For type 1, dsa_switch_suspend() calls dsa_user_suspend() -> phylink_stop(), +and dsa_switch_resume() calls dsa_user_resume() -> phylink_start(). +These seem good candidates for setting mac_managed_pm = true because +that is essentially its definition [1], but that does not seem to be the +biggest problem for now, and is not what this change focuses on. + +Talking strictly about the 2nd category of DSA drivers here (which +do not have MAC managed PM, meaning that for their attached PHYs, +mdio_bus_phy_suspend() and mdio_bus_phy_resume() should run in full), +I have noticed that the following warning from mdio_bus_phy_resume() is +triggered: + + WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY && + phydev->state != PHY_UP); + +because the PHY state machine is running. + +It's running as a result of a previous dsa_user_open() -> ... -> +phylink_start() -> phy_start() having been initiated by the user. + +The previous mdio_bus_phy_suspend() was supposed to have called +phy_stop_machine(), but it didn't. So this is why the PHY is in state +PHY_NOLINK by the time mdio_bus_phy_resume() runs. + +mdio_bus_phy_suspend() did not call phy_stop_machine() because for +phylink, the phydev->adjust_link function pointer is NULL. This seems a +technicality introduced by commit fddd91016d16 ("phylib: fix PAL state +machine restart on resume"). That commit was written before phylink +existed, and was intended to avoid crashing with consumer drivers which +don't use the PHY state machine - phylink always does, when using a PHY. +But phylink itself has historically not been developed with +suspend/resume in mind, and apparently not tested too much in that +scenario, allowing this bug to exist unnoticed for so long. Plus, prior +to the WARN_ON(), it would have likely been invisible. + +This issue is not in fact restricted to type 2 DSA drivers (according to +the above ad-hoc classification), but can be extrapolated to any MAC +driver with phylink and MDIO-bus-managed PHY PM ops. DSA is just where +the issue was reported. Assuming mac_managed_pm is set correctly, a +quick search indicates the following other drivers might be affected: + +$ grep -Zlr PHYLINK_NETDEV drivers/ | xargs -0 grep -L mac_managed_pm +drivers/net/ethernet/atheros/ag71xx.c +drivers/net/ethernet/microchip/sparx5/sparx5_main.c +drivers/net/ethernet/microchip/lan966x/lan966x_main.c +drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +drivers/net/ethernet/freescale/ucc_geth.c +drivers/net/ethernet/freescale/enetc/enetc_pf_common.c +drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +drivers/net/ethernet/marvell/mvneta.c +drivers/net/ethernet/marvell/prestera/prestera_main.c +drivers/net/ethernet/mediatek/mtk_eth_soc.c +drivers/net/ethernet/altera/altera_tse_main.c +drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +drivers/net/ethernet/meta/fbnic/fbnic_phylink.c +drivers/net/ethernet/tehuti/tn40_phy.c +drivers/net/ethernet/mscc/ocelot_net.c + +Make the existing conditions dependent on the PHY device having a +phydev->phy_link_change() implementation equal to the default +phy_link_change() provided by phylib. Otherwise, we implicitly know that +the phydev has the phylink-provided phylink_phy_change() callback, and +when phylink is used, the PHY state machine always needs to be stopped/ +started on the suspend/resume path. The code is structured as such that +if phydev->phy_link_change() is absent, it is a matter of time until the +kernel will crash - no need to further complicate the test. + +Thus, for the situation where the PM is not managed by the MAC, we will +make the MDIO bus PM ops treat identically the phylink-controlled PHYs +with the phylib-controlled PHYs where an adjust_link() callback is +supplied. In both cases, the MDIO bus PM ops should stop and restart the +PHY state machine. + +[1] https://lore.kernel.org/netdev/Z-1tiW9zjcoFkhwc@shell.armlinux.org.uk/ + +Fixes: 744d23c71af3 ("net: phy: Warn about incorrect mdio_bus_phy_resume() state") +Reported-by: Wei Fang +Tested-by: Wei Fang +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20250407094042.2155633-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/phy_device.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -247,6 +247,33 @@ static void phy_link_change(struct phy_d + phydev->mii_ts->link_state(phydev->mii_ts, phydev); + } + ++/** ++ * phy_uses_state_machine - test whether consumer driver uses PAL state machine ++ * @phydev: the target PHY device structure ++ * ++ * Ultimately, this aims to indirectly determine whether the PHY is attached ++ * to a consumer which uses the state machine by calling phy_start() and ++ * phy_stop(). ++ * ++ * When the PHY driver consumer uses phylib, it must have previously called ++ * phy_connect_direct() or one of its derivatives, so that phy_prepare_link() ++ * has set up a hook for monitoring state changes. ++ * ++ * When the PHY driver is used by the MAC driver consumer through phylink (the ++ * only other provider of a phy_link_change() method), using the PHY state ++ * machine is not optional. ++ * ++ * Return: true if consumer calls phy_start() and phy_stop(), false otherwise. ++ */ ++static bool phy_uses_state_machine(struct phy_device *phydev) ++{ ++ if (phydev->phy_link_change == phy_link_change) ++ return phydev->attached_dev && phydev->adjust_link; ++ ++ /* phydev->phy_link_change is implicitly phylink_phy_change() */ ++ return true; ++} ++ + static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) + { + struct device_driver *drv = phydev->mdio.dev.driver; +@@ -307,7 +334,7 @@ static __maybe_unused int mdio_bus_phy_s + * may call phy routines that try to grab the same lock, and that may + * lead to a deadlock. + */ +- if (phydev->attached_dev && phydev->adjust_link) ++ if (phy_uses_state_machine(phydev)) + phy_stop_machine(phydev); + + if (!mdio_bus_phy_may_suspend(phydev)) +@@ -361,7 +388,7 @@ no_resume: + } + } + +- if (phydev->attached_dev && phydev->adjust_link) ++ if (phy_uses_state_machine(phydev)) + phy_start_machine(phydev); + + return 0; diff --git a/queue-6.1/net-phy-fix-phy_uses_state_machine.patch b/queue-6.1/net-phy-fix-phy_uses_state_machine.patch new file mode 100644 index 0000000000..af4f6c1bd0 --- /dev/null +++ b/queue-6.1/net-phy-fix-phy_uses_state_machine.patch @@ -0,0 +1,80 @@ +From 681739313@139.com Fri Mar 27 02:53:35 2026 +From: Rajani Kantha <681739313@139.com> +Date: Fri, 27 Mar 2026 09:53:16 +0800 +Subject: net: phy: fix phy_uses_state_machine() +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, rmk+kernel@armlinux.org.uk +Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, vladimir.oltean@nxp.com, netdev@vger.kernel.org, xu.yang_2@nxp.com +Message-ID: <20260327015316.1713133-1-681739313@139.com> + +From: "Russell King (Oracle)" + +[ Upstream commit e0d1c55501d377163eb57feed863777ed1c973ad ] + +The blamed commit changed the conditions which phylib uses to stop +and start the state machine in the suspend and resume paths, and +while improving it, has caused two issues. + +The original code used this test: + + phydev->attached_dev && phydev->adjust_link + +and if true, the paths would handle the PHY state machine. This test +evaluates true for normal drivers that are using phylib directly +while the PHY is attached to the network device, but false in all +other cases, which include the following cases: + +- when the PHY has never been attached to a network device. +- when the PHY has been detached from a network device (as phy_detach() + sets phydev->attached_dev to NULL, phy_disconnect() calls + phy_detach() and additionally sets phydev->adjust_link NULL.) +- when phylink is using the driver (as phydev->adjust_link is NULL.) + +Only the third case was incorrect, and the blamed commit attempted to +fix this by changing this test to (simplified for brevity, see +phy_uses_state_machine()): + + phydev->phy_link_change == phy_link_change ? + phydev->attached_dev && phydev->adjust_link : true + +However, this also incorrectly evaluates true in the first two cases. + +Fix the first case by ensuring that phy_uses_state_machine() returns +false when phydev->phy_link_change is NULL. + +Fix the second case by ensuring that phydev->phy_link_change is set to +NULL when phy_detach() is called. + +Reported-by: Xu Yang +Link: https://lore.kernel.org/r/20250806082931.3289134-1-xu.yang_2@nxp.com +Fixes: fc75ea20ffb4 ("net: phy: allow MDIO bus PM ops to start/stop state machine for phylink-controlled PHY") +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/E1uvMEz-00000003Aoe-3qWe@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/phy_device.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -270,8 +270,7 @@ static bool phy_uses_state_machine(struc + if (phydev->phy_link_change == phy_link_change) + return phydev->attached_dev && phydev->adjust_link; + +- /* phydev->phy_link_change is implicitly phylink_phy_change() */ +- return true; ++ return !!phydev->phy_link_change; + } + + static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) +@@ -1791,6 +1790,8 @@ void phy_detach(struct phy_device *phyde + phydev->attached_dev->phydev = NULL; + phydev->attached_dev = NULL; + } ++ ++ phydev->phy_link_change = NULL; + phydev->phylink = NULL; + + if (phydev->mdio.dev.driver) diff --git a/queue-6.1/net-phy-move-phy_link_change-prior-to-mdio_bus_phy_may_suspend.patch b/queue-6.1/net-phy-move-phy_link_change-prior-to-mdio_bus_phy_may_suspend.patch new file mode 100644 index 0000000000..e807fba8b1 --- /dev/null +++ b/queue-6.1/net-phy-move-phy_link_change-prior-to-mdio_bus_phy_may_suspend.patch @@ -0,0 +1,75 @@ +From 681739313@139.com Fri Mar 27 02:51:43 2026 +From: Rajani Kantha <681739313@139.com> +Date: Fri, 27 Mar 2026 09:51:20 +0800 +Subject: net: phy: move phy_link_change() prior to mdio_bus_phy_may_suspend() +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, vladimir.oltean@nxp.com +Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, netdev@vger.kernel.org, rmk+kernel@armlinux.org.uk +Message-ID: <20260327015120.1712759-1-681739313@139.com> + +From: Vladimir Oltean + +[ Upstream commit f40a673d6b4a128fe95dd9b8c3ed02da50a6a862 ] + +In an upcoming change, mdio_bus_phy_may_suspend() will need to +distinguish a phylib-based PHY client from a phylink PHY client. +For that, it will need to compare the phydev->phy_link_change() function +pointer with the eponymous phy_link_change() provided by phylib. + +To avoid forward function declarations, the default PHY link state +change method should be moved upwards. There is no functional change +associated with this patch, it is only to reduce the noise from a real +bug fix. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/20250407093900.2155112-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +[ Minor context change fixed ] +Signed-off-by: Rajani Kantha <681739313@139.com> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/phy_device.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -234,6 +234,19 @@ static struct phy_driver genphy_driver; + static LIST_HEAD(phy_fixup_list); + static DEFINE_MUTEX(phy_fixup_lock); + ++static void phy_link_change(struct phy_device *phydev, bool up) ++{ ++ struct net_device *netdev = phydev->attached_dev; ++ ++ if (up) ++ netif_carrier_on(netdev); ++ else ++ netif_carrier_off(netdev); ++ phydev->adjust_link(netdev); ++ if (phydev->mii_ts && phydev->mii_ts->link_state) ++ phydev->mii_ts->link_state(phydev->mii_ts, phydev); ++} ++ + static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) + { + struct device_driver *drv = phydev->mdio.dev.driver; +@@ -1036,19 +1049,6 @@ struct phy_device *phy_find_first(struct + } + EXPORT_SYMBOL(phy_find_first); + +-static void phy_link_change(struct phy_device *phydev, bool up) +-{ +- struct net_device *netdev = phydev->attached_dev; +- +- if (up) +- netif_carrier_on(netdev); +- else +- netif_carrier_off(netdev); +- phydev->adjust_link(netdev); +- if (phydev->mii_ts && phydev->mii_ts->link_state) +- phydev->mii_ts->link_state(phydev->mii_ts, phydev); +-} +- + /** + * phy_prepare_link - prepares the PHY layer to monitor link status + * @phydev: target phy_device struct diff --git a/queue-6.1/selftests-mptcp-join-check-removing-signal-subflow-endp.patch b/queue-6.1/selftests-mptcp-join-check-removing-signal-subflow-endp.patch new file mode 100644 index 0000000000..ef6904d1d8 --- /dev/null +++ b/queue-6.1/selftests-mptcp-join-check-removing-signal-subflow-endp.patch @@ -0,0 +1,65 @@ +From matttbe@kernel.org Tue Mar 24 10:50:56 2026 +From: "Matthieu Baerts (NGI0)" +Date: Tue, 24 Mar 2026 10:49:39 +0100 +Subject: selftests: mptcp: join: check removing signal+subflow endp +To: mptcp@lists.linux.dev, stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: "Matthieu Baerts (NGI0)" , sashal@kernel.org, Mat Martineau , Jakub Kicinski +Message-ID: <20260324094936.1826804-6-matttbe@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +commit 1777f349ff41b62dfe27454b69c27b0bc99ffca5 upstream. + +This validates the previous commit: endpoints with both the signal and +subflow flags should always be marked as used even if it was not +possible to create new subflows due to the MPTCP PM limits. + +For this test, an extra endpoint is created with both the signal and the +subflow flags, and limits are set not to create extra subflows. In this +case, an ADD_ADDR is sent, but no subflows are created. Still, the local +endpoint is marked as used, and no warning is fired when removing the +endpoint, after having sent a RM_ADDR. + +The 'Fixes' tag here below is the same as the one from the previous +commit: this patch here is not fixing anything wrong in the selftests, +but it validates the previous fix for an issue introduced by this commit +ID. + +Fixes: 85df533a787b ("mptcp: pm: do not ignore 'subflow' if 'signal' flag is also set") +Cc: stable@vger.kernel.org +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260303-net-mptcp-misc-fixes-7-0-rc2-v1-5-4b5462b6f016@kernel.org +Signed-off-by: Jakub Kicinski +[ No conflicts, but in this kernel version 'run_tests' doesn't support + parameters set via env vars: positional parameters need to be used. + See commit 595ef566a2ef ("selftests: mptcp: drop addr_nr_ns1/2 + parameters") and commit e571fb09c893 ("selftests: mptcp: add speed env + var") which are not in this kernel version. ] +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/net/mptcp/mptcp_join.sh | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -2407,6 +2407,18 @@ remove_tests() + chk_rst_nr 0 0 + fi + ++ # signal+subflow with limits, remove ++ if reset "remove signal+subflow with limits"; then ++ pm_nl_set_limits $ns1 0 0 ++ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,subflow ++ pm_nl_set_limits $ns2 0 0 ++ run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow ++ chk_join_nr 0 0 0 ++ chk_add_nr 1 1 ++ chk_rm_nr 1 0 invert ++ chk_rst_nr 0 0 ++ fi ++ + # addresses remove + if reset "remove addresses"; then + pm_nl_set_limits $ns1 3 3 diff --git a/queue-6.1/selftests-mptcp-join-implicit-stop-transfer-after-last-check.patch b/queue-6.1/selftests-mptcp-join-implicit-stop-transfer-after-last-check.patch new file mode 100644 index 0000000000..3a1f239636 --- /dev/null +++ b/queue-6.1/selftests-mptcp-join-implicit-stop-transfer-after-last-check.patch @@ -0,0 +1,85 @@ +From matttbe@kernel.org Tue Mar 24 10:50:55 2026 +From: "Matthieu Baerts (NGI0)" +Date: Tue, 24 Mar 2026 10:49:38 +0100 +Subject: selftests: mptcp: join: implicit: stop transfer after last check +To: mptcp@lists.linux.dev, stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: "Matthieu Baerts (NGI0)" , sashal@kernel.org +Message-ID: <20260324094936.1826804-5-matttbe@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +With this kernel version, the 'implicit EP' MPTCP Join selftest ended +with an error message: + + 115 implicit EP creation[ ok ] + ID change is prevented[ ok ] + modif is allowed[ ok ] + TcpPassiveOpens 2 0.0 + TcpEstabResets 2 0.0 + TcpInSegs 315 0.0 + TcpOutSegs 617 0.0 + TcpOutRsts 1 0.0 + TcpExtDelayedACKs 289 0.0 + TcpExtTCPPureAcks 6 0.0 + TcpExtTCPOrigDataSent 306 0.0 + TcpExtTCPDelivered 306 0.0 + MPTcpExtMPCapableSYNRX 1 0.0 + MPTcpExtMPCapableACKRX 1 0.0 + MPTcpExtMPJoinSynRx 1 0.0 + MPTcpExtMPJoinAckRx 1 0.0 + MPTcpExtAddAddr 1 0.0 + MPTcpExtEchoAdd 1 0.0 + MPTcpExtMPFastcloseTx 1 0.0 + MPTcpExtMPRstTx 1 0.0 + MPTcpExtMPRstRx 1 0.0 + TcpActiveOpens 2 0.0 + TcpEstabResets 2 0.0 + TcpInSegs 617 0.0 + TcpOutSegs 315 0.0 + TcpOutRsts 1 0.0 + TcpExtTCPPureAcks 308 0.0 + TcpExtTCPOrigDataSent 306 0.0 + TcpExtTCPDelivered 307 0.0 + MPTcpExtMPCapableSYNTX 1 0.0 + MPTcpExtMPCapableSYNACKRX 1 0.0 + MPTcpExtMPJoinSynAckRx 1 0.0 + MPTcpExtAddAddr 1 0.0 + MPTcpExtEchoAdd 1 0.0 + MPTcpExtMPFastcloseRx 1 0.0 + MPTcpExtMPRstTx 1 0.0 + MPTcpExtMPRstRx 1 0.0 + MPTcpExtRcvWndShared 1 0.0 + +That's because the test was waiting for the end of the transfer for no +reasons, which ended after a timeout with an error. In this case, the +stats were displayed, but this error was ignored: the end of transfer is +not validated in this test. + +To fix that, stop the transfer after the last check, similar to what is +done in the other tests. + +Fixes: 699879d5f866 ("selftests: mptcp: join: endpoints: longer transfer") +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/net/mptcp/mptcp_join.sh | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -3429,6 +3429,7 @@ endpoint_tests() + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + run_tests $ns1 $ns2 10.0.1.1 128 0 0 slow 2>/dev/null & ++ local tests_pid=$! + + wait_mpj $ns1 + pm_nl_check_endpoint 1 "creation" \ +@@ -3441,6 +3442,7 @@ endpoint_tests() + pm_nl_add_endpoint $ns2 10.0.2.2 flags signal + pm_nl_check_endpoint 0 "modif is allowed" \ + $ns2 10.0.2.2 id 1 flags signal ++ kill_wait "${tests_pid}" + kill_tests_wait + fi + diff --git a/queue-6.1/series b/queue-6.1/series index 7d958b960b..75690a3383 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -292,3 +292,17 @@ mptcp-fix-lock-class-name-family-in-pm_nl_create_listen_socket.patch ext4-handle-wraparound-when-searching-for-blocks-for-indirect-mapped-blocks.patch cpufreq-governor-free-dbs_data-directly-when-gov-init-fails.patch cpufreq-governor-fix-double-free-in-cpufreq_dbs_governor_init-error-path.patch +mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch +mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch +erofs-handle-overlapped-pclusters-out-of-crafted-images-properly.patch +erofs-fix-psi-memstall-accounting.patch +erofs-fix-the-slab-out-of-bounds-in-drop_buffers.patch +xfs-avoid-dereferencing-log-items-after-push-callbacks.patch +xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch +net-phy-move-phy_link_change-prior-to-mdio_bus_phy_may_suspend.patch +net-phy-allow-mdio-bus-pm-ops-to-start-stop-state-machine-for-phylink-controlled-phy.patch +net-phy-fix-phy_uses_state_machine.patch +gfs2-fix-unlikely-race-in-gdlm_put_lock.patch +selftests-mptcp-join-implicit-stop-transfer-after-last-check.patch +selftests-mptcp-join-check-removing-signal-subflow-endp.patch +bluetooth-eir-fix-possible-crashes-on-eir_create_adv_data.patch diff --git a/queue-6.1/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch b/queue-6.1/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch new file mode 100644 index 0000000000..50bea5fc7d --- /dev/null +++ b/queue-6.1/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch @@ -0,0 +1,172 @@ +From 79ef34ec0554ec04bdbafafbc9836423734e1bd6 Mon Sep 17 00:00:00 2001 +From: Yuto Ohnuki +Date: Tue, 10 Mar 2026 18:38:38 +0000 +Subject: xfs: avoid dereferencing log items after push callbacks + +From: Yuto Ohnuki + +commit 79ef34ec0554ec04bdbafafbc9836423734e1bd6 upstream. + +After xfsaild_push_item() calls iop_push(), the log item may have been +freed if the AIL lock was dropped during the push. Background inode +reclaim or the dquot shrinker can free the log item while the AIL lock +is not held, and the tracepoints in the switch statement dereference +the log item after iop_push() returns. + +Fix this by capturing the log item type, flags, and LSN before calling +xfsaild_push_item(), and introducing a new xfs_ail_push_class trace +event class that takes these pre-captured values and the ailp pointer +instead of the log item pointer. + +Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c +Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary") +Cc: stable@vger.kernel.org # v5.9 +Signed-off-by: Yuto Ohnuki +Reviewed-by: Darrick J. Wong +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_trace.c | 1 + + fs/xfs/xfs_trace.h | 36 ++++++++++++++++++++++++++++++++---- + fs/xfs/xfs_trans_ail.c | 26 +++++++++++++++++++------- + 3 files changed, 52 insertions(+), 11 deletions(-) + +--- a/fs/xfs/xfs_trace.c ++++ b/fs/xfs/xfs_trace.c +@@ -22,6 +22,7 @@ + #include "xfs_trans.h" + #include "xfs_log.h" + #include "xfs_log_priv.h" ++#include "xfs_trans_priv.h" + #include "xfs_buf_item.h" + #include "xfs_quota.h" + #include "xfs_dquot_item.h" +--- a/fs/xfs/xfs_trace.h ++++ b/fs/xfs/xfs_trace.h +@@ -47,6 +47,7 @@ + #include + + struct xfs_agf; ++struct xfs_ail; + struct xfs_alloc_arg; + struct xfs_attr_list_context; + struct xfs_buf_log_item; +@@ -1335,14 +1336,41 @@ TRACE_EVENT(xfs_log_force, + DEFINE_EVENT(xfs_log_item_class, name, \ + TP_PROTO(struct xfs_log_item *lip), \ + TP_ARGS(lip)) +-DEFINE_LOG_ITEM_EVENT(xfs_ail_push); +-DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned); +-DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); +-DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); + DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_mark); + DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_skip); + DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_unpin); + ++DECLARE_EVENT_CLASS(xfs_ail_push_class, ++ TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), ++ TP_ARGS(ailp, type, flags, lsn), ++ TP_STRUCT__entry( ++ __field(dev_t, dev) ++ __field(uint, type) ++ __field(unsigned long, flags) ++ __field(xfs_lsn_t, lsn) ++ ), ++ TP_fast_assign( ++ __entry->dev = ailp->ail_log->l_mp->m_super->s_dev; ++ __entry->type = type; ++ __entry->flags = flags; ++ __entry->lsn = lsn; ++ ), ++ TP_printk("dev %d:%d lsn %d/%d type %s flags %s", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ CYCLE_LSN(__entry->lsn), BLOCK_LSN(__entry->lsn), ++ __print_symbolic(__entry->type, XFS_LI_TYPE_DESC), ++ __print_flags(__entry->flags, "|", XFS_LI_FLAGS)) ++) ++ ++#define DEFINE_AIL_PUSH_EVENT(name) \ ++DEFINE_EVENT(xfs_ail_push_class, name, \ ++ TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), \ ++ TP_ARGS(ailp, type, flags, lsn)) ++DEFINE_AIL_PUSH_EVENT(xfs_ail_push); ++DEFINE_AIL_PUSH_EVENT(xfs_ail_pinned); ++DEFINE_AIL_PUSH_EVENT(xfs_ail_locked); ++DEFINE_AIL_PUSH_EVENT(xfs_ail_flushing); ++ + DECLARE_EVENT_CLASS(xfs_ail_class, + TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), + TP_ARGS(lip, old_lsn, new_lsn), +--- a/fs/xfs/xfs_trans_ail.c ++++ b/fs/xfs/xfs_trans_ail.c +@@ -389,6 +389,12 @@ xfsaild_resubmit_item( + return XFS_ITEM_SUCCESS; + } + ++/* ++ * Push a single log item from the AIL. ++ * ++ * @lip may have been released and freed by the time this function returns, ++ * so callers must not dereference the log item afterwards. ++ */ + static inline uint + xfsaild_push_item( + struct xfs_ail *ailp, +@@ -474,20 +480,26 @@ xfsaild_push( + + lsn = lip->li_lsn; + while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) { +- int lock_result; ++ int lock_result; ++ uint type = lip->li_type; ++ unsigned long flags = lip->li_flags; ++ xfs_lsn_t item_lsn = lip->li_lsn; + + /* + * Note that iop_push may unlock and reacquire the AIL lock. We + * rely on the AIL cursor implementation to be able to deal with + * the dropped lock. ++ * ++ * The log item may have been freed by the push, so it must not ++ * be accessed or dereferenced below this line. + */ + lock_result = xfsaild_push_item(ailp, lip); + switch (lock_result) { + case XFS_ITEM_SUCCESS: + XFS_STATS_INC(mp, xs_push_ail_success); +- trace_xfs_ail_push(lip); ++ trace_xfs_ail_push(ailp, type, flags, item_lsn); + +- ailp->ail_last_pushed_lsn = lsn; ++ ailp->ail_last_pushed_lsn = item_lsn; + break; + + case XFS_ITEM_FLUSHING: +@@ -503,22 +515,22 @@ xfsaild_push( + * AIL is being flushed. + */ + XFS_STATS_INC(mp, xs_push_ail_flushing); +- trace_xfs_ail_flushing(lip); ++ trace_xfs_ail_flushing(ailp, type, flags, item_lsn); + + flushing++; +- ailp->ail_last_pushed_lsn = lsn; ++ ailp->ail_last_pushed_lsn = item_lsn; + break; + + case XFS_ITEM_PINNED: + XFS_STATS_INC(mp, xs_push_ail_pinned); +- trace_xfs_ail_pinned(lip); ++ trace_xfs_ail_pinned(ailp, type, flags, item_lsn); + + stuck++; + ailp->ail_log_flush++; + break; + case XFS_ITEM_LOCKED: + XFS_STATS_INC(mp, xs_push_ail_locked); +- trace_xfs_ail_locked(lip); ++ trace_xfs_ail_locked(ailp, type, flags, item_lsn); + + stuck++; + break; diff --git a/queue-6.1/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch b/queue-6.1/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch new file mode 100644 index 0000000000..b2f85699e3 --- /dev/null +++ b/queue-6.1/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch @@ -0,0 +1,96 @@ +From 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 Mon Sep 17 00:00:00 2001 +From: Yuto Ohnuki +Date: Tue, 10 Mar 2026 18:38:39 +0000 +Subject: xfs: save ailp before dropping the AIL lock in push callbacks + +From: Yuto Ohnuki + +commit 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 upstream. + +In xfs_inode_item_push() and xfs_qm_dquot_logitem_push(), the AIL lock +is dropped to perform buffer IO. Once the cluster buffer no longer +protects the log item from reclaim, the log item may be freed by +background reclaim or the dquot shrinker. The subsequent spin_lock() +call dereferences lip->li_ailp, which is a use-after-free. + +Fix this by saving the ailp pointer in a local variable while the AIL +lock is held and the log item is guaranteed to be valid. + +Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c +Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary") +Cc: stable@vger.kernel.org # v5.9 +Reviewed-by: Darrick J. Wong +Reviewed-by: Dave Chinner +Signed-off-by: Yuto Ohnuki +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_dquot_item.c | 9 +++++++-- + fs/xfs/xfs_inode_item.c | 9 +++++++-- + 2 files changed, 14 insertions(+), 4 deletions(-) + +--- a/fs/xfs/xfs_dquot_item.c ++++ b/fs/xfs/xfs_dquot_item.c +@@ -125,6 +125,7 @@ xfs_qm_dquot_logitem_push( + { + struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; + struct xfs_buf *bp = lip->li_buf; ++ struct xfs_ail *ailp = lip->li_ailp; + uint rval = XFS_ITEM_SUCCESS; + int error; + +@@ -153,7 +154,7 @@ xfs_qm_dquot_logitem_push( + goto out_unlock; + } + +- spin_unlock(&lip->li_ailp->ail_lock); ++ spin_unlock(&ailp->ail_lock); + + error = xfs_qm_dqflush(dqp, &bp); + if (!error) { +@@ -163,7 +164,11 @@ xfs_qm_dquot_logitem_push( + } else if (error == -EAGAIN) + rval = XFS_ITEM_LOCKED; + +- spin_lock(&lip->li_ailp->ail_lock); ++ /* ++ * The buffer no longer protects the log item from reclaim, so ++ * do not reference lip after this point. ++ */ ++ spin_lock(&ailp->ail_lock); + out_unlock: + xfs_dqunlock(dqp); + return rval; +--- a/fs/xfs/xfs_inode_item.c ++++ b/fs/xfs/xfs_inode_item.c +@@ -727,6 +727,7 @@ xfs_inode_item_push( + struct xfs_inode_log_item *iip = INODE_ITEM(lip); + struct xfs_inode *ip = iip->ili_inode; + struct xfs_buf *bp = lip->li_buf; ++ struct xfs_ail *ailp = lip->li_ailp; + uint rval = XFS_ITEM_SUCCESS; + int error; + +@@ -749,7 +750,7 @@ xfs_inode_item_push( + if (!xfs_buf_trylock(bp)) + return XFS_ITEM_LOCKED; + +- spin_unlock(&lip->li_ailp->ail_lock); ++ spin_unlock(&ailp->ail_lock); + + /* + * We need to hold a reference for flushing the cluster buffer as it may +@@ -773,7 +774,11 @@ xfs_inode_item_push( + rval = XFS_ITEM_LOCKED; + } + +- spin_lock(&lip->li_ailp->ail_lock); ++ /* ++ * The buffer no longer protects the log item from reclaim, so ++ * do not reference lip after this point. ++ */ ++ spin_lock(&ailp->ail_lock); + return rval; + } +