From: Greg Kroah-Hartman Date: Mon, 20 Jul 2026 14:46:42 +0000 (+0200) Subject: 6.1-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96739ee3e46429fdd90d7b042a9b233cebb51716;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch mips-ip22-gio-fix-device-reference-leak-in-probe.patch mips-ip22-gio-fix-gio-device-memory-leak.patch mips-ip22-gio-fix-kfree-of-static-object.patch mips-sched-fix-cpumask_offstack-memory-corruption.patch mtd-rawnand-fix-condition-in-nand_select_target.patch mtd-rawnand-pl353-fix-probe-resource-allocation.patch mtd-slram-remove-failed-entries-from-the-device-list.patch net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch ocfs2-avoid-moving-extents-to-occupied-clusters.patch ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch proc-only-bump-parent-nlink-when-registering-directories.patch riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch --- diff --git a/queue-6.1/fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch b/queue-6.1/fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch new file mode 100644 index 0000000000..c77d06e9e2 --- /dev/null +++ b/queue-6.1/fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch @@ -0,0 +1,81 @@ +From 1ebd684b8f627f75bc3e03f8b2ad8400fd1f02cd Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Mon, 13 Apr 2026 09:31:17 -0400 +Subject: fs/ntfs3: add depth limit to indx_find_buffer to prevent stack overflow + +From: Michael Bommarito + +commit 1ebd684b8f627f75bc3e03f8b2ad8400fd1f02cd upstream. + +indx_find_buffer() recursively descends the B+ tree index with no depth +limit. A crafted NTFS image with circular index node references causes +unbounded recursion, overflowing the kernel stack and panicking the +system. + +This is reachable by mounting a malicious NTFS filesystem (e.g. from a +USB drive via desktop automount) and deleting a file whose index entry +triggers the rebalancing fallback path in indx_delete_entry(). + +Add a depth parameter and bail out with -EINVAL when it reaches the +fnd->nodes array bound, matching the constraint already enforced by +fnd_push() in indx_find(). + +The related function indx_find() was previously patched for a similar +infinite-loop issue (commit 1732053c8a6b), but indx_find_buffer() was +missed. + +Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") +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: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/index.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -1991,13 +1991,21 @@ out1: + static struct indx_node *indx_find_buffer(struct ntfs_index *indx, + struct ntfs_inode *ni, + const struct INDEX_ROOT *root, +- __le64 vbn, struct indx_node *n) ++ __le64 vbn, struct indx_node *n, ++ int depth) + { + int err; + const struct NTFS_DE *e; + struct indx_node *r; + const struct INDEX_HDR *hdr = n ? &n->index->ihdr : &root->ihdr; + ++ /* ++ * Limit recursion depth to prevent stack overflow from crafted ++ * images. Use the same bound as the fnd->nodes array (20). ++ */ ++ if (depth > ARRAY_SIZE(((struct ntfs_fnd *)NULL)->nodes)) ++ return ERR_PTR(-EINVAL); ++ + /* Step 1: Scan one level. */ + for (e = hdr_first_de(hdr);; e = hdr_next_de(hdr, e)) { + if (!e) +@@ -2018,7 +2026,8 @@ static struct indx_node *indx_find_buffe + if (err) + return ERR_PTR(err); + +- r = indx_find_buffer(indx, ni, root, vbn, n); ++ r = indx_find_buffer(indx, ni, root, vbn, n, ++ depth + 1); + if (r) + return r; + } +@@ -2419,7 +2428,7 @@ int indx_delete_entry(struct ntfs_index + + fnd_clear(fnd); + +- in = indx_find_buffer(indx, ni, root, sub_vbn, NULL); ++ in = indx_find_buffer(indx, ni, root, sub_vbn, NULL, 0); + if (IS_ERR(in)) { + err = PTR_ERR(in); + goto out; diff --git a/queue-6.1/fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch b/queue-6.1/fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch new file mode 100644 index 0000000000..5816c0d6f9 --- /dev/null +++ b/queue-6.1/fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch @@ -0,0 +1,64 @@ +From d1570c48f49a693974d000251030370ee2e83539 Mon Sep 17 00:00:00 2001 +From: Konstantin Komarov +Date: Tue, 2 Jun 2026 15:15:47 +0200 +Subject: fs/ntfs3: bound attr_off in UpdateResidentValue against data_off + +From: Konstantin Komarov + +commit d1570c48f49a693974d000251030370ee2e83539 upstream. + +In do_action()'s UpdateResidentValue case (fslog.c:3307), +lrh->attr_off and lrh->redo_len come from the on-disk LRH. +When they satisfy aoff + dlen < attr->res.data_off, the +assignment + + attr->res.data_size = cpu_to_le32(aoff + dlen - data_off); + +underflows to ~4 GiB (e.g. 0xFFFFFFF9 when aoff=0x10, dlen=1, +data_off=0x18). Subsequent code that reads attr->res.data_size +to walk the resident attribute payload would then read up to +4 GiB past the 1024-byte MFT record allocation. + +The existing mi_enum_attr() defense in fs/ntfs3/record.c:287 +catches the corrupted data_size on the next attribute walk +and fails the mount, but only on the path that walks all +attributes. A read site that picks an attribute by name and +reads its data_size without re-validating is not covered. +Validate aoff against data_off and asize at the source. + +Reproduced under UML+KASAN on mainline 8d90b09e6741 via +pr_warn-only probe: with aoff=0x10 and data_off=0x18, the +post-assignment data_size is 0xfffffff9 (mount then fails +at -22 from mi_enum_attr). + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +[almaz.alexandrovich@paragon-software.com: clang-formatted the changes] +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -3316,6 +3316,17 @@ skip_load_parent: + nsize = ALIGN(nsize, 8); + data_off = le16_to_cpu(attr->res.data_off); + ++ /* ++ * aoff comes from the on-disk lrh->attr_off. Forbid ++ * writes that begin below the resident attribute's ++ * data_off (which would overwrite the resident header), ++ * and forbid aoff + dlen < data_off, which would make ++ * the data_size assignment below underflow to ~4 GiB. ++ */ ++ if (aoff < data_off || aoff + dlen < data_off || ++ aoff + dlen > asize) ++ goto dirty_vol; ++ + if (nsize < asize) { + memmove(Add2Ptr(attr, aoff), data, dlen); + data = NULL; // To skip below memmove(). diff --git a/queue-6.1/fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch b/queue-6.1/fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch new file mode 100644 index 0000000000..ec75e48923 --- /dev/null +++ b/queue-6.1/fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch @@ -0,0 +1,116 @@ +From 5e7b598660cfa8e5af172cf4c65cffc126333307 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Fri, 15 May 2026 12:34:05 -0400 +Subject: fs/ntfs3: bound copy_lcns dp->page_lcns[] index in analysis pass + +From: Michael Bommarito + +commit 5e7b598660cfa8e5af172cf4c65cffc126333307 upstream. + +In log_replay()'s analysis pass, after find_dp() returns a +valid DIR_PAGE_ENTRY for the (target_attr, target_vcn) tuple, +the copy_lcns block walks lrh->lcns_follow further entries: + + t16 = le16_to_cpu(lrh->lcns_follow); + for (i = 0; i < t16; i++) { + size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) - + le64_to_cpu(dp->vcn)); + dp->page_lcns[j + i] = lrh->page_lcns[i]; + } + +find_dp() only validates that target_vcn falls within +[dp->vcn, dp->vcn + dp->lcns_follow), i.e., that the FIRST +cluster is covered. The walk through the further entries is +not bounded against dp->lcns_follow. For a malformed LRH +where target_vcn = dp->vcn + dp->lcns_follow - 1 and +lrh->lcns_follow > 1, the i > 0 writes overflow the dp's +allocated page_lcns[] array. + +Add the missing j + lrh->lcns_follow <= dp->lcns_follow guard. + +Reproduced under UML+KASAN on mainline 8d90b09e6741 as a +slab-out-of-bounds write of size 8 from log_replay+0x68d4 on +the mount path. + +This is distinct from Pavitra Jha's 2026-05-02 patch +("fs/ntfs3: validate lcns_follow in log_replay conversion", +<20260502154252.164586-1-jhapavitra98@gmail.com>) which +addresses the separate version-0 dirty-page-table conversion +path's memmove(&dp->vcn, ...) call. The two fixes are +complementary; both should land. + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +[almaz.alexandrovich@paragon-software.com: clang-formatted the changes, +fixed conflicts] +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 46 +++++++++++++++++++++++++++++----------------- + 1 file changed, 29 insertions(+), 17 deletions(-) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -3368,8 +3368,8 @@ move_data: + + if (run_get_highest_vcn(le64_to_cpu(attr->nres.svcn), + attr_run(attr), +- le32_to_cpu(attr->size) - +- le16_to_cpu(attr->nres.run_off), ++ le32_to_cpu(attr->size) - ++ le16_to_cpu(attr->nres.run_off), + &t64)) { + goto dirty_vol; + } +@@ -4563,22 +4563,34 @@ copy_lcns: + * whole routine a loop, case Lcns do not fit below. + */ + t16 = le16_to_cpu(lrh->lcns_follow); +- t32 = le32_to_cpu(dp->lcns_follow); +- if (le64_to_cpu(lrh->target_vcn) < le64_to_cpu(dp->vcn)) { +- err = -EINVAL; +- goto out; +- } +- +- for (i = 0; i < t16; i++) { +- size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) - +- le64_to_cpu(dp->vcn)); +- if (j >= t32 || i >= t32 - j) { +- err = -EINVAL; +- goto out; +- } +- dp->page_lcns[j + i] = lrh->page_lcns[i]; +- } ++ t32 = le32_to_cpu(dp->lcns_follow); ++ if (le64_to_cpu(lrh->target_vcn) < le64_to_cpu(dp->vcn)) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ /* ++ * find_dp() only validates that target_vcn is the first ++ * cluster covered by dp. The walk through lrh->lcns_follow ++ * further entries must stay within the allocated ++ * dp->page_lcns[] array, which is sized by dp->lcns_follow. ++ */ ++ if (le64_to_cpu(lrh->target_vcn) - le64_to_cpu(dp->vcn) + t16 > ++ le32_to_cpu(dp->lcns_follow)) { ++ err = -EINVAL; ++ log->set_dirty = true; ++ goto out; ++ } + ++ for (i = 0; i < t16; i++) { ++ size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) - ++ le64_to_cpu(dp->vcn)); ++ if (j >= t32 || i >= t32 - j) { ++ err = -EINVAL; ++ goto out; ++ } ++ dp->page_lcns[j + i] = lrh->page_lcns[i]; ++ } + goto next_log_record_analyze; + + case DeleteDirtyClusters: { diff --git a/queue-6.1/fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch b/queue-6.1/fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch new file mode 100644 index 0000000000..997e2bcb5e --- /dev/null +++ b/queue-6.1/fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch @@ -0,0 +1,74 @@ +From fc4626bb3656362de8b0ecd56605d47a19ec3518 Mon Sep 17 00:00:00 2001 +From: Konstantin Komarov +Date: Tue, 2 Jun 2026 15:21:03 +0200 +Subject: fs/ntfs3: bound DeleteIndexEntryAllocation memmove length + +From: Konstantin Komarov + +commit fc4626bb3656362de8b0ecd56605d47a19ec3518 upstream. + +In do_action()'s DeleteIndexEntryAllocation case, e->size comes +from an on-disk INDEX_BUFFER entry. When e->size makes +e + e->size point past hdr + hdr->used, +PtrOffset(e1, Add2Ptr(hdr, used)) returns a negative ptrdiff_t +that is silently cast to a quasi-infinite size_t when passed +to memmove(). The memmove then walks past the destination +buffer. + +The sibling DeleteIndexEntryRoot case at fslog.c:3540-3543 +already carries the corresponding guard: + + if (PtrOffset(e1, Add2Ptr(hdr, used)) < esize || + Add2Ptr(e, esize) > Add2Ptr(lrh, rec_len) || + used + esize > le32_to_cpu(hdr->total)) { + goto dirty_vol; + } + +Apply the same shape to the allocation-path case. Also reject +esize == 0: memmove(e, e, ...) is a no-op and leaves +hdr->used unchanged, hiding a malformed entry from the +existing check_index_header() walk. + +Reproduced under UML+KASAN on mainline 8d90b09e6741 by +mounting a crafted NTFS image: the unguarded memmove takes a +length of 0xffffffffffffff00 and the kernel oopses in +memmove+0x81/0x1a0 on the do_action+0x36a2 frame. + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +[almaz.alexandrovich@paragon-software.com: clang-formatted the changes] +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -3577,9 +3577,23 @@ move_data: + } + + e1 = Add2Ptr(e, esize); +- nsize = esize; + used = le32_to_cpu(hdr->used); + ++ /* ++ * Reject crafted entries whose e->size makes e + esize ++ * point past the INDEX_HDR's used boundary. Without this, ++ * PtrOffset(e1, hdr + used) underflows to a quasi-infinite ++ * size_t when fed to the memmove() below. ++ * ++ * Also reject esize == 0: memmove(e, e, ...) is a no-op and ++ * leaves hdr->used unchanged, masking the crafted entry. ++ */ ++ if (!esize || Add2Ptr(e, esize) > Add2Ptr(hdr, used) || ++ PtrOffset(e1, Add2Ptr(hdr, used)) < esize) ++ goto dirty_vol; ++ ++ nsize = esize; ++ + memmove(e, e1, PtrOffset(e1, Add2Ptr(hdr, used))); + + hdr->used = cpu_to_le32(used - nsize); diff --git a/queue-6.1/fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch b/queue-6.1/fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch new file mode 100644 index 0000000000..3e999498da --- /dev/null +++ b/queue-6.1/fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch @@ -0,0 +1,80 @@ +From 3e127829e57f5190f612412ece4541cb96d5ec7a Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Tue, 19 May 2026 05:51:35 -0400 +Subject: fs/ntfs3: bound NTFS_DE view.data_off in UpdateRecordData{Root,Allocation} + +From: Michael Bommarito + +commit 3e127829e57f5190f612412ece4541cb96d5ec7a upstream. + +In do_action()'s UpdateRecordDataRoot (fslog.c:3489) and +UpdateRecordDataAllocation (fslog.c:3697) cases, the memmove +destination is `Add2Ptr(e, le16_to_cpu(e->view.data_off))`, +where e->view.data_off comes from an on-disk NTFS_DE inside +an INDEX_ROOT or INDEX_BUFFER. Neither case validates +view.data_off + dlen against e->size; the existing +check_if_index_root / check_if_alloc_index helpers walk the +entry chain and validate the entry's offset, but not its +internal view fields. + +The neighbouring read sites (e.g., fs/ntfs3/index.c when +iterating view entries) check view.data_off + view.data_size +<= e->size. Apply the same bound at the two memmove sites. + +Reproduced under UML+KASAN on mainline 8d90b09e6741 via +pr_warn-only probe instrumentation: with view.data_off forced +to 0xFFFC, the memmove writes 32 bytes past the end of the +NTFS_DE. + +This is similar in shape to Pavitra Jha's 2026-05-02 patch +"fs/ntfs3: prevent oob in case UpdateRecordDataRoot" +(<20260502105008.21827-1-jhapavitra98@gmail.com>) which +proposes calling ntfs3_bad_de_range(); that helper does not +exist in mainline. This patch uses inline checks. + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Cc: stable@vger.kernel.org +Reported-by: Pavitra Jha +Closes: https://lore.kernel.org/ntfs3/20260502105008.21827-1-jhapavitra98@gmail.com/ +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -3515,6 +3515,18 @@ move_data: + + e = Add2Ptr(attr, le16_to_cpu(lrh->attr_off)); + ++ /* ++ * e->view.data_off and dlen come from the on-disk ++ * INDEX_ROOT entry / LRH. The neighbouring read sites ++ * (e.g. fs/ntfs3/index.c) check that ++ * view.data_off + view.data_size <= e->size; mirror that ++ * bound here so the memmove cannot reach past the entry. ++ */ ++ if (le16_to_cpu(e->view.data_off) > le16_to_cpu(e->size) || ++ le16_to_cpu(e->view.data_off) + dlen > ++ le16_to_cpu(e->size)) ++ goto dirty_vol; ++ + memmove(Add2Ptr(e, le16_to_cpu(e->view.data_off)), data, dlen); + + mi->dirty = true; +@@ -3723,6 +3735,12 @@ move_data: + goto dirty_vol; + } + ++ /* See UpdateRecordDataRoot for the rationale. */ ++ if (le16_to_cpu(e->view.data_off) > le16_to_cpu(e->size) || ++ le16_to_cpu(e->view.data_off) + dlen > ++ le16_to_cpu(e->size)) ++ goto dirty_vol; ++ + memmove(Add2Ptr(e, le16_to_cpu(e->view.data_off)), data, dlen); + + a_dirty = true; diff --git a/queue-6.1/fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch b/queue-6.1/fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch new file mode 100644 index 0000000000..6b8eb250d1 --- /dev/null +++ b/queue-6.1/fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch @@ -0,0 +1,45 @@ +From 932fa0c1496286e39e14e27194c1ee7c2181629f Mon Sep 17 00:00:00 2001 +From: Zhan Xusheng +Date: Wed, 6 May 2026 15:55:54 +0800 +Subject: fs/ntfs3: fix syncing wrong inode on DIRSYNC cross-directory rename + +From: Zhan Xusheng + +commit 932fa0c1496286e39e14e27194c1ee7c2181629f upstream. + +In ntfs3_rename(), when IS_DIRSYNC(new_dir) is true, the code syncs +the renamed file inode instead of the target directory new_dir: + if (IS_DIRSYNC(new_dir)) + ntfs_sync_inode(inode); /* should be new_dir */ + +DIRSYNC requires that directory metadata changes are written to disk +synchronously. Since new_dir was modified (a new directory entry was +added), it is new_dir that must be synced to satisfy the guarantee, +not the renamed file itself. + +This bug has existed since the initial ntfs3 implementation and was +carried through the refactoring in commit 78ab59fee07f +("fs/ntfs3: Rework file operations"). + +Fix by syncing new_dir instead of inode. + +Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") +Cc: stable@vger.kernel.org +Signed-off-by: Zhan Xusheng +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ntfs3/namei.c ++++ b/fs/ntfs3/namei.c +@@ -333,7 +333,7 @@ static int ntfs_rename(struct user_names + ntfs_sync_inode(dir); + + if (IS_DIRSYNC(new_dir)) +- ntfs_sync_inode(inode); ++ ntfs_sync_inode(new_dir); + } + + ni_unlock(ni); diff --git a/queue-6.1/fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch b/queue-6.1/fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch new file mode 100644 index 0000000000..cb39e4edbd --- /dev/null +++ b/queue-6.1/fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch @@ -0,0 +1,76 @@ +From 6a4c53a2e26a865565bd6a460961e8d6fcb32329 Mon Sep 17 00:00:00 2001 +From: Konstantin Komarov +Date: Mon, 1 Jun 2026 10:57:56 +0200 +Subject: fs/ntfs3: validate lcns_follow in log_replay conversion + +From: Konstantin Komarov + +commit 6a4c53a2e26a865565bd6a460961e8d6fcb32329 upstream. + +log_replay() converts DIR_PAGE_ENTRY_32 records into DIR_PAGE_ENTRY +records when replaying version 0 restart tables. + +During this conversion, the memmove() length is derived directly from +the on-disk lcns_follow field: + + memmove(&dp->vcn, &dp0->vcn_low, + 2 * sizeof(u64) + + le32_to_cpu(dp->lcns_follow) * sizeof(u64)); + +check_rstbl() validates restart table structure, but does not constrain +per-entry lcns_follow values relative to the entry size. A malformed +filesystem image can provide an oversized lcns_follow value, causing +the conversion memmove() to access memory beyond the bounds of the +allocated restart table buffer. + +The same field is later used to bound iteration over page_lcns[], +so validating lcns_follow during conversion also prevents downstream +out-of-bounds access from the same malformed metadata. + +Compute the maximum valid lcns_follow from the already-validated +restart table entry size and reject entries that exceed this bound. +Reuse the existing t16/t32 scratch variables already declared in +log_replay() to avoid introducing new declarations. + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Cc: stable@vger.kernel.org +Signed-off-by: Pavitra Jha +[almaz.alexandrovich@paragon-software.com: fixed the conflicts] +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -4265,13 +4265,26 @@ check_dirty_page_table: + if (rst->major_ver) + goto end_conv_1; + ++ t16 = le16_to_cpu(dptbl->size); ++ if (t16 < sizeof(struct DIR_PAGE_ENTRY)) { ++ log->set_dirty = true; ++ goto out; ++ } ++ ++ t32 = (t16 - sizeof(struct DIR_PAGE_ENTRY)) / sizeof(u64); ++ + dp = NULL; + while ((dp = enum_rstbl(dptbl, dp))) { + struct DIR_PAGE_ENTRY_32 *dp0 = (struct DIR_PAGE_ENTRY_32 *)dp; +- // NOTE: Danger. Check for of boundary. ++ u32 lcns = le32_to_cpu(dp->lcns_follow); ++ ++ if (lcns > t32) { ++ log->set_dirty = true; ++ goto out; ++ } ++ + memmove(&dp->vcn, &dp0->vcn_low, +- 2 * sizeof(u64) + +- le32_to_cpu(dp->lcns_follow) * sizeof(u64)); ++ 2 * sizeof(u64) + lcns * sizeof(u64)); + } + + end_conv_1: diff --git a/queue-6.1/mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch b/queue-6.1/mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch new file mode 100644 index 0000000000..8ae2dba563 --- /dev/null +++ b/queue-6.1/mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch @@ -0,0 +1,123 @@ +From 5ff79e8bdc75db51e30298a75939e2308e7658e0 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Wed, 6 May 2026 23:42:23 +0100 +Subject: MIPS: DEC: Ensure 32-bit stack location for o32 prom_printf() + +From: Maciej W. Rozycki + +commit 5ff79e8bdc75db51e30298a75939e2308e7658e0 upstream. + +In 64-bit configurations calling any firmware entry points from a kernel +thread other than the initial one will result in a situation where the +stack has been placed in the XKPHYS 64-bit memory segment. + +Consequently the stack pointer is no longer a 32-bit value and when the +32-bit firmware code called uses 32-bit ALU operations to manipulate the +stack pointer, the calculated result is incorrect (in fact in the 64-bit +MIPS ISA almost all 32-bit ALU operations will produce an unpredictable +result when executed on 64-bit data) and control goes astray. + +This may happen when no final console driver has been enabled in the +configuration and consequently the initial console continues being used +late into bootstrap, or with an upcoming change that will switch the zs +driver to use a platform device, which in turn will make the console +handover happen only after other kernel threads have already been +started, and the kernel will hang at: + + pid_max: default: 32768 minimum: 301 + +or somewhat later, but always before: + + cblist_init_generic: Setting adjustable number of callback queues. + +has been printed. + +It seems that only the prom_printf() entry point is affected. Of all +the other entry points wired only rex_slot_address() and rex_gettcinfo() +are called from a kernel thread other than the initial one, specifically +kernel_init(), and they are leaf functions that do no business with the +stack, having worked with no issue ever since 64-bit support was added +for the platform back in 2002. + +To address this issue then, arrange for the stack to be switched in the +o32 wrapper as required for prom_printf() only, by supplying call_o32() +with a pointer to a chunk of initdata space, which is placed in the +CKSEG0 32-bit compatibility segment, observing that prom_printf() is +only called from console output handler and therefore with the console +lock held, implying no need for this code to be reentrant. + +Other firmware entry points may be called with interrupts enabled and no +lock held, and may therefore require that call_o32() be reentrant. They +trigger no issue at this point and "if it ain't broke, don't fix it," so +just leave them alone. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Maciej W. Rozycki +Cc: stable@vger.kernel.org # v2.6.12+ +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/dec/prom/init.c | 6 +++++- + arch/mips/include/asm/dec/prom.h | 15 +++++++++++++-- + 2 files changed, 18 insertions(+), 3 deletions(-) + +--- a/arch/mips/dec/prom/init.c ++++ b/arch/mips/dec/prom/init.c +@@ -3,7 +3,7 @@ + * init.c: PROM library initialisation code. + * + * Copyright (C) 1998 Harald Koerfgen +- * Copyright (C) 2002, 2004 Maciej W. Rozycki ++ * Copyright (C) 2002, 2004, 2026 Maciej W. Rozycki + */ + #include + #include +@@ -20,6 +20,10 @@ + #include + + ++#ifdef CONFIG_64BIT ++unsigned long o32_stk[O32_STK_SIZE] __initdata = { 0 }; ++#endif ++ + int (*__rex_bootinit)(void); + int (*__rex_bootread)(void); + int (*__rex_getbitmap)(memmap *); +--- a/arch/mips/include/asm/dec/prom.h ++++ b/arch/mips/include/asm/dec/prom.h +@@ -4,7 +4,7 @@ + * + * DECstation PROM interface. + * +- * Copyright (C) 2002 Maciej W. Rozycki ++ * Copyright (C) 2002, 2026 Maciej W. Rozycki + * + * Based on arch/mips/dec/prom/prom.h by the Anonymous. + */ +@@ -97,6 +97,17 @@ extern int (*__pmax_close)(int); + + #ifdef CONFIG_64BIT + ++#define O32_STK_SIZE 512 ++extern unsigned long o32_stk[]; ++ ++/* Switch the stack if outside the 32-bit address space. */ ++static inline unsigned long *o32_get_stk(void) ++{ ++ long fp = (long)__builtin_frame_address(0); ++ ++ return fp != (int)fp ? o32_stk + O32_STK_SIZE : NULL; ++} ++ + /* + * On MIPS64 we have to call PROM functions via a helper + * dispatcher to accommodate ABI incompatibilities. +@@ -128,7 +139,7 @@ int __DEC_PROM_O32(_prom_printf, (int (* + + #define prom_getchar() _prom_getchar(__prom_getchar, NULL) + #define prom_getenv(x) _prom_getenv(__prom_getenv, NULL, x) +-#define prom_printf(x...) _prom_printf(__prom_printf, NULL, x) ++#define prom_printf(x...) _prom_printf(__prom_printf, o32_get_stk(), x) + + #else /* !CONFIG_64BIT */ + diff --git a/queue-6.1/mips-ip22-gio-fix-device-reference-leak-in-probe.patch b/queue-6.1/mips-ip22-gio-fix-device-reference-leak-in-probe.patch new file mode 100644 index 0000000000..3f604e2adb --- /dev/null +++ b/queue-6.1/mips-ip22-gio-fix-device-reference-leak-in-probe.patch @@ -0,0 +1,39 @@ +From b82930a4c5dbc5c4df39c0f93d968c239f2c6885 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 24 Apr 2026 12:28:47 +0200 +Subject: MIPS: ip22-gio: fix device reference leak in probe + +From: Johan Hovold + +commit b82930a4c5dbc5c4df39c0f93d968c239f2c6885 upstream. + +The gio probe function needlessly takes a device reference which is +never released and therefore prevents unbound gio devices from being +freed. + +Fixes: e84de0c61905 ("MIPS: GIO bus support for SGI IP22/28") +Cc: stable@vger.kernel.org # 3.3 +Cc: Thomas Bogendoerfer +Signed-off-by: Johan Hovold +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/sgi-ip22/ip22-gio.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/arch/mips/sgi-ip22/ip22-gio.c ++++ b/arch/mips/sgi-ip22/ip22-gio.c +@@ -133,13 +133,9 @@ static int gio_device_probe(struct devic + if (!drv->probe) + return error; + +- gio_dev_get(gio_dev); +- + match = gio_match_device(drv->id_table, gio_dev); + if (match) + error = drv->probe(gio_dev, match); +- if (error) +- gio_dev_put(gio_dev); + + return error; + } diff --git a/queue-6.1/mips-ip22-gio-fix-gio-device-memory-leak.patch b/queue-6.1/mips-ip22-gio-fix-gio-device-memory-leak.patch new file mode 100644 index 0000000000..4504a0249e --- /dev/null +++ b/queue-6.1/mips-ip22-gio-fix-gio-device-memory-leak.patch @@ -0,0 +1,33 @@ +From 7de9a1b45f5a95b58145653c525c8fb80292d9ab Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 24 Apr 2026 12:28:46 +0200 +Subject: MIPS: ip22-gio: fix gio device memory leak + +From: Johan Hovold + +commit 7de9a1b45f5a95b58145653c525c8fb80292d9ab upstream. + +The gio device release callback was never wired up so gio devices are +not freed when the last reference is dropped. + +Fixes: e84de0c61905 ("MIPS: GIO bus support for SGI IP22/28") +Cc: stable@vger.kernel.org # 3.3 +Cc: Thomas Bogendoerfer +Signed-off-by: Johan Hovold +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/sgi-ip22/ip22-gio.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/sgi-ip22/ip22-gio.c ++++ b/arch/mips/sgi-ip22/ip22-gio.c +@@ -101,6 +101,8 @@ int gio_device_register(struct gio_devic + { + giodev->dev.bus = &gio_bus_type; + giodev->dev.parent = &gio_bus; ++ giodev->dev.release = gio_release_dev; ++ + return device_register(&giodev->dev); + } + EXPORT_SYMBOL_GPL(gio_device_register); diff --git a/queue-6.1/mips-ip22-gio-fix-kfree-of-static-object.patch b/queue-6.1/mips-ip22-gio-fix-kfree-of-static-object.patch new file mode 100644 index 0000000000..0a0589d752 --- /dev/null +++ b/queue-6.1/mips-ip22-gio-fix-kfree-of-static-object.patch @@ -0,0 +1,32 @@ +From c62cdd3e919bdf84c37ec46810f87cdb1736e822 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 24 Apr 2026 12:28:45 +0200 +Subject: MIPS: ip22-gio: fix kfree() of static object + +From: Johan Hovold + +commit c62cdd3e919bdf84c37ec46810f87cdb1736e822 upstream. + +The gio bus root device is a statically allocated object which must not +be freed by kfree() on failure to register the device or bus. + +Fixes: 82242d28ff8b ("MIPS: IP22: Add missing put_device call") +Cc: stable@vger.kernel.org # 3.17 +Cc: Levente Kurusa +Signed-off-by: Johan Hovold +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/sgi-ip22/ip22-gio.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/mips/sgi-ip22/ip22-gio.c ++++ b/arch/mips/sgi-ip22/ip22-gio.c +@@ -30,7 +30,6 @@ static struct { + + static void gio_bus_release(struct device *dev) + { +- kfree(dev); + } + + static struct device gio_bus = { diff --git a/queue-6.1/mips-sched-fix-cpumask_offstack-memory-corruption.patch b/queue-6.1/mips-sched-fix-cpumask_offstack-memory-corruption.patch new file mode 100644 index 0000000000..6f35806de2 --- /dev/null +++ b/queue-6.1/mips-sched-fix-cpumask_offstack-memory-corruption.patch @@ -0,0 +1,94 @@ +From 98e37db4a34d3af3fb2f4648295c25b5e40b20e3 Mon Sep 17 00:00:00 2001 +From: Aaron Tomlin +Date: Tue, 26 May 2026 10:16:51 -0400 +Subject: mips: sched: Fix CPUMASK_OFFSTACK memory corruption + +From: Aaron Tomlin + +commit 98e37db4a34d3af3fb2f4648295c25b5e40b20e3 upstream. + +This patch addresses a critical memory management flaw. When +CONFIG_CPUMASK_OFFSTACK is enabled, cpumask_var_t is a pointer. +Consequently, sizeof(new_mask) evaluates to the pointer size, causing +copy_from_user() to clobber the mask pointer. Furthermore, the old +logic performed copy_from_user() before allocating the mask. + +Fix this by allocating new_mask first. To handle variable-sized user +masks correctly, use cpumask_size() to truncate overly large user masks +or pad undersized masks with zeros before copying the data directly into +the allocated buffer. + +Fixes: 295cbf6d63165 ("[MIPS] Move FPU affinity code into separate file.") +Cc: stable@vger.kernel.org +Signed-off-by: Aaron Tomlin +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kernel/mips-mt-fpaff.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +--- a/arch/mips/kernel/mips-mt-fpaff.c ++++ b/arch/mips/kernel/mips-mt-fpaff.c +@@ -70,11 +70,16 @@ asmlinkage long mipsmt_sys_sched_setaffi + struct task_struct *p; + int retval; + +- if (len < sizeof(new_mask)) +- return -EINVAL; +- +- if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask))) +- return -EFAULT; ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) ++ return -ENOMEM; ++ if (len < cpumask_size()) ++ cpumask_clear(new_mask); ++ else if (len > cpumask_size()) ++ len = cpumask_size(); ++ if (copy_from_user(new_mask, user_mask_ptr, len)) { ++ retval = -EFAULT; ++ goto out_free_new_mask; ++ } + + cpus_read_lock(); + rcu_read_lock(); +@@ -83,7 +88,8 @@ asmlinkage long mipsmt_sys_sched_setaffi + if (!p) { + rcu_read_unlock(); + cpus_read_unlock(); +- return -ESRCH; ++ retval = -ESRCH; ++ goto out_free_new_mask; + } + + /* Prevent p going away */ +@@ -94,13 +100,9 @@ asmlinkage long mipsmt_sys_sched_setaffi + retval = -ENOMEM; + goto out_put_task; + } +- if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { +- retval = -ENOMEM; +- goto out_free_cpus_allowed; +- } + if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) { + retval = -ENOMEM; +- goto out_free_new_mask; ++ goto out_free_cpus_allowed; + } + if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) { + retval = -EPERM; +@@ -141,13 +143,13 @@ asmlinkage long mipsmt_sys_sched_setaffi + } + out_unlock: + free_cpumask_var(effective_mask); +-out_free_new_mask: +- free_cpumask_var(new_mask); + out_free_cpus_allowed: + free_cpumask_var(cpus_allowed); + out_put_task: + put_task_struct(p); + cpus_read_unlock(); ++out_free_new_mask: ++ free_cpumask_var(new_mask); + return retval; + } + diff --git a/queue-6.1/mtd-rawnand-fix-condition-in-nand_select_target.patch b/queue-6.1/mtd-rawnand-fix-condition-in-nand_select_target.patch new file mode 100644 index 0000000000..60e4c2ff92 --- /dev/null +++ b/queue-6.1/mtd-rawnand-fix-condition-in-nand_select_target.patch @@ -0,0 +1,31 @@ +From 8507c2cc9e4fa402401819f44d1e8a5ef4d11d8b Mon Sep 17 00:00:00 2001 +From: Arseniy Krasnov +Date: Tue, 5 May 2026 11:30:30 +0300 +Subject: mtd: rawnand: fix condition in 'nand_select_target()' + +From: Arseniy Krasnov + +commit 8507c2cc9e4fa402401819f44d1e8a5ef4d11d8b upstream. + +'cs' here must be in range [0:nanddev_ntargets[. + +Cc: stable@vger.kernel.org +Fixes: 32813e288414 ("mtd: rawnand: Get rid of chip->numchips") +Signed-off-by: Arseniy Krasnov +Signed-off-by: Miquel Raynal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/nand/raw/nand_base.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/nand/raw/nand_base.c ++++ b/drivers/mtd/nand/raw/nand_base.c +@@ -175,7 +175,7 @@ void nand_select_target(struct nand_chip + * cs should always lie between 0 and nanddev_ntargets(), when that's + * not the case it's a bug and the caller should be fixed. + */ +- if (WARN_ON(cs > nanddev_ntargets(&chip->base))) ++ if (WARN_ON(cs >= nanddev_ntargets(&chip->base))) + return; + + chip->cur_cs = cs; diff --git a/queue-6.1/mtd-rawnand-pl353-fix-probe-resource-allocation.patch b/queue-6.1/mtd-rawnand-pl353-fix-probe-resource-allocation.patch new file mode 100644 index 0000000000..8a77f8a214 --- /dev/null +++ b/queue-6.1/mtd-rawnand-pl353-fix-probe-resource-allocation.patch @@ -0,0 +1,35 @@ +From 19ed11aee966d91beebdef9d32ce926474872f79 Mon Sep 17 00:00:00 2001 +From: Bastien Curutchet +Date: Tue, 26 May 2026 09:10:00 +0200 +Subject: mtd: rawnand: pl353: fix probe resource allocation + +From: Bastien Curutchet + +commit 19ed11aee966d91beebdef9d32ce926474872f79 upstream. + +During probe(), the devm_ioremap() is called with the parent device +instead of the current one. So when the module is unloaded, the register +area isn't released. + +Target the pl35x device in the devm_ioremap() instead of its parent. + +Cc: stable@vger.kernel.org +Fixes: 08d8c62164a3 ("mtd: rawnand: pl353: Add support for the ARM PL353 SMC NAND controller") +Signed-off-by: Bastien Curutchet +Signed-off-by: Miquel Raynal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/nand/raw/pl35x-nand-controller.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/nand/raw/pl35x-nand-controller.c ++++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c +@@ -1155,7 +1155,7 @@ static int pl35x_nand_probe(struct platf + nfc->controller.ops = &pl35x_nandc_ops; + INIT_LIST_HEAD(&nfc->chips); + +- nfc->conf_regs = devm_ioremap_resource(&smc_amba->dev, &smc_amba->res); ++ nfc->conf_regs = devm_ioremap_resource(nfc->dev, &smc_amba->res); + if (IS_ERR(nfc->conf_regs)) + return PTR_ERR(nfc->conf_regs); + diff --git a/queue-6.1/mtd-slram-remove-failed-entries-from-the-device-list.patch b/queue-6.1/mtd-slram-remove-failed-entries-from-the-device-list.patch new file mode 100644 index 0000000000..a7719099d8 --- /dev/null +++ b/queue-6.1/mtd-slram-remove-failed-entries-from-the-device-list.patch @@ -0,0 +1,85 @@ +From 36f1648644d769c496a8e47e53603e863e358d73 Mon Sep 17 00:00:00 2001 +From: Ruoyu Wang +Date: Tue, 9 Jun 2026 16:45:27 +0800 +Subject: mtd: slram: remove failed entries from the device list + +From: Ruoyu Wang + +commit 36f1648644d769c496a8e47e53603e863e358d73 upstream. + +register_device() links a new slram_mtdlist entry before allocating all +of the state needed by the entry. If a later allocation, memremap(), or +mtd_device_register() fails, the partially initialized entry remains on +the global list. A later cleanup can then dereference or free invalid +state from that failed entry. + +Unwind the partially initialized entry and clear the list tail on each +failure path after the entry has been linked. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Ruoyu Wang +Signed-off-by: Miquel Raynal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mtd/devices/slram.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +--- a/drivers/mtd/devices/slram.c ++++ b/drivers/mtd/devices/slram.c +@@ -129,6 +129,7 @@ static int slram_write(struct mtd_info * + static int register_device(char *name, unsigned long start, unsigned long length) + { + slram_mtd_list_t **curmtd; ++ int ret = -ENOMEM; + + curmtd = &slram_mtdlist; + while (*curmtd) { +@@ -155,14 +156,15 @@ static int register_device(char *name, u + + if (!(*curmtd)->mtdinfo) { + E("slram: Cannot allocate new MTD device.\n"); +- return(-ENOMEM); ++ goto err_free_list; + } + + if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start = + memremap(start, length, + MEMREMAP_WB | MEMREMAP_WT | MEMREMAP_WC))) { + E("slram: memremap failed\n"); +- return -EIO; ++ ret = -EIO; ++ goto err_free_priv; + } + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end = + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length; +@@ -183,10 +185,8 @@ static int register_device(char *name, u + + if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0)) { + E("slram: Failed to register new device\n"); +- memunmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); +- kfree((*curmtd)->mtdinfo->priv); +- kfree((*curmtd)->mtdinfo); +- return(-EAGAIN); ++ ret = -EAGAIN; ++ goto err_unmap; + } + T("slram: Registered device %s from %luKiB to %luKiB\n", name, + (start / 1024), ((start + length) / 1024)); +@@ -194,6 +194,16 @@ static int register_device(char *name, u + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start, + ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end); + return(0); ++ ++err_unmap: ++ memunmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); ++err_free_priv: ++ kfree((*curmtd)->mtdinfo->priv); ++err_free_list: ++ kfree((*curmtd)->mtdinfo); ++ kfree(*curmtd); ++ *curmtd = NULL; ++ return ret; + } + + static void unregister_devices(void) diff --git a/queue-6.1/net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch b/queue-6.1/net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch new file mode 100644 index 0000000000..e6f8997b9a --- /dev/null +++ b/queue-6.1/net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch @@ -0,0 +1,101 @@ +From 6b4f48728faa8bb514368f7eacda05565dea8696 Mon Sep 17 00:00:00 2001 +From: Vasiliy Kovalev +Date: Wed, 15 Apr 2026 18:52:37 +0300 +Subject: net/9p: fix infinite loop in p9_client_rpc on fatal signal + +From: Vasiliy Kovalev + +commit 6b4f48728faa8bb514368f7eacda05565dea8696 upstream. + +When p9_client_rpc() is called with type P9_TFLUSH and the transport +has no peer (e.g. fd transport backed by pipes with no 9p server), +a fatal signal causes an infinite loop: + + again: + err = io_wait_event_killable(req->wq, ...) + /* SIGKILL wakes the task, returns -ERESTARTSYS */ + + if (err == -ERESTARTSYS && c->status == Connected && + type == P9_TFLUSH) { + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); + goto again; + } + +clear_thread_flag() clears TIF_SIGPENDING before jumping back to +io_wait_event_killable(). signal_pending_state() checks TIF_SIGPENDING, +finds it zero, and the task goes to sleep again. The task can only wake +on the next signal delivery that calls signal_wake_up() and sets +TIF_SIGPENDING again. When that happens the loop repeats, clears +TIF_SIGPENDING, and sleeps again indefinitely. + +This is triggered in practice by coredump_wait(): when a thread in a +multi-threaded process causes a coredump (e.g. via SIGSYS from Syscall +User Dispatch), coredump_wait() sends SIGKILL to all other threads and +waits for them to call mm_release(). If one of those threads is blocked +in p9_client_rpc() over an fd transport with no peer, it enters the +P9_TFLUSH loop and never calls mm_release(), so coredump_wait() stalls +forever: + +INFO: task syz.0.18:676 blocked for more than 143 seconds. + Not tainted 6.12.77+ #1 +task:syz.0.18 state:D stack:27600 pid:676 tgid:673 ppid:630 flags:0x00000004 +Call Trace: + + context_switch kernel/sched/core.c:5344 [inline] + __schedule+0xcb4/0x5d50 kernel/sched/core.c:6724 + __schedule_loop kernel/sched/core.c:6801 [inline] + schedule+0xe5/0x350 kernel/sched/core.c:6816 + schedule_timeout+0x253/0x290 kernel/time/timer.c:2593 + do_wait_for_common kernel/sched/completion.c:95 [inline] + __wait_for_common+0x409/0x600 kernel/sched/completion.c:116 + wait_for_common kernel/sched/completion.c:127 [inline] + wait_for_completion_state+0x1d/0x40 kernel/sched/completion.c:264 + coredump_wait fs/coredump.c:448 [inline] + do_coredump+0x854/0x4350 fs/coredump.c:629 + get_signal+0x1425/0x2730 kernel/signal.c:2903 + arch_do_signal_or_restart+0x81/0x880 arch/x86/kernel/signal.c:337 + exit_to_user_mode_loop kernel/entry/common.c:111 [inline] + exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline] + __syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline] + syscall_exit_to_user_mode+0xf9/0x160 kernel/entry/common.c:218 + do_syscall_64+0x102/0x220 arch/x86/entry/common.c:84 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + +Fix: check fatal_signal_pending() before clearing TIF_SIGPENDING in the +P9_TFLUSH retry loop. At that point TIF_SIGPENDING is still set, so +fatal_signal_pending() works correctly. If a fatal signal is pending, +jump to recalc_sigpending to restore TIF_SIGPENDING and return +-ERESTARTSYS to the caller. + +The same defect is present in stable kernels back to 5.4. On those +kernels the infinite loop is broken earlier by a second SIGKILL from +the parent process (e.g. kill_and_wait() retrying after a timeout), +resulting in a zombie process and a shutdown delay rather than a +permanent D-state hang, but the underlying flaw is the same. + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 91b8534fa8f5 ("9p: make rpc code common and rework flush code") +Closes: https://syzkaller.appspot.com/bug?extid=3ce7863f8fc836a427e7 +Cc: stable@vger.kernel.org +Signed-off-by: Vasiliy Kovalev +Message-ID: <20260415155237.182891-1-kovalev@altlinux.org> +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + net/9p/client.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -716,6 +716,8 @@ again: + + if (err == -ERESTARTSYS && c->status == Connected && + type == P9_TFLUSH) { ++ if (fatal_signal_pending(current)) ++ goto recalc_sigpending; + sigpending = 1; + clear_thread_flag(TIF_SIGPENDING); + goto again; diff --git a/queue-6.1/ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch b/queue-6.1/ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch new file mode 100644 index 0000000000..fed732f692 --- /dev/null +++ b/queue-6.1/ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch @@ -0,0 +1,82 @@ +From 9b6926ac9c970ae0b2c2fe6289b16e9aa10b6a67 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Fri, 17 Apr 2026 19:33:05 -0400 +Subject: ntfs3: bound to_move in indx_insert_into_root before hdr_insert_head + +From: Michael Bommarito + +commit 9b6926ac9c970ae0b2c2fe6289b16e9aa10b6a67 upstream. + +indx_insert_into_root() promotes a full resident $INDEX_ROOT into +$INDEX_ALLOCATION and copies all non-last resident root entries into +a newly allocated INDEX_BUFFER via hdr_insert_head(). The source +byte count 'to_move' is summed from the on-disk resident entry sizes +and is independent of the destination buffer size, which comes from +root->index_block_size (via indx->index_bits). + +A crafted NTFS image that keeps a valid, full resident root but +shrinks root->index_block_size down to 512 after the root has been +populated makes hdr_insert_head() memcpy attacker-controlled resident +entry bytes past the end of the kmalloc(1u << indx->index_bits) +allocation returned by indx_new(). For a 512-byte destination and a +resident root whose non-last entries total 560 bytes, the memcpy +overruns by 120 bytes and a following memmove extends the highest +written offset to 136 bytes past the allocation. The overflow bytes +are a direct copy of on-disk entries (via kmemdup), so they are +fully attacker-controlled. + +The write is reachable from unprivileged open(O_CREAT) on a mounted +crafted NTFS image: a single sufficiently long create in a directory +whose resident root is already full forces root promotion and +triggers the copy. + +This is a controlled out-of-bounds write of 120-136 bytes past a +kmalloc(index_block_size) allocation, with attacker-controlled +content. It is a bounded adjacent-heap corruption primitive; it is +not an arbitrary-address write. Successful exploitation into a named +victim object depends on the surrounding slab layout. + +Reject the copy at the sink. The destination's INDEX_HDR already +reports hdr_total (the payload capacity of the new buffer) and +hdr_used (the bytes already consumed by the terminal END entry +installed by indx_new()); require that to_move fits in the remaining +payload before calling hdr_insert_head(). On mismatch, fail with +-EINVAL and mark the filesystem as having a detected on-disk +inconsistency, which is the same behaviour as the surrounding +validation in this function. + +Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/index.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -1730,6 +1730,22 @@ static int indx_insert_into_root(struct + hdr_used = le32_to_cpu(hdr->used); + hdr_total = le32_to_cpu(hdr->total); + ++ /* ++ * The destination INDEX_BUFFER has 'hdr_total' bytes of payload ++ * available after the header, of which 'hdr_used' are already ++ * consumed by the single terminal END entry installed by ++ * indx_new(). A crafted image can present a resident root whose ++ * non-last entries (summing to 'to_move') exceed what fits in ++ * this buffer; copying them unchecked would overrun the ++ * kmalloc(1u << indx->index_bits) allocation backing the new ++ * buffer. Reject the copy in that case. ++ */ ++ if (to_move > hdr_total - hdr_used) { ++ err = -EINVAL; ++ ntfs_set_state(sbi, NTFS_DIRTY_ERROR); ++ goto out_put_n; ++ } ++ + /* Copy root entries into new buffer. */ + hdr_insert_head(hdr, re, to_move); + diff --git a/queue-6.1/ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch b/queue-6.1/ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch new file mode 100644 index 0000000000..afc401674e --- /dev/null +++ b/queue-6.1/ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch @@ -0,0 +1,88 @@ +From 9611f644302c07d21bc8af97e3e06a3d30064253 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Sun, 17 May 2026 19:41:40 -0400 +Subject: ntfs3: cap RESTART_TABLE free-chain walker at rt->used + +From: Michael Bommarito + +commit 9611f644302c07d21bc8af97e3e06a3d30064253 upstream. + +A crafted NTFS3 disk image triggers an in-kernel infinite loop at +mount time, hanging the mounting thread and firing the soft-lockup +watchdog within ~22s on multi-CPU hosts (panic with +kernel.softlockup_panic=1). The bug is reachable from desktop USB +auto-mount on distributions where udisks2 routes the NTFS signature +to the in-tree ntfs3 driver (Arch family and an increasing fraction +of Fedora / openSUSE / RHEL deployments); CAP_SYS_ADMIN-class manual +mount elsewhere. + +check_rstbl()'s second walker iterates the free-entry singly-linked +list headed by rt->first_free with no upper bound on iteration count: + + for (off = ff; off;) { + if (off == RESTART_ENTRY_ALLOCATED) + return false; + off = le32_to_cpu(*(__le32 *)Add2Ptr(rt, off)); + if (off > ts - sizeof(__le32)) + return false; + } + +The existing guards cover three exits: end-of-list (off == 0), the +in-use marker (off == RESTART_ENTRY_ALLOCATED), and out-of-bounds +(off > ts - sizeof(__le32)). None of the three prevents an +in-bounds cycle. + +A crafted on-disk RESTART_TABLE whose free chain contains a +self-loop or A->B->A cycle whose offsets satisfy: + + - in range [sizeof(struct RESTART_TABLE), ts - sizeof(__le32)] + - (off - sizeof(struct RESTART_TABLE)) % rsize == 0 + +passes all existing guards and spins the mount-time thread forever. +Reproduced in UML by hand-forging a 2 MB NTFS3 image whose journal +RESTART_TABLE first_free = 0x18 and whose entry at offset 0x18 +stores 0x18 as its next pointer; mount of the forged image with +the in-tree ntfs3 driver never returns. + +Bound the walker by rt->used. Each entry on a legitimate free +chain is unique, and the total slot count is ne = le16_to_cpu +(rt->used). A traversal that visits more than ne slots is by +construction malformed; reject it as a corrupt RESTART_TABLE. + +After this patch, mount of the forged image returns with -EINVAL +and a log_replay failure message, and mkntfs-produced legitimate +images mount cleanly (verified in the same UML harness). + +Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") +Cc: stable@vger.kernel.org +Signed-off-by: Michael Bommarito +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/fslog.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -764,8 +764,19 @@ static bool check_rstbl(const struct RES + /* + * Walk through the list headed by the first entry to make + * sure none of the entries are currently being used. ++ * ++ * Bound traversal by ne (rt->used) to defeat a crafted on-disk ++ * cycle in the free chain. Each entry in a legitimate free ++ * list is unique, so a chain that visits more than ne slots ++ * is malformed. Without this guard, an attacker-controlled ++ * RESTART_TABLE with a self-loop or A->B->A cycle whose ++ * offsets satisfy the existing alignment + in-bounds guards ++ * spins forever at mount time. + */ +- for (off = ff; off;) { ++ for (off = ff, i = 0; off; i++) { ++ if (i > ne) ++ return false; ++ + if (off == RESTART_ENTRY_ALLOCATED) + return false; + diff --git a/queue-6.1/ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch b/queue-6.1/ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch new file mode 100644 index 0000000000..63eb5e9ee4 --- /dev/null +++ b/queue-6.1/ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch @@ -0,0 +1,35 @@ +From 7160a57192fb16d7a6fa9b7f5c7ac341d2444a89 Mon Sep 17 00:00:00 2001 +From: Tristan Madani +Date: Sat, 18 Apr 2026 13:11:18 +0000 +Subject: ntfs3: fix out-of-bounds read in decompress_lznt + +From: Tristan Madani + +commit 7160a57192fb16d7a6fa9b7f5c7ac341d2444a89 upstream. + +decompress_lznt() does not validate array index bounds before accessing +the decompression table. A corrupted NTFS3 image with invalid compressed +data can trigger an out-of-bounds read. + +Add index bounds checking to prevent the OOB access. + +Reported-by: syzbot+39b2fb0f2638669008ec@syzkaller.appspotmail.com +Cc: stable@vger.kernel.org +Signed-off-by: Tristan Madani +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/lznt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ntfs3/lznt.c ++++ b/fs/ntfs3/lznt.c +@@ -240,7 +240,7 @@ static inline ssize_t decompress_chunk(u + if (up - unc > LZNT_CHUNK_SIZE) + return -EINVAL; + /* Correct index */ +- while (unc + s_max_off[index] < up) ++ while (index < ARRAY_SIZE(s_max_off) - 1 && unc + s_max_off[index] < up) + index += 1; + + /* Check the current flag for zero. */ diff --git a/queue-6.1/ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch b/queue-6.1/ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch new file mode 100644 index 0000000000..ad194527f4 --- /dev/null +++ b/queue-6.1/ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch @@ -0,0 +1,50 @@ +From a291c77c034b7a81849ce9b71cc9ecda9e587d89 Mon Sep 17 00:00:00 2001 +From: Joseph Qi +Date: Sun, 31 May 2026 21:16:45 +0800 +Subject: ocfs2: add journal NULL check in ocfs2_checkpoint_inode() + +From: Joseph Qi + +commit a291c77c034b7a81849ce9b71cc9ecda9e587d89 upstream. + +During unmount, ocfs2_journal_shutdown() frees the journal and sets +osb->journal to NULL. Later, when VFS evicts remaining cached inodes, +ocfs2_evict_inode() -> ocfs2_clear_inode() -> ocfs2_checkpoint_inode() +-> ocfs2_ci_fully_checkpointed() dereferences osb->journal, causing a +NULL pointer dereference. + +Fix this by adding a NULL check for osb->journal in +ocfs2_checkpoint_inode(). If the journal is NULL, it has already been +fully flushed and destroyed during shutdown, so there is nothing to +checkpoint. + +Link: https://lore.kernel.org/20260531131645.3650299-1-joseph.qi@linux.alibaba.com +Reported-by: Farhad Alemi +Fixes: da5e7c87827e ("ocfs2: cleanup journal init and shutdown") +Signed-off-by: Joseph Qi +Tested-by: Farhad Alemi +Reviewed-by: Heming Zhao +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/journal.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/ocfs2/journal.h ++++ b/fs/ocfs2/journal.h +@@ -196,6 +196,9 @@ static inline void ocfs2_checkpoint_inod + if (ocfs2_mount_local(osb)) + return; + ++ if (!osb->journal) ++ return; ++ + if (!ocfs2_ci_fully_checkpointed(INODE_CACHE(inode))) { + /* WARNING: This only kicks off a single + * checkpoint. If someone races you and adds more diff --git a/queue-6.1/ocfs2-avoid-moving-extents-to-occupied-clusters.patch b/queue-6.1/ocfs2-avoid-moving-extents-to-occupied-clusters.patch new file mode 100644 index 0000000000..97250eae0b --- /dev/null +++ b/queue-6.1/ocfs2-avoid-moving-extents-to-occupied-clusters.patch @@ -0,0 +1,67 @@ +From 22920541c35a9f23f219038ba5874c843a7c4419 Mon Sep 17 00:00:00 2001 +From: Kyle Zeng +Date: Thu, 11 Jun 2026 14:35:10 -0700 +Subject: ocfs2: avoid moving extents to occupied clusters + +From: Kyle Zeng + +commit 22920541c35a9f23f219038ba5874c843a7c4419 upstream. + +For non-auto OCFS2_IOC_MOVE_EXT operations, userspace supplies a physical +me_goal. ocfs2_move_extent() initializes new_phys_cpos from that goal and +expects ocfs2_probe_alloc_group() to replace it with a free run in the +target block group. + +The probe currently leaves *phys_cpos unchanged if the scan reaches the +end of the group without finding a free run. An occupied goal at the last +bit can therefore survive the probe and be passed to +__ocfs2_move_extent(), which copies file data into a cluster still owned +by another inode before the bitmap is updated. + +When the probe does find a free run, it also subtracts move_len from the +ending bit. The start of an N-bit run ending at i is i - N + 1, so the +current calculation can report the bit immediately before the free run. + +Clear *phys_cpos before scanning and use the correct free-run start. +Callers already treat a zero result as -ENOSPC, so failed probes no longer +continue with an occupied caller-controlled goal. + +Link: https://lore.kernel.org/20260611213510.16956-1-kylebot@openai.com +Fixes: e6b5859cccfa ("Ocfs2/move_extents: helper to probe a proper region to move in an alloc group.") +Fixes: 236b9254f8d1 ("ocfs2: fix non-auto defrag path not working issue") +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Kyle Zeng +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Heming Zhao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/move_extents.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ocfs2/move_extents.c ++++ b/fs/ocfs2/move_extents.c +@@ -534,6 +534,8 @@ static void ocfs2_probe_alloc_group(stru + u32 base_cpos = ocfs2_blocks_to_clusters(inode->i_sb, + le64_to_cpu(gd->bg_blkno)); + ++ *phys_cpos = 0; ++ + for (i = base_bit; i < le16_to_cpu(gd->bg_bits); i++) { + + used = ocfs2_test_bit(i, (unsigned long *)gd->bg_bitmap); +@@ -555,7 +557,7 @@ static void ocfs2_probe_alloc_group(stru + last_free_bits++; + + if (last_free_bits == move_len) { +- i -= move_len; ++ i = i - move_len + 1; + *goal_bit = i; + *phys_cpos = base_cpos + i; + break; diff --git a/queue-6.1/ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch b/queue-6.1/ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch new file mode 100644 index 0000000000..817f89d2f9 --- /dev/null +++ b/queue-6.1/ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch @@ -0,0 +1,67 @@ +From f9ab30c96b0f00c20c6dac93681bdae3a033d229 Mon Sep 17 00:00:00 2001 +From: Ian Bridges +Date: Thu, 11 Jun 2026 09:46:38 -0500 +Subject: ocfs2: fix NULL h_transaction deref in ocfs2_assure_trans_credits + +From: Ian Bridges + +commit f9ab30c96b0f00c20c6dac93681bdae3a033d229 upstream. + +[BUG] +A direct write over unwritten extents can panic the kernel in +ocfs2_assure_trans_credits() when the journal aborts during DIO +completion. The crash is a general protection fault from a NULL pointer +dereference. + +[CAUSE] +ocfs2_dio_end_io_write() loops over a direct write's unwritten extents, +marking each written under a single journal handle. If the journal +aborts (for example after an I/O error) while the extent tree is being +updated, the handle is left aborted with its transaction pointer +cleared. The extent merge treats that failure as not critical and +reports success, so the loop keeps using the handle. +ocfs2_assure_trans_credits() reads the handle's remaining credits +without first checking whether the handle is aborted, and that read +dereferences the cleared transaction pointer. + +[FIX] +A journal abort is recorded in the handle itself, so callers are +expected to test the handle rather than rely on a returned error. +Make ocfs2_assure_trans_credits() do that, as the other ocfs2 journal +helpers already do, and return -EROFS when the handle is aborted. + +Link: https://lore.kernel.org/airKTsM1fRVN-Wj7@dev +Fixes: be346c1a6eeb ("ocfs2: fix DIO failure due to insufficient transaction credits") +Signed-off-by: Ian Bridges +Reported-by: syzbot+e9c15ff790cea6a0cfae@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e9c15ff790cea6a0cfae +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Heming Zhao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/journal.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -478,8 +478,12 @@ bail: + */ + int ocfs2_assure_trans_credits(handle_t *handle, int nblocks) + { +- int old_nblks = jbd2_handle_buffer_credits(handle); ++ int old_nblks; + ++ if (is_handle_aborted(handle)) ++ return -EROFS; ++ ++ old_nblks = jbd2_handle_buffer_credits(handle); + trace_ocfs2_assure_trans_credits(old_nblks); + if (old_nblks >= nblocks) + return 0; diff --git a/queue-6.1/ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch b/queue-6.1/ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch new file mode 100644 index 0000000000..ce62aa4607 --- /dev/null +++ b/queue-6.1/ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch @@ -0,0 +1,120 @@ +From 51407c2d249987a466416890a5c931a2354a46aa Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Tue, 19 May 2026 07:04:03 -0400 +Subject: ocfs2: reject dinodes whose i_rdev disagrees with the file type + +From: Michael Bommarito + +commit 51407c2d249987a466416890a5c931a2354a46aa upstream. + +id1.dev1.i_rdev is the device-number arm of the ocfs2_dinode id1 union. +It is only meaningful for character and block device inodes. For any +other user-visible file type the on-disk value must be zero. + +ocfs2_populate_inode() currently copies id1.dev1.i_rdev into inode->i_rdev +before the S_IFMT switch decides whether the inode is a special file. A +non-device inode with a non-zero i_rdev can therefore publish stale or +attacker-controlled device state into the in-core inode. + +System inodes legitimately use other arms of the same union, so keep the +cross-check restricted to non-system inodes. Factor that predicate into a +helper and use it in both the normal validator and online filecheck path; +filecheck reports the malformed dinode through +OCFS2_FILECHECK_ERR_INVALIDINO instead of ocfs2_error(). + +Link: https://lore.kernel.org/20260519110404.1803902-3-michael.bommarito@gmail.com +Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.") +Signed-off-by: Michael Bommarito +Assisted-by: Claude:claude-opus-4-7 +Reviewed-by: Joseph Qi +Cc: Changwei Ge +Cc: Heming Zhao +Cc: Joel Becker +Cc: Jun Piao +Cc: Junxiao Bi +Cc: Mark Fasheh +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +--- a/fs/ocfs2/inode.c ++++ b/fs/ocfs2/inode.c +@@ -73,6 +73,16 @@ static bool ocfs2_valid_inode_mode(umode + return fs_umode_to_ftype(mode) != FT_UNKNOWN; + } + ++static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di) ++{ ++ umode_t mode = le16_to_cpu(di->i_mode); ++ ++ if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL) ++ return false; ++ ++ return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0; ++} ++ + void ocfs2_set_inode_flags(struct inode *inode) + { + unsigned int flags = OCFS2_I(inode)->ip_attr; +@@ -1442,6 +1452,41 @@ int ocfs2_validate_inode_block(struct su + goto bail; + } + ++ /* ++ * id1.dev1.i_rdev is the device-number arm of the id1 union and ++ * is only meaningful for character and block device inodes. For ++ * any other regular user-visible file type the on-disk value ++ * must be zero. ocfs2_populate_inode() currently runs ++ * ++ * inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); ++ * ++ * unconditionally, before the S_IFMT switch decides whether the ++ * inode is a special file. As a result, an i_rdev value present ++ * on a non-device inode is silently published into the in-core ++ * inode; a subsequent forced re-read or in-core mode mutation ++ * (cluster peer with raw write access to the shared LUN, ++ * on-disk corruption, or a separately forged dinode) can then ++ * expose the attacker-controlled device number to ++ * init_special_inode() without ever showing an unusual i_mode ++ * at validation time. ++ * ++ * System inodes (OCFS2_SYSTEM_FL) legitimately use the bitmap1 ++ * and journal1 arms of the same union (allocator i_used / ++ * i_total counters and the journal ij_flags / ++ * ij_recovery_generation pair); those bytes are not an i_rdev ++ * and must not be checked here. Restrict the cross-check to ++ * non-system inodes, which is the full attacker-controllable ++ * surface. ++ */ ++ if (ocfs2_dinode_has_unexpected_rdev(di)) { ++ rc = ocfs2_error(sb, ++ "Invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n", ++ (unsigned long long)bh->b_blocknr, ++ le16_to_cpu(di->i_mode), ++ (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev)); ++ goto bail; ++ } ++ + if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) { + struct ocfs2_inline_data *data = &di->id2.i_data; + +@@ -1547,6 +1592,16 @@ static int ocfs2_filecheck_validate_inod + (unsigned long long)bh->b_blocknr, + le16_to_cpu(di->i_mode)); + rc = -OCFS2_FILECHECK_ERR_INVALIDINO; ++ goto bail; ++ } ++ ++ if (ocfs2_dinode_has_unexpected_rdev(di)) { ++ mlog(ML_ERROR, ++ "Filecheck: invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n", ++ (unsigned long long)bh->b_blocknr, ++ le16_to_cpu(di->i_mode), ++ (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev)); ++ rc = -OCFS2_FILECHECK_ERR_INVALIDINO; + } + + bail: diff --git a/queue-6.1/ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch b/queue-6.1/ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch new file mode 100644 index 0000000000..1d74d1c7ec --- /dev/null +++ b/queue-6.1/ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch @@ -0,0 +1,133 @@ +From 5366a017099c6a3c443be908a05f26fd72af12a1 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Tue, 19 May 2026 07:04:02 -0400 +Subject: ocfs2: reject dinodes with non-canonical i_mode type + +From: Michael Bommarito + +commit 5366a017099c6a3c443be908a05f26fd72af12a1 upstream. + +Patch series "ocfs2: harden inode validators against forged metadata", v2. + +This series adds three structural checks to OCFS2 dinode validation so +malformed on-disk fields are rejected before ocfs2_populate_inode() copies +them into the in-core inode. + +The checks cover: + + - i_mode values whose type bits do not name a canonical POSIX file + type; + - non-device dinodes whose id1.dev1.i_rdev field is non-zero; and + - non-inline dinodes that claim non-zero i_size while i_clusters is + zero, covering directories unconditionally and regular files on + non-sparse volumes. + +The normal read path reports these through ocfs2_error(), matching the +existing suballoc-slot, inline-data, chain-list, and refcount checks. The +online filecheck path uses the same structural predicates but keeps its +own reporting contract, returning OCFS2_FILECHECK_ERR_INVALIDINO instead +of calling ocfs2_error(). + + +This patch (of 3): + +ocfs2_validate_inode_block() currently accepts any non-zero i_mode value. +ocfs2_populate_inode() then copies that mode verbatim into inode->i_mode +and dispatches on i_mode & S_IFMT to the file/dir/symlink/special_file +iops; an unrecognised type falls through to ocfs2_special_file_iops and +init_special_inode(). + +Reject dinodes whose type bits do not name one of the seven canonical +POSIX file types. Use fs_umode_to_ftype(), the same generic file-type +conversion helper OCFS2 already uses for directory entries, so the +accepted inode type set matches the kernel file-type vocabulary instead of +open-coding a local switch. + +Apply the same structural check to the online filecheck read path. +filecheck keeps its own error namespace, so it reports malformed i_mode +through the filecheck logger and OCFS2_FILECHECK_ERR_INVALIDINO instead of +calling ocfs2_error(), but it must not allow a malformed dinode to proceed +into ocfs2_populate_inode(). + +Link: https://lore.kernel.org/20260519110404.1803902-1-michael.bommarito@gmail.com +Link: https://lore.kernel.org/20260519110404.1803902-2-michael.bommarito@gmail.com +Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.") +Signed-off-by: Michael Bommarito +Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com +Assisted-by: Claude:claude-opus-4-7 +Reviewed-by: Joseph Qi +Cc: Changwei Ge +Cc: Heming Zhao +Cc: Joel Becker +Cc: Jun Piao +Cc: Junxiao Bi +Cc: Mark Fasheh +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/inode.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +--- a/fs/ocfs2/inode.c ++++ b/fs/ocfs2/inode.c +@@ -66,7 +66,12 @@ static int ocfs2_filecheck_read_inode_bl + static int ocfs2_filecheck_validate_inode_block(struct super_block *sb, + struct buffer_head *bh); + static int ocfs2_filecheck_repair_inode_block(struct super_block *sb, +- struct buffer_head *bh); ++ struct buffer_head *bh); ++ ++static bool ocfs2_valid_inode_mode(umode_t mode) ++{ ++ return fs_umode_to_ftype(mode) != FT_UNKNOWN; ++} + + void ocfs2_set_inode_flags(struct inode *inode) + { +@@ -1419,6 +1424,24 @@ int ocfs2_validate_inode_block(struct su + goto bail; + } + ++ /* ++ * Reject dinodes whose i_mode does not name one of the seven ++ * canonical POSIX file types. ocfs2_populate_inode() copies ++ * i_mode verbatim into inode->i_mode and then dispatches via ++ * switch (mode & S_IFMT) to file/dir/symlink/special_file iops; ++ * an unrecognised type falls into ocfs2_special_file_iops with ++ * init_special_inode(), which interprets i_rdev. Constrain the ++ * type here so the dispatch only ever sees a value mkfs.ocfs2 / ++ * VFS can produce. ++ */ ++ if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) { ++ rc = ocfs2_error(sb, ++ "Invalid dinode #%llu: mode 0%o has unknown file type\n", ++ (unsigned long long)bh->b_blocknr, ++ le16_to_cpu(di->i_mode)); ++ goto bail; ++ } ++ + if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) { + struct ocfs2_inline_data *data = &di->id2.i_data; + +@@ -1515,6 +1538,15 @@ static int ocfs2_filecheck_validate_inod + (unsigned long long)bh->b_blocknr, + le32_to_cpu(di->i_fs_generation)); + rc = -OCFS2_FILECHECK_ERR_GENERATION; ++ goto bail; ++ } ++ ++ if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) { ++ mlog(ML_ERROR, ++ "Filecheck: invalid dinode #%llu: mode 0%o has unknown file type\n", ++ (unsigned long long)bh->b_blocknr, ++ le16_to_cpu(di->i_mode)); ++ rc = -OCFS2_FILECHECK_ERR_INVALIDINO; + } + + bail: +@@ -1690,4 +1722,3 @@ const struct ocfs2_caching_operations oc + .co_io_lock = ocfs2_inode_cache_io_lock, + .co_io_unlock = ocfs2_inode_cache_io_unlock, + }; +- diff --git a/queue-6.1/ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch b/queue-6.1/ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch new file mode 100644 index 0000000000..1988e3c508 --- /dev/null +++ b/queue-6.1/ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch @@ -0,0 +1,135 @@ +From 7ebc672fab7a76e1e47e0f2fc1ee48118d27fde4 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Tue, 19 May 2026 07:04:04 -0400 +Subject: ocfs2: reject non-inline dinodes with i_size and zero i_clusters + +From: Michael Bommarito + +commit 7ebc672fab7a76e1e47e0f2fc1ee48118d27fde4 upstream. + +On a volume mounted without OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, a +non-inline regular file with non-zero i_size and zero i_clusters is +structurally malformed: the extent map declares no allocated clusters yet +the size header claims content exists. Keep rejecting that shape, but +express it through a shared predicate so the same invariant is available +to normal inode reads and online filecheck. + +The same zero-cluster shape is also malformed for non-inline directories. +ocfs2 directory growth allocates backing storage before advancing i_size, +and ocfs2_dir_foreach_blk_el() later walks until ctx->pos reaches +i_size_read(inode). A forged directory dinode with a huge i_size and no +clusters would repeatedly fail on holes while advancing through the +claimed size. + +Sparse regular files remain exempt: on sparse-alloc volumes, truncate can +legitimately grow i_size without allocating clusters. System inodes and +inline-data dinodes also retain their separate storage rules. + +Mirror the check in ocfs2_filecheck_validate_inode_block() as well. +filecheck reports through its own error namespace, so malformed +size/cluster state is logged as a filecheck invalid-inode result rather +than via ocfs2_error(), but it must not proceed into +ocfs2_populate_inode(). + +Link: https://lore.kernel.org/20260519110404.1803902-4-michael.bommarito@gmail.com +Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.") +Signed-off-by: Michael Bommarito +Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com +Assisted-by: Claude:claude-opus-4-7 +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Heming Zhao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/inode.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +--- a/fs/ocfs2/inode.c ++++ b/fs/ocfs2/inode.c +@@ -83,6 +83,24 @@ static bool ocfs2_dinode_has_unexpected_ + return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0; + } + ++static bool ocfs2_dinode_has_size_without_clusters(struct super_block *sb, ++ struct ocfs2_dinode *di) ++{ ++ umode_t mode = le16_to_cpu(di->i_mode); ++ ++ if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL) ++ return false; ++ if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) ++ return false; ++ if (!le64_to_cpu(di->i_size) || le32_to_cpu(di->i_clusters)) ++ return false; ++ ++ if (S_ISDIR(mode)) ++ return true; ++ ++ return !ocfs2_sparse_alloc(OCFS2_SB(sb)) && S_ISREG(mode); ++} ++ + void ocfs2_set_inode_flags(struct inode *inode) + { + unsigned int flags = OCFS2_I(inode)->ip_attr; +@@ -1487,6 +1505,33 @@ int ocfs2_validate_inode_block(struct su + goto bail; + } + ++ /* ++ * Non-inline directories must not have i_size without allocated ++ * clusters: directory growth adds storage before advancing i_size, ++ * and readdir walks i_size block-by-block. A forged directory ++ * with zero clusters and a huge i_size would repeatedly fault on ++ * holes while advancing through the claimed size. ++ * ++ * Non-inline regular files have the same invariant on non-sparse ++ * volumes. Sparse regular files are different: truncate can ++ * legitimately grow i_size without allocating clusters, so keep ++ * the sparse-alloc carveout for S_IFREG only. System inodes and ++ * inline-data dinodes have their own storage rules. ++ */ ++ if (ocfs2_dinode_has_size_without_clusters(sb, di)) { ++ if (S_ISDIR(le16_to_cpu(di->i_mode))) ++ rc = ocfs2_error(sb, ++ "Invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n", ++ (unsigned long long)bh->b_blocknr, ++ (unsigned long long)le64_to_cpu(di->i_size)); ++ else ++ rc = ocfs2_error(sb, ++ "Invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n", ++ (unsigned long long)bh->b_blocknr, ++ (unsigned long long)le64_to_cpu(di->i_size)); ++ goto bail; ++ } ++ + if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) { + struct ocfs2_inline_data *data = &di->id2.i_data; + +@@ -1602,6 +1647,21 @@ static int ocfs2_filecheck_validate_inod + le16_to_cpu(di->i_mode), + (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev)); + rc = -OCFS2_FILECHECK_ERR_INVALIDINO; ++ goto bail; ++ } ++ ++ if (ocfs2_dinode_has_size_without_clusters(sb, di)) { ++ if (S_ISDIR(le16_to_cpu(di->i_mode))) ++ mlog(ML_ERROR, ++ "Filecheck: invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n", ++ (unsigned long long)bh->b_blocknr, ++ (unsigned long long)le64_to_cpu(di->i_size)); ++ else ++ mlog(ML_ERROR, ++ "Filecheck: invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n", ++ (unsigned long long)bh->b_blocknr, ++ (unsigned long long)le64_to_cpu(di->i_size)); ++ rc = -OCFS2_FILECHECK_ERR_INVALIDINO; + } + + bail: diff --git a/queue-6.1/ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch b/queue-6.1/ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch new file mode 100644 index 0000000000..5a19dd21ae --- /dev/null +++ b/queue-6.1/ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch @@ -0,0 +1,43 @@ +From 93c8c6ea90be9e9df8fe14048ad4e3caad0770a6 Mon Sep 17 00:00:00 2001 +From: Tristan Madani +Date: Sat, 18 Apr 2026 13:10:48 +0000 +Subject: ocfs2: use kzalloc for quota recovery bitmap allocation + +From: Tristan Madani + +commit 93c8c6ea90be9e9df8fe14048ad4e3caad0770a6 upstream. + +ocfs2 quota recovery allocates a bitmap buffer with kmalloc and does not +fully initialize it. This can lead to use of uninitialized bits during +quota recovery from a corrupted filesystem image. + +Use kzalloc instead to ensure the bitmap is zero-initialized. + +Link: https://lore.kernel.org/20260418131048.1052507-1-tristmd@gmail.com +Reported-by: syzbot+7ea0b96c4ddb49fd1a70@syzkaller.appspotmail.com +Signed-off-by: Tristan Madani +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Heming Zhao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/quota_local.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ocfs2/quota_local.c ++++ b/fs/ocfs2/quota_local.c +@@ -302,7 +302,7 @@ static int ocfs2_add_recovery_chunk(stru + if (!rc) + return -ENOMEM; + rc->rc_chunk = chunk; +- rc->rc_bitmap = kmalloc(sb->s_blocksize, GFP_NOFS); ++ rc->rc_bitmap = kzalloc(sb->s_blocksize, GFP_NOFS); + if (!rc->rc_bitmap) { + kfree(rc); + return -ENOMEM; diff --git a/queue-6.1/power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch b/queue-6.1/power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch new file mode 100644 index 0000000000..7c1feaf911 --- /dev/null +++ b/queue-6.1/power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch @@ -0,0 +1,43 @@ +From 4373cfa38ead58f980362c841b0d0bdf8c4d956c Mon Sep 17 00:00:00 2001 +From: WenTao Liang +Date: Thu, 11 Jun 2026 08:53:21 +0800 +Subject: power: supply: charger-manager: fix refcount leak in is_full_charged() + +From: WenTao Liang + +commit 4373cfa38ead58f980362c841b0d0bdf8c4d956c upstream. + +In is_full_charged(), power_supply_get_by_name() is called to +obtain a reference to the fuel_gauge power supply. If the +voltage check (uV >= desc->fullbatt_uV) succeeds, the function +returns true directly without releasing the reference, leaking +the refcount. + +Fix this by setting a flag and jumping to the out label where +power_supply_put() properly drops the reference. + +Cc: stable@vger.kernel.org +Fixes: e132fc6bb89b ("power: supply: charger-manager: Make decisions focussed on battery status") +Signed-off-by: WenTao Liang +Link: https://patch.msgid.link/20260611005322.53096-1-vulab@iscas.ac.cn +Signed-off-by: Sebastian Reichel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/charger-manager.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/power/supply/charger-manager.c ++++ b/drivers/power/supply/charger-manager.c +@@ -302,8 +302,10 @@ static bool is_full_charged(struct charg + if (cm->battery_status == POWER_SUPPLY_STATUS_FULL + && desc->fullbatt_vchkdrop_uV) + uV += desc->fullbatt_vchkdrop_uV; +- if (uV >= desc->fullbatt_uV) +- return true; ++ if (uV >= desc->fullbatt_uV) { ++ is_full = true; ++ goto out; ++ } + } + } + diff --git a/queue-6.1/power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch b/queue-6.1/power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch new file mode 100644 index 0000000000..29a02ec226 --- /dev/null +++ b/queue-6.1/power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch @@ -0,0 +1,51 @@ +From a2c14ff63e0e02e3c832385e523e9cc81301171c Mon Sep 17 00:00:00 2001 +From: Ma Ke +Date: Fri, 24 Apr 2026 09:10:13 +0800 +Subject: power: supply: cpcap-battery: Fix missing nvmem_device_put() causing reference leak +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ma Ke + +commit a2c14ff63e0e02e3c832385e523e9cc81301171c upstream. + +In cpcap_battery_detect_battery_type(), the reference to an nvmem +device obtained via nvmem_device_find() is not released with +nvmem_device_put() on the success or read-failure paths, causing a +permanent reference leak. The driver’s retry logic on subsequent +battery property reads can compound this leak, preventing the nvmem +device from ever being freed. + +Found by code review. + +Signed-off-by: Ma Ke +Cc: stable@vger.kernel.org +Fixes: fd46821e85de ("power: supply: cpcap-battery: Add battery type auto detection for mapphone devices") +Link: https://patch.msgid.link/20260424011013.879639-1-make24@iscas.ac.cn +Signed-off-by: Sebastian Reichel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/power/supply/cpcap-battery.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/power/supply/cpcap-battery.c ++++ b/drivers/power/supply/cpcap-battery.c +@@ -415,10 +415,13 @@ static void cpcap_battery_detect_battery + if (IS_ERR_OR_NULL(nvmem)) { + ddata->check_nvmem = true; + dev_info_once(ddata->dev, "Can not find battery nvmem device. Assuming generic lipo battery\n"); +- } else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) { +- battery_id = 0; +- ddata->check_nvmem = true; +- dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n"); ++ } else { ++ if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) { ++ battery_id = 0; ++ ddata->check_nvmem = true; ++ dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n"); ++ } ++ nvmem_device_put(nvmem); + } + + switch (battery_id) { diff --git a/queue-6.1/proc-only-bump-parent-nlink-when-registering-directories.patch b/queue-6.1/proc-only-bump-parent-nlink-when-registering-directories.patch new file mode 100644 index 0000000000..5bb623091f --- /dev/null +++ b/queue-6.1/proc-only-bump-parent-nlink-when-registering-directories.patch @@ -0,0 +1,90 @@ +From 16b02eb4b9b272c221255c20d34ccd5db53a3ed3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= +Date: Sat, 13 Jun 2026 21:10:05 +0000 +Subject: proc: only bump parent nlink when registering directories +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Krzysztof Wilczyński + +commit 16b02eb4b9b272c221255c20d34ccd5db53a3ed3 upstream. + +proc_register() increments the parent directory's link count for every +entry it registers, while remove_proc_entry() and remove_proc_subtree() +decrement it only when the removed entry is a directory. Regular files +thus inflate the parent's count while they exist, and leak one link +permanently on every create and remove cycle. + +For example, /proc/bus/pci/00 with twenty-two device files and no +subdirectories reports nlink 24 instead of 2, and SR-IOV VF enable +and disable cycles, each creating and removing the VF config space +entries under /proc/bus/pci/, inflate the link count of that +directory without bound. + +Before commit e06689bf5701 ("proc: change ->nlink under +proc_subdir_lock"), the increment lived in proc_mkdir_data() and +proc_create_mount_point(), and was therefore applied only to +directories. Moving it into proc_register() to bring it under +proc_subdir_lock dropped the S_ISDIR check. + +Thus, move the nlink accounting into pde_subdir_insert() and +pde_erase(), only updating it for directories in both, so the link +count is always changed together with the directory entry itself. + +Fixes: e06689bf5701 ("proc: change ->nlink under proc_subdir_lock") +Cc: stable@vger.kernel.org # v5.5+ +Signed-off-by: Krzysztof Wilczyński +Link: https://patch.msgid.link/20260613211005.921692-1-kwilczynski@kernel.org +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/generic.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/fs/proc/generic.c ++++ b/fs/proc/generic.c +@@ -112,6 +112,8 @@ static bool pde_subdir_insert(struct pro + /* Add new node and rebalance tree. */ + rb_link_node(&de->subdir_node, parent, new); + rb_insert_color(&de->subdir_node, root); ++ if (S_ISDIR(de->mode)) ++ dir->nlink++; + return true; + } + +@@ -400,7 +402,6 @@ struct proc_dir_entry *proc_register(str + write_unlock(&proc_subdir_lock); + goto out_free_inum; + } +- dir->nlink++; + write_unlock(&proc_subdir_lock); + + return dp; +@@ -699,6 +700,8 @@ static void pde_erase(struct proc_dir_en + { + rb_erase(&pde->subdir_node, &parent->subdir); + RB_CLEAR_NODE(&pde->subdir_node); ++ if (S_ISDIR(pde->mode)) ++ parent->nlink--; + } + + /* +@@ -724,8 +727,6 @@ void remove_proc_entry(const char *name, + de = NULL; + } else { + pde_erase(de, parent); +- if (S_ISDIR(de->mode)) +- parent->nlink--; + } + } + write_unlock(&proc_subdir_lock); +@@ -784,8 +785,6 @@ int remove_proc_subtree(const char *name + continue; + } + next = de->parent; +- if (S_ISDIR(de->mode)) +- next->nlink--; + write_unlock(&proc_subdir_lock); + + proc_entry_rundown(de); diff --git a/queue-6.1/riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch b/queue-6.1/riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch new file mode 100644 index 0000000000..d6230a4f3c --- /dev/null +++ b/queue-6.1/riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch @@ -0,0 +1,41 @@ +From bf4a195f063b0a0805c1417f6aad1dd32ea48f0f Mon Sep 17 00:00:00 2001 +From: Zishun Yi +Date: Sat, 6 Jun 2026 20:17:58 -0600 +Subject: riscv: cacheinfo: Fix node reference leak in populate_cache_leaves + +From: Zishun Yi + +commit bf4a195f063b0a0805c1417f6aad1dd32ea48f0f upstream. + +Currently, the while loop drops the reference to prev in each iteration. +If the loop terminates early due to a break, the final of_node_put(np) +correctly drops the reference to the current node. + +However, if the loop terminates naturally because np == NULL, calling +of_node_put(np) is a no-op. This leaves the last valid node stored in +prev without its reference dropped, resulting in a node reference leak. + +Fix this by changing the final `of_node_put(np)` to `of_node_put(prev)`. + +Fixes: 94f9bf118f1e ("RISC-V: Fix of_node_* refcount") +Cc: stable@vger.kernel.org +Assisted-by: Gemini:gemini-3.1-pro +Signed-off-by: Zishun Yi +Link: https://patch.msgid.link/20260509074040.1747800-1-vulab@iscas.ac.cn +Signed-off-by: Paul Walmsley +Signed-off-by: Greg Kroah-Hartman +--- + arch/riscv/kernel/cacheinfo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/riscv/kernel/cacheinfo.c ++++ b/arch/riscv/kernel/cacheinfo.c +@@ -141,7 +141,7 @@ int populate_cache_leaves(unsigned int c + + levels = level; + } +- of_node_put(np); ++ of_node_put(prev); + + return 0; + } diff --git a/queue-6.1/scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch b/queue-6.1/scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch new file mode 100644 index 0000000000..d597211d0f --- /dev/null +++ b/queue-6.1/scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch @@ -0,0 +1,148 @@ +From be8fcd4a8217a916344c88a4b1b84f5736dda17e Mon Sep 17 00:00:00 2001 +From: Ionut Nechita +Date: Tue, 19 May 2026 16:52:33 +0300 +Subject: scsi: sas: Skip opt_sectors when DMA reports no real optimization hint +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ionut Nechita + +commit be8fcd4a8217a916344c88a4b1b84f5736dda17e upstream. + +sas_host_setup() unconditionally sets shost->opt_sectors from +dma_opt_mapping_size(). + +When the IOMMU is disabled or in passthrough mode and no DMA ops provide +an opt_mapping_size callback, dma_opt_mapping_size() returns +min(dma_max_mapping_size(), SIZE_MAX) which equals +dma_max_mapping_size() — a hard upper bound, not an optimization hint. + +On a Dell PowerEdge R750 with mpt3sas (Broadcom SAS3816, FW 33.15.00.00) +and intel_iommu=off the following values are observed: + + dma_opt_mapping_size() = dma_max_mapping_size() (no real hint) + shost->max_sectors = 32767 + opt_sectors = min(32767, huge >> 9) = 32767 + optimal_io_size = 32767 << 9 = 16776704 + → round_down(16776704, 4096) = 16773120 + +The SAS disk (SAMSUNG MZILT800HBHQ0D3) does not report an Optimal +Transfer Length in VPD page B0, so sdkp->opt_xfer_blocks remains 0. + +sd_revalidate_disk() then uses min_not_zero(0, opt_sectors) = +opt_sectors, propagating the bogus value into the block device's +optimal_io_size (visible as OPT-IO = 16773120 in lsblk --topology). + +mkfs.xfs picks up optimal_io_size and minimum_io_size and computes: + + swidth = 16773120 / 4096 = 4095 + sunit = 8192 / 4096 = 2 + +Since 4095 % 2 != 0, XFS rejects the geometry: + + SB stripe unit sanity check failed + +This makes it impossible to create XFS filesystems (e.g. for +/var/lib/docker) during system bootstrap. + +Fix this by introducing a sas_dma_setup_opt_sectors() helper that sets +opt_sectors only when dma_opt_mapping_size() is strictly less than +dma_max_mapping_size(), indicating a genuine DMA optimization +constraint. + +The helper computes min(opt_sectors, max_sectors) first, then rounds +down to a power of two so that filesystem geometry calculations always +produce clean results. + +When the two DMA values are equal, no backend provided a real hint, so +opt_sectors stays at 0 ("no preference"). + +[mkp: implemented hch's suggestion] + +Fixes: 4cbfca5f7750 ("scsi: scsi_transport_sas: cap shost opt_sectors according to DMA optimal limit") +Cc: stable@vger.kernel.org +Reviewed-by: John Garry +Signed-off-by: Ionut Nechita +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260519135238.373784-2-ionut.nechita@windriver.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/scsi_transport_sas.c | 41 +++++++++++++++++++++++++++---- + 1 file changed, 36 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c +index d8f2377b017f..d689b9ed08a6 100644 +--- a/drivers/scsi/scsi_transport_sas.c ++++ b/drivers/scsi/scsi_transport_sas.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -220,12 +221,45 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) + * SAS host attributes + */ + ++/* ++ * Set shost->opt_sectors from the DMA optimal mapping size, but only ++ * when dma_opt_mapping_size() is strictly less than dma_max_mapping_size(), ++ * indicating a genuine optimization hint from an IOMMU or DMA backend. ++ * When the two are equal (e.g. IOMMU disabled / passthrough), no real ++ * hint exists, so leave opt_sectors at 0 to avoid bogus optimal_io_size ++ * values that break filesystem geometry (e.g. mkfs.xfs stripe alignment). ++ */ ++static void sas_dma_setup_opt_sectors(struct Scsi_Host *shost) ++{ ++ struct device *dma_dev = shost->dma_dev; ++ size_t opt = dma_opt_mapping_size(dma_dev); ++ size_t max = dma_max_mapping_size(dma_dev); ++ unsigned int opt_sectors; ++ ++ /* opt >= max means no real hint was provided by the DMA layer */ ++ if (opt >= max) ++ return; ++ ++ /* Clamp to max_sectors to avoid overflow in sector arithmetic */ ++ opt_sectors = min_t(unsigned int, opt >> SECTOR_SHIFT, ++ shost->max_sectors); ++ ++ /* Guard against zero before rounddown_pow_of_two() */ ++ if (!opt_sectors) ++ return; ++ ++ /* ++ * Round down to power-of-two so filesystem geometry calculations ++ * (e.g. XFS stripe width/unit) always produce clean divisors. ++ */ ++ shost->opt_sectors = rounddown_pow_of_two(opt_sectors); ++} ++ + static int sas_host_setup(struct transport_container *tc, struct device *dev, + struct device *cdev) + { + struct Scsi_Host *shost = dev_to_shost(dev); + struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); +- struct device *dma_dev = shost->dma_dev; + + INIT_LIST_HEAD(&sas_host->rphy_list); + mutex_init(&sas_host->lock); +@@ -237,10 +271,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, + dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", + shost->host_no); + +- if (dma_dev->dma_mask) { +- shost->opt_sectors = min_t(unsigned int, shost->max_sectors, +- dma_opt_mapping_size(dma_dev) >> SECTOR_SHIFT); +- } ++ sas_dma_setup_opt_sectors(shost); + + return 0; + } +-- +2.55.0 + diff --git a/queue-6.1/scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch b/queue-6.1/scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch new file mode 100644 index 0000000000..ce256ba936 --- /dev/null +++ b/queue-6.1/scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch @@ -0,0 +1,41 @@ +From 57db1307afb1f83d45f5ff53b93f8d040100d13e Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 13 May 2026 19:42:35 +0200 +Subject: scsi: smartpqi: Use shost_to_hba() in pqi_scan_finished() + +From: Martin Wilck + +commit 57db1307afb1f83d45f5ff53b93f8d040100d13e upstream. + +shost_to_hba() is used everywhere except to obtain pqi_ctrl_info from +shosti, except in pqi_scan_finished(), where shost_priv() is used. This +causes one pointer dereference to be missed, as shost->hostdata is a +pointer in smartpqi. Fix it. + +Fixes: 6c223761eb54 ("smartpqi: initial commit of Microsemi smartpqi driver") +Signed-off-by: Martin Wilck +Reviewed-by: Don Brace +Cc: Don Brace +Cc: storagedev@microchip.com +Cc: stable@vger.kernel.org +Reviewed-by: Hannes Reinecke +Reviewed-by: Hannes Reinecke +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260513174236.430465-2-mwilck@suse.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/smartpqi/smartpqi_init.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -2632,7 +2632,7 @@ static int pqi_scan_finished(struct Scsi + { + struct pqi_ctrl_info *ctrl_info; + +- ctrl_info = shost_priv(shost); ++ ctrl_info = shost_to_hba(shost); + + return !mutex_is_locked(&ctrl_info->scan_mutex); + } diff --git a/queue-6.1/series b/queue-6.1/series index 56d79a4906..7e8a725e3a 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -779,3 +779,35 @@ nvdimm-btt-free-arenas-on-btt_init-error-paths.patch nvdimm-btt-free-arena-sub-allocations-on-discover_arenas-error-path.patch lockd-plug-nlm_file-leak-when-nlm_do_fopen-fails.patch lockd-plug-nlm_file-refcount-leak-on-cached-nlm_do_fopen-failure.patch +mips-ip22-gio-fix-gio-device-memory-leak.patch +mips-ip22-gio-fix-kfree-of-static-object.patch +mips-ip22-gio-fix-device-reference-leak-in-probe.patch +mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch +power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch +fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch +fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch +fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch +fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch +fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch +fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch +fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch +ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch +ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch +ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch +power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch +mips-sched-fix-cpumask_offstack-memory-corruption.patch +riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch +proc-only-bump-parent-nlink-when-registering-directories.patch +mtd-slram-remove-failed-entries-from-the-device-list.patch +scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch +scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch +ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch +mtd-rawnand-pl353-fix-probe-resource-allocation.patch +net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch +mtd-rawnand-fix-condition-in-nand_select_target.patch +ocfs2-avoid-moving-extents-to-occupied-clusters.patch +ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch +ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch +ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch +ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch +ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch