]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Jul 2026 14:46:53 +0000 (16:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Jul 2026 14:46:53 +0000 (16:46 +0200)
added patches:
9p-skip-nlink-update-in-cacheless-mode-to-fix-warn_on.patch
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
mm-damon-core-make-charge_addr_from-aware-of-end-address-exclusivity.patch
mm-damon-sysfs-schemes-fix-dir-put-orders-in-access_pattern_add_dirs.patch
mm-damon-sysfs-schemes-put-stats-for-scheme_add_dirs-internal-error.patch
mm-mm_init-fix-uninitialized-struct-pages-for-zone_device.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
ntfs3-validate-split-point-offset-in-indx_insert_into_buffer.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
remoteproc-qcom-fix-leak-when-custom-dump_segments-addition-fails.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

40 files changed:
queue-6.6/9p-skip-nlink-update-in-cacheless-mode-to-fix-warn_on.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch [new file with mode: 0644]
queue-6.6/fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch [new file with mode: 0644]
queue-6.6/mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch [new file with mode: 0644]
queue-6.6/mips-ip22-gio-fix-device-reference-leak-in-probe.patch [new file with mode: 0644]
queue-6.6/mips-ip22-gio-fix-gio-device-memory-leak.patch [new file with mode: 0644]
queue-6.6/mips-ip22-gio-fix-kfree-of-static-object.patch [new file with mode: 0644]
queue-6.6/mips-sched-fix-cpumask_offstack-memory-corruption.patch [new file with mode: 0644]
queue-6.6/mm-damon-core-make-charge_addr_from-aware-of-end-address-exclusivity.patch [new file with mode: 0644]
queue-6.6/mm-damon-sysfs-schemes-fix-dir-put-orders-in-access_pattern_add_dirs.patch [new file with mode: 0644]
queue-6.6/mm-damon-sysfs-schemes-put-stats-for-scheme_add_dirs-internal-error.patch [new file with mode: 0644]
queue-6.6/mm-mm_init-fix-uninitialized-struct-pages-for-zone_device.patch [new file with mode: 0644]
queue-6.6/mtd-rawnand-fix-condition-in-nand_select_target.patch [new file with mode: 0644]
queue-6.6/mtd-rawnand-pl353-fix-probe-resource-allocation.patch [new file with mode: 0644]
queue-6.6/mtd-slram-remove-failed-entries-from-the-device-list.patch [new file with mode: 0644]
queue-6.6/net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch [new file with mode: 0644]
queue-6.6/ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch [new file with mode: 0644]
queue-6.6/ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch [new file with mode: 0644]
queue-6.6/ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch [new file with mode: 0644]
queue-6.6/ntfs3-validate-split-point-offset-in-indx_insert_into_buffer.patch [new file with mode: 0644]
queue-6.6/ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch [new file with mode: 0644]
queue-6.6/ocfs2-avoid-moving-extents-to-occupied-clusters.patch [new file with mode: 0644]
queue-6.6/ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch [new file with mode: 0644]
queue-6.6/ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch [new file with mode: 0644]
queue-6.6/ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch [new file with mode: 0644]
queue-6.6/ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch [new file with mode: 0644]
queue-6.6/ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch [new file with mode: 0644]
queue-6.6/power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch [new file with mode: 0644]
queue-6.6/power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch [new file with mode: 0644]
queue-6.6/proc-only-bump-parent-nlink-when-registering-directories.patch [new file with mode: 0644]
queue-6.6/remoteproc-qcom-fix-leak-when-custom-dump_segments-addition-fails.patch [new file with mode: 0644]
queue-6.6/riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch [new file with mode: 0644]
queue-6.6/scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch [new file with mode: 0644]
queue-6.6/scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-6.6/9p-skip-nlink-update-in-cacheless-mode-to-fix-warn_on.patch b/queue-6.6/9p-skip-nlink-update-in-cacheless-mode-to-fix-warn_on.patch
new file mode 100644 (file)
index 0000000..909895d
--- /dev/null
@@ -0,0 +1,71 @@
+From 574aa0b4799470ac814479f1138d19efe6262255 Mon Sep 17 00:00:00 2001
+From: Breno Leitao <leitao@debian.org>
+Date: Tue, 21 Apr 2026 02:41:09 -0700
+Subject: 9p: skip nlink update in cacheless mode to fix WARN_ON
+
+From: Breno Leitao <leitao@debian.org>
+
+commit 574aa0b4799470ac814479f1138d19efe6262255 upstream.
+
+v9fs_dec_count() unconditionally calls drop_nlink() on regular files,
+even when the inode's nlink is already zero. In cacheless mode the
+client refetches inode metadata from the server (the source of truth)
+on every operation, so by the time v9fs_remove() returns, the locally
+cached nlink may already reflect the post-unlink value:
+
+  1. Client initiates unlink, server processes it and sets nlink to 0
+  2. Client refetches inode metadata (nlink=0) before unlink returns
+  3. Client's v9fs_remove() completes successfully
+  4. Client calls v9fs_dec_count() which calls drop_nlink() on nlink=0
+
+This race is easily triggered under heavy unlink workloads, such as
+stress-ng's unlink stressor, producing the following warning:
+
+  WARNING: fs/inode.c:417 at drop_nlink+0x4c/0xc8
+  Call trace:
+   drop_nlink+0x4c/0xc8
+   v9fs_remove+0x1e0/0x250 [9p]
+   v9fs_vfs_unlink+0x20/0x38 [9p]
+   vfs_unlink+0x13c/0x258
+   ...
+
+In cacheless mode the server is authoritative and the inode is on its
+way out, so locally adjusting nlink buys nothing. Skip v9fs_dec_count()
+entirely when neither CACHE_META nor CACHE_LOOSE is set, which both
+avoids the warning and removes a class of nlink races (two concurrent
+unlinkers observing nlink > 0 and both calling drop_nlink()) that an
+nlink == 0 guard alone would only narrow rather than close.
+
+Fixes: ac89b2ef9b55 ("9p: don't maintain dir i_nlink if the exported fs doesn't either")
+Cc: stable@vger.kernel.org
+Suggested-by: Dominique Martinet <asmadeus@codewreck.org>
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Message-ID: <20260421-9p-v2-1-48762d294fad@debian.org>
+Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/9p/vfs_inode.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -521,10 +521,19 @@ static int v9fs_at_to_dotl_flags(int fla
+  * - ext4 (with dir_nlink feature enabled) sets nlink to 1 if a dir has more
+  *   than EXT4_LINK_MAX (65000) links.
+  *
++ * In cacheless mode the server is the source of truth for nlink and the
++ * inode is going away immediately, so locally adjusting i_nlink buys
++ * nothing and races with concurrent metadata fetches that may already
++ * have observed the post-unlink value (nlink == 0).
++ *
+  * @inode: inode whose nlink is being dropped
+  */
+ static void v9fs_dec_count(struct inode *inode)
+ {
++      struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
++
++      if (!(v9ses->cache & (CACHE_META | CACHE_LOOSE)))
++              return;
+       if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
+               drop_nlink(inode);
+ }
diff --git a/queue-6.6/fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch b/queue-6.6/fs-ntfs3-add-depth-limit-to-indx_find_buffer-to-prevent-stack-overflow.patch
new file mode 100644 (file)
index 0000000..6833838
--- /dev/null
@@ -0,0 +1,81 @@
+From 1ebd684b8f627f75bc3e03f8b2ad8400fd1f02cd Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+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 <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/index.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/fs/ntfs3/index.c
++++ b/fs/ntfs3/index.c
+@@ -2016,13 +2016,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)
+@@ -2043,7 +2051,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;
+               }
+@@ -2448,7 +2457,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.6/fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch b/queue-6.6/fs-ntfs3-bound-attr_off-in-updateresidentvalue-against-data_off.patch
new file mode 100644 (file)
index 0000000..71a95bf
--- /dev/null
@@ -0,0 +1,64 @@
+From d1570c48f49a693974d000251030370ee2e83539 Mon Sep 17 00:00:00 2001
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Date: Tue, 2 Jun 2026 15:15:47 +0200
+Subject: fs/ntfs3: bound attr_off in UpdateResidentValue against data_off
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+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 <michael.bommarito@gmail.com>
+[almaz.alexandrovich@paragon-software.com: clang-formatted the changes]
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/fslog.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -3313,6 +3313,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.6/fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch b/queue-6.6/fs-ntfs3-bound-copy_lcns-dp-page_lcns-index-in-analysis-pass.patch
new file mode 100644 (file)
index 0000000..48dc743
--- /dev/null
@@ -0,0 +1,116 @@
+From 5e7b598660cfa8e5af172cf4c65cffc126333307 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+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 <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+[almaz.alexandrovich@paragon-software.com: clang-formatted the changes,
+fixed conflicts]
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/fslog.c |   46 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 29 insertions(+), 17 deletions(-)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -3365,8 +3365,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;
+               }
+@@ -4581,22 +4581,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.6/fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch b/queue-6.6/fs-ntfs3-bound-deleteindexentryallocation-memmove-length.patch
new file mode 100644 (file)
index 0000000..fc44850
--- /dev/null
@@ -0,0 +1,74 @@
+From fc4626bb3656362de8b0ecd56605d47a19ec3518 Mon Sep 17 00:00:00 2001
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Date: Tue, 2 Jun 2026 15:21:03 +0200
+Subject: fs/ntfs3: bound DeleteIndexEntryAllocation memmove length
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+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 <michael.bommarito@gmail.com>
+[almaz.alexandrovich@paragon-software.com: clang-formatted the changes]
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/fslog.c |   16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -3574,9 +3574,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.6/fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch b/queue-6.6/fs-ntfs3-bound-ntfs_de-view.data_off-in-updaterecorddata-root-allocation.patch
new file mode 100644 (file)
index 0000000..bda7f28
--- /dev/null
@@ -0,0 +1,80 @@
+From 3e127829e57f5190f612412ece4541cb96d5ec7a Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+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 <michael.bommarito@gmail.com>
+
+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 <jhapavitra98@gmail.com>
+Closes: https://lore.kernel.org/ntfs3/20260502105008.21827-1-jhapavitra98@gmail.com/
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/fslog.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -3512,6 +3512,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;
+@@ -3718,6 +3730,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.6/fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch b/queue-6.6/fs-ntfs3-fix-syncing-wrong-inode-on-dirsync-cross-directory-rename.patch
new file mode 100644 (file)
index 0000000..b762e0d
--- /dev/null
@@ -0,0 +1,45 @@
+From 932fa0c1496286e39e14e27194c1ee7c2181629f Mon Sep 17 00:00:00 2001
+From: Zhan Xusheng <zhanxusheng1024@gmail.com>
+Date: Wed, 6 May 2026 15:55:54 +0800
+Subject: fs/ntfs3: fix syncing wrong inode on DIRSYNC cross-directory rename
+
+From: Zhan Xusheng <zhanxusheng1024@gmail.com>
+
+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 <zhanxusheng@xiaomi.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/namei.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ntfs3/namei.c
++++ b/fs/ntfs3/namei.c
+@@ -341,7 +341,7 @@ static int ntfs_rename(struct mnt_idmap
+                       ntfs_sync_inode(dir);
+               if (IS_DIRSYNC(new_dir))
+-                      ntfs_sync_inode(inode);
++                      ntfs_sync_inode(new_dir);
+       }
+       if (dir_ni != new_dir_ni)
diff --git a/queue-6.6/fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch b/queue-6.6/fs-ntfs3-validate-lcns_follow-in-log_replay-conversion.patch
new file mode 100644 (file)
index 0000000..b2d9a2c
--- /dev/null
@@ -0,0 +1,76 @@
+From 6a4c53a2e26a865565bd6a460961e8d6fcb32329 Mon Sep 17 00:00:00 2001
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Date: Mon, 1 Jun 2026 10:57:56 +0200
+Subject: fs/ntfs3: validate lcns_follow in log_replay conversion
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+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 <jhapavitra98@gmail.com>
+[almaz.alexandrovich@paragon-software.com: fixed the conflicts]
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/fslog.c |   19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+--- a/fs/ntfs3/fslog.c
++++ b/fs/ntfs3/fslog.c
+@@ -4263,13 +4263,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.6/mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch b/queue-6.6/mips-dec-ensure-32-bit-stack-location-for-o32-prom_printf.patch
new file mode 100644 (file)
index 0000000..8ae2dba
--- /dev/null
@@ -0,0 +1,123 @@
+From 5ff79e8bdc75db51e30298a75939e2308e7658e0 Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@orcam.me.uk>
+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 <macro@orcam.me.uk>
+
+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 <macro@orcam.me.uk>
+Cc: stable@vger.kernel.org # v2.6.12+
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <linux/init.h>
+ #include <linux/kernel.h>
+@@ -20,6 +20,10 @@
+ #include <asm/dec/prom.h>
++#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.6/mips-ip22-gio-fix-device-reference-leak-in-probe.patch b/queue-6.6/mips-ip22-gio-fix-device-reference-leak-in-probe.patch
new file mode 100644 (file)
index 0000000..3f604e2
--- /dev/null
@@ -0,0 +1,39 @@
+From b82930a4c5dbc5c4df39c0f93d968c239f2c6885 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 24 Apr 2026 12:28:47 +0200
+Subject: MIPS: ip22-gio: fix device reference leak in probe
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <tsbogend@alpha.franken.de>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/mips-ip22-gio-fix-gio-device-memory-leak.patch b/queue-6.6/mips-ip22-gio-fix-gio-device-memory-leak.patch
new file mode 100644 (file)
index 0000000..4504a02
--- /dev/null
@@ -0,0 +1,33 @@
+From 7de9a1b45f5a95b58145653c525c8fb80292d9ab Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 24 Apr 2026 12:28:46 +0200
+Subject: MIPS: ip22-gio: fix gio device memory leak
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <tsbogend@alpha.franken.de>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/mips-ip22-gio-fix-kfree-of-static-object.patch b/queue-6.6/mips-ip22-gio-fix-kfree-of-static-object.patch
new file mode 100644 (file)
index 0000000..0a0589d
--- /dev/null
@@ -0,0 +1,32 @@
+From c62cdd3e919bdf84c37ec46810f87cdb1736e822 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 24 Apr 2026 12:28:45 +0200
+Subject: MIPS: ip22-gio: fix kfree() of static object
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <levex@linux.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/mips-sched-fix-cpumask_offstack-memory-corruption.patch b/queue-6.6/mips-sched-fix-cpumask_offstack-memory-corruption.patch
new file mode 100644 (file)
index 0000000..6f35806
--- /dev/null
@@ -0,0 +1,94 @@
+From 98e37db4a34d3af3fb2f4648295c25b5e40b20e3 Mon Sep 17 00:00:00 2001
+From: Aaron Tomlin <atomlin@atomlin.com>
+Date: Tue, 26 May 2026 10:16:51 -0400
+Subject: mips: sched: Fix CPUMASK_OFFSTACK memory corruption
+
+From: Aaron Tomlin <atomlin@atomlin.com>
+
+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 <atomlin@atomlin.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/mm-damon-core-make-charge_addr_from-aware-of-end-address-exclusivity.patch b/queue-6.6/mm-damon-core-make-charge_addr_from-aware-of-end-address-exclusivity.patch
new file mode 100644 (file)
index 0000000..d0323c4
--- /dev/null
@@ -0,0 +1,40 @@
+From 5a2d162e22bf33eb89d53e802d0fc1ec422e19b6 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Mon, 27 Apr 2026 21:29:40 -0700
+Subject: mm/damon/core: make charge_addr_from aware of end-address exclusivity
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 5a2d162e22bf33eb89d53e802d0fc1ec422e19b6 upstream.
+
+DAMON region end address is exclusive one, but charge_addr_from is
+assigned assuming the end address is inclusive.  As a result, DAMOS action
+to next up to min_region_sz memory can be skipped.  This is quite
+negligible user impact.  But, the bug is a bug that can be very simply
+fixed.  Fix the wrong assignment to respect the exclusiveness of the
+address.
+
+The issue was discovered [1] by Sashiko.
+
+Link: https://lore.kernel.org/20260428042942.118230-1-sj@kernel.org
+Link: https://lore.kernel.org/20260428032324.115663-1-sj@kernel.org [1]
+Fixes: 50585192bc2e ("mm/damon/schemes: skip already charged targets and regions")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.16.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/damon/core.c
++++ b/mm/damon/core.c
+@@ -1003,7 +1003,7 @@ static void damos_apply_scheme(struct da
+               quota->charged_sz += sz;
+               if (quota->esz && quota->charged_sz >= quota->esz) {
+                       quota->charge_target_from = t;
+-                      quota->charge_addr_from = r->ar.end + 1;
++                      quota->charge_addr_from = r->ar.end;
+               }
+       }
+       if (s->action != DAMOS_STAT)
diff --git a/queue-6.6/mm-damon-sysfs-schemes-fix-dir-put-orders-in-access_pattern_add_dirs.patch b/queue-6.6/mm-damon-sysfs-schemes-fix-dir-put-orders-in-access_pattern_add_dirs.patch
new file mode 100644 (file)
index 0000000..f350eaa
--- /dev/null
@@ -0,0 +1,67 @@
+From d58fdbe37a829fd2e5803dd4e5a72992dd8c5368 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Wed, 17 Jun 2026 17:56:47 -0700
+Subject: mm/damon/sysfs-schemes: fix dir put orders in access_pattern_add_dirs()
+
+From: SeongJae Park <sj@kernel.org>
+
+commit d58fdbe37a829fd2e5803dd4e5a72992dd8c5368 upstream.
+
+Patch series "mm/damon/sysfs-schemes: fix wrong directories put orders in
+error paths".
+
+Error paths of damon_sysfs_access_pattern_add_dirs() and
+damon_sysfs_scheme_add_dirs() functions put references to directories in
+wrong orders.  As a result, uninitialized memory dereference and/or
+memory leak can happen.  Fix those.
+
+
+This patch (of 2):
+
+In access_pattern_add_dirs(), error handling path puts references starting
+from setup failed directories.  If the failure happpened from the initial
+allication in the setup functions, uninitialized memory dereference
+happen.  The allocation failures will not commonly happen, but the
+consequence is quite bad.  Fix the wrong reference put orders.
+
+The issue was discovered [1] by Sashiko.
+
+Link: https://lore.kernel.org/20260618005650.83868-2-sj@kernel.org
+Link: https://lore.kernel.org/20260617060005.86852-1-sj@kernel.org [1]
+Fixes: 7e84b1f8212a ("mm/damon/sysfs: support DAMON-based Operation Schemes")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.18.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/sysfs-schemes.c |    9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/mm/damon/sysfs-schemes.c
++++ b/mm/damon/sysfs-schemes.c
+@@ -1077,22 +1077,19 @@ static int damon_sysfs_access_pattern_ad
+       err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
+                       &access_pattern->sz, "sz");
+       if (err)
+-              goto put_sz_out;
++              return err;
+       err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
+                       &access_pattern->nr_accesses, "nr_accesses");
+       if (err)
+-              goto put_nr_accesses_sz_out;
++              goto put_sz_out;
+       err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
+                       &access_pattern->age, "age");
+       if (err)
+-              goto put_age_nr_accesses_sz_out;
++              goto put_nr_accesses_sz_out;
+       return 0;
+-put_age_nr_accesses_sz_out:
+-      kobject_put(&access_pattern->age->kobj);
+-      access_pattern->age = NULL;
+ put_nr_accesses_sz_out:
+       kobject_put(&access_pattern->nr_accesses->kobj);
+       access_pattern->nr_accesses = NULL;
diff --git a/queue-6.6/mm-damon-sysfs-schemes-put-stats-for-scheme_add_dirs-internal-error.patch b/queue-6.6/mm-damon-sysfs-schemes-put-stats-for-scheme_add_dirs-internal-error.patch
new file mode 100644 (file)
index 0000000..3dfb56f
--- /dev/null
@@ -0,0 +1,59 @@
+From 05ea83ee88ca70f8932906d9f2617ff996f45b50 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Wed, 17 Jun 2026 17:56:48 -0700
+Subject: mm/damon/sysfs-schemes: put stats for scheme_add_dirs() internal error
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 05ea83ee88ca70f8932906d9f2617ff996f45b50 upstream.
+
+damon_sysfs_scheme_add_dirs() setup the tried_regions directory after the
+stats directory setup is completed.  When the tried_regions directory
+setup is failed, the setup function ensures the reference for the tried
+regions directory is released.  Hence the error path should put references
+on setup succeeded directory objects, starting from the stats directory.
+However, the error path is putting the tried_regions directory instead of
+the stats directory.
+
+As a direct result, the stats directory object is leaked.  Worse yet, if
+the tried_regions directory setup failed from the initial allocation, the
+scheme->tried_regions field remains uninitialized.  The following
+kobject_put(&scheme->tried_regions->kobj) call in the error path will
+dereference the uninitialized memory.  The setup failures should not be
+common.  But once it happens, the consequence is quite bad.
+
+Fix this issue by correctly putting the stats directory instead of the
+tried_regions directory.
+
+The issue was discovered [1] by Sashiko.
+
+Link: https://lore.kernel.org/20260618005650.83868-3-sj@kernel.org
+Link: https://lore.kernel.org/20260617005223.96813-1-sj@kernel.org [1]
+Fixes: 5181b75f438d ("mm/damon/sysfs-schemes: implement schemes/tried_regions directory")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.2.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/sysfs-schemes.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/mm/damon/sysfs-schemes.c
++++ b/mm/damon/sysfs-schemes.c
+@@ -1303,12 +1303,12 @@ static int damon_sysfs_scheme_add_dirs(s
+               goto put_filters_watermarks_quotas_access_pattern_out;
+       err = damon_sysfs_scheme_set_tried_regions(scheme);
+       if (err)
+-              goto put_tried_regions_out;
++              goto put_stats_out;
+       return 0;
+-put_tried_regions_out:
+-      kobject_put(&scheme->tried_regions->kobj);
+-      scheme->tried_regions = NULL;
++put_stats_out:
++      kobject_put(&scheme->stats->kobj);
++      scheme->stats = NULL;
+ put_filters_watermarks_quotas_access_pattern_out:
+       kobject_put(&scheme->filters->kobj);
+       scheme->filters = NULL;
diff --git a/queue-6.6/mm-mm_init-fix-uninitialized-struct-pages-for-zone_device.patch b/queue-6.6/mm-mm_init-fix-uninitialized-struct-pages-for-zone_device.patch
new file mode 100644 (file)
index 0000000..9624f67
--- /dev/null
@@ -0,0 +1,73 @@
+From cd681403a87085562499d60325b7b45d3be11217 Mon Sep 17 00:00:00 2001
+From: Muchun Song <songmuchun@bytedance.com>
+Date: Tue, 28 Apr 2026 16:18:55 +0800
+Subject: mm/mm_init: fix uninitialized struct pages for ZONE_DEVICE
+
+From: Muchun Song <songmuchun@bytedance.com>
+
+commit cd681403a87085562499d60325b7b45d3be11217 upstream.
+
+If DAX memory is hotplugged into an unoccupied subsection of an early
+section, section_activate() reuses the unoptimized boot memmap.  However,
+compound_nr_pages() still assumes that vmemmap optimization is in effect
+and initializes only the reduced number of struct pages.  As a result, the
+remaining tail struct pages are left uninitialized, which can later lead
+to unexpected behavior or crashes.
+
+Fix this by treating early sections as unoptimized when calculating how
+many struct pages to initialize.
+
+Link: https://lore.kernel.org/20260428081855.1249045-7-songmuchun@bytedance.com
+Fixes: 6fd3620b3428 ("mm/page_alloc: reuse tail struct pages for compound devmaps")
+Signed-off-by: Muchun Song <songmuchun@bytedance.com>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Acked-by: Liam R. Howlett <liam@infradead.org>
+Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
+Cc: Joao Martins <joao.m.martins@oracle.com>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mm_init.c |   13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/mm/mm_init.c
++++ b/mm/mm_init.c
+@@ -1024,10 +1024,17 @@ static void __ref __init_zone_device_pag
+  * of how the sparse_vmemmap internals handle compound pages in the lack
+  * of an altmap. See vmemmap_populate_compound_pages().
+  */
+-static inline unsigned long compound_nr_pages(struct vmem_altmap *altmap,
++static inline unsigned long compound_nr_pages(unsigned long pfn,
++                                            struct vmem_altmap *altmap,
+                                             struct dev_pagemap *pgmap)
+ {
+-      if (!vmemmap_can_optimize(altmap, pgmap))
++      /*
++       * If DAX memory is hot-plugged into an unoccupied subsection
++       * of an early section, the unoptimized boot memmap is reused.
++       * See section_activate().
++       */
++      if (early_section(__pfn_to_section(pfn)) ||
++          !vmemmap_can_optimize(altmap, pgmap))
+               return pgmap_vmemmap_nr(pgmap);
+       return VMEMMAP_RESERVE_NR * (PAGE_SIZE / sizeof(struct page));
+@@ -1095,7 +1102,7 @@ void __ref memmap_init_zone_device(struc
+                       continue;
+               memmap_init_compound(page, pfn, zone_idx, nid, pgmap,
+-                                   compound_nr_pages(altmap, pgmap));
++                                   compound_nr_pages(pfn, altmap, pgmap));
+       }
+       pr_debug("%s initialised %lu pages in %ums\n", __func__,
diff --git a/queue-6.6/mtd-rawnand-fix-condition-in-nand_select_target.patch b/queue-6.6/mtd-rawnand-fix-condition-in-nand_select_target.patch
new file mode 100644 (file)
index 0000000..60e4c2f
--- /dev/null
@@ -0,0 +1,31 @@
+From 8507c2cc9e4fa402401819f44d1e8a5ef4d11d8b Mon Sep 17 00:00:00 2001
+From: Arseniy Krasnov <avkrasnov@rulkc.org>
+Date: Tue, 5 May 2026 11:30:30 +0300
+Subject: mtd: rawnand: fix condition in 'nand_select_target()'
+
+From: Arseniy Krasnov <avkrasnov@rulkc.org>
+
+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 <avkrasnov@rulkc.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/mtd-rawnand-pl353-fix-probe-resource-allocation.patch b/queue-6.6/mtd-rawnand-pl353-fix-probe-resource-allocation.patch
new file mode 100644 (file)
index 0000000..0a56db1
--- /dev/null
@@ -0,0 +1,35 @@
+From 19ed11aee966d91beebdef9d32ce926474872f79 Mon Sep 17 00:00:00 2001
+From: Bastien Curutchet <bastien.curutchet@bootlin.com>
+Date: Tue, 26 May 2026 09:10:00 +0200
+Subject: mtd: rawnand: pl353: fix probe resource allocation
+
+From: Bastien Curutchet <bastien.curutchet@bootlin.com>
+
+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 <bastien.curutchet@bootlin.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -1153,7 +1153,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.6/mtd-slram-remove-failed-entries-from-the-device-list.patch b/queue-6.6/mtd-slram-remove-failed-entries-from-the-device-list.patch
new file mode 100644 (file)
index 0000000..a771909
--- /dev/null
@@ -0,0 +1,85 @@
+From 36f1648644d769c496a8e47e53603e863e358d73 Mon Sep 17 00:00:00 2001
+From: Ruoyu Wang <ruoyuw560@gmail.com>
+Date: Tue, 9 Jun 2026 16:45:27 +0800
+Subject: mtd: slram: remove failed entries from the device list
+
+From: Ruoyu Wang <ruoyuw560@gmail.com>
+
+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 <ruoyuw560@gmail.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch b/queue-6.6/net-9p-fix-infinite-loop-in-p9_client_rpc-on-fatal-signal.patch
new file mode 100644 (file)
index 0000000..fee2949
--- /dev/null
@@ -0,0 +1,101 @@
+From 6b4f48728faa8bb514368f7eacda05565dea8696 Mon Sep 17 00:00:00 2001
+From: Vasiliy Kovalev <kovalev@altlinux.org>
+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 <kovalev@altlinux.org>
+
+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:
+ <TASK>
+ 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
+ </TASK>
+
+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 <kovalev@altlinux.org>
+Message-ID: <20260415155237.182891-1-kovalev@altlinux.org>
+Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/9p/client.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -722,6 +722,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.6/ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch b/queue-6.6/ntfs3-bound-to_move-in-indx_insert_into_root-before-hdr_insert_head.patch
new file mode 100644 (file)
index 0000000..f149977
--- /dev/null
@@ -0,0 +1,82 @@
+From 9b6926ac9c970ae0b2c2fe6289b16e9aa10b6a67 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+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 <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/index.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/ntfs3/index.c
++++ b/fs/ntfs3/index.c
+@@ -1745,6 +1745,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.6/ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch b/queue-6.6/ntfs3-cap-restart_table-free-chain-walker-at-rt-used.patch
new file mode 100644 (file)
index 0000000..afc4016
--- /dev/null
@@ -0,0 +1,88 @@
+From 9611f644302c07d21bc8af97e3e06a3d30064253 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Sun, 17 May 2026 19:41:40 -0400
+Subject: ntfs3: cap RESTART_TABLE free-chain walker at rt->used
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch b/queue-6.6/ntfs3-fix-out-of-bounds-read-in-decompress_lznt.patch
new file mode 100644 (file)
index 0000000..63eb5e9
--- /dev/null
@@ -0,0 +1,35 @@
+From 7160a57192fb16d7a6fa9b7f5c7ac341d2444a89 Mon Sep 17 00:00:00 2001
+From: Tristan Madani <tristan@talencesecurity.com>
+Date: Sat, 18 Apr 2026 13:11:18 +0000
+Subject: ntfs3: fix out-of-bounds read in decompress_lznt
+
+From: Tristan Madani <tristan@talencesecurity.com>
+
+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 <tristan@talencesecurity.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ntfs3-validate-split-point-offset-in-indx_insert_into_buffer.patch b/queue-6.6/ntfs3-validate-split-point-offset-in-indx_insert_into_buffer.patch
new file mode 100644 (file)
index 0000000..103cc19
--- /dev/null
@@ -0,0 +1,82 @@
+From f1df9d771df47aa40de6d70949c28720ae1e430d Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Fri, 17 Apr 2026 18:57:12 -0400
+Subject: ntfs3: validate split-point offset in indx_insert_into_buffer
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit f1df9d771df47aa40de6d70949c28720ae1e430d upstream.
+
+indx_insert_into_buffer() computes
+
+    used = used1 - to_copy - sp_size;
+    memmove(de_t, Add2Ptr(sp, sp_size), used - le32_to_cpu(hdr1->de_off));
+
+where sp and sp_size come from hdr_find_split().  hdr_find_split()
+walks entries by le16_to_cpu(e->size) without validating that each
+step stays within hdr->used or that the size field is at least
+sizeof(struct NTFS_DE).  index_hdr_check(), the on-load gatekeeper,
+only validates header-level fields (used, total, de_off) and does
+not walk per-entry sizes.
+
+A crafted NTFS image whose leaf INDEX_HDR reports used == total but
+contains one interior NTFS_DE with size = 0xFFF0 therefore passes
+validation, descends to indx_insert_into_buffer() through the
+ntfs_create() -> indx_insert_entry() path, and makes hdr_find_split()
+return an sp whose sp_size (0xFFF0) greatly exceeds the remaining
+bytes in the buffer.  The u32 subtraction underflows and the memmove
+count becomes a near-4-GiB value, producing an out-of-bounds kernel
+write that corrupts adjacent allocations and panics the kernel.
+
+Reproduced on 7.0.0-rc7 with UML + KASAN via a crafted image and a
+single 'touch' inside the mounted directory; crash site resolves to
+fs/ntfs3/index.c at the memmove.  Trigger requires only local mount
+of an attacker-supplied filesystem image (USB, loopback, or removable
+media auto-mount).
+
+Reject the split whenever the chosen sp plus its declared size
+already extends past hdr1->used.  This is the minimal fix; it
+preserves the existing hdr_find_split() contract and relies on the
+same out: cleanup path as the pre-existing error returns.
+
+A prior OOB read in the very same indx_insert_into_buffer() memmove
+was fixed in commit b8c44949044e ("fs/ntfs3: Fix OOB read in
+indx_insert_into_buffer") by tightening hdr_find_e(), but that fix
+does not cover the split-point size field path addressed here: sp is
+returned by hdr_find_split(), not hdr_find_e(), and the underflow is
+driven by sp->size rather than hdr->used exceeding hdr->total.
+
+Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block")
+Cc: stable@vger.kernel.org
+Reported-by: Michael Bommarito <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/index.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/fs/ntfs3/index.c
++++ b/fs/ntfs3/index.c
+@@ -1865,6 +1865,20 @@ indx_insert_into_buffer(struct ntfs_inde
+       memcpy(up_e, sp, sp_size);
+       used1 = le32_to_cpu(hdr1->used);
++
++      /*
++       * hdr_find_split does not validate per-entry sizes, so a crafted
++       * NTFS_DE whose le16 size field is out of range can place sp such
++       * that (PtrOffset(hdr1, sp) + sp_size) exceeds used1. Without this
++       * guard the u32 'used = used1 - to_copy - sp_size' underflows and
++       * the subsequent memmove count becomes a near-4-GiB value,
++       * triggering an out-of-bounds kernel write.
++       */
++      if (PtrOffset(hdr1, sp) + sp_size > used1) {
++              err = -EINVAL;
++              goto out;
++      }
++
+       hdr1_saved = kmemdup(hdr1, used1, GFP_NOFS);
+       if (!hdr1_saved) {
+               err = -ENOMEM;
diff --git a/queue-6.6/ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch b/queue-6.6/ocfs2-add-journal-null-check-in-ocfs2_checkpoint_inode.patch
new file mode 100644 (file)
index 0000000..ad19452
--- /dev/null
@@ -0,0 +1,50 @@
+From a291c77c034b7a81849ce9b71cc9ecda9e587d89 Mon Sep 17 00:00:00 2001
+From: Joseph Qi <joseph.qi@linux.alibaba.com>
+Date: Sun, 31 May 2026 21:16:45 +0800
+Subject: ocfs2: add journal NULL check in ocfs2_checkpoint_inode()
+
+From: Joseph Qi <joseph.qi@linux.alibaba.com>
+
+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 <farhad.alemi@berkeley.edu>
+Fixes: da5e7c87827e ("ocfs2: cleanup journal init and shutdown")
+Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Tested-by: Farhad Alemi <farhad.alemi@berkeley.edu>
+Reviewed-by: Heming Zhao <heming.zhao@suse.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ocfs2-avoid-moving-extents-to-occupied-clusters.patch b/queue-6.6/ocfs2-avoid-moving-extents-to-occupied-clusters.patch
new file mode 100644 (file)
index 0000000..97250ea
--- /dev/null
@@ -0,0 +1,67 @@
+From 22920541c35a9f23f219038ba5874c843a7c4419 Mon Sep 17 00:00:00 2001
+From: Kyle Zeng <kylebot@openai.com>
+Date: Thu, 11 Jun 2026 14:35:10 -0700
+Subject: ocfs2: avoid moving extents to occupied clusters
+
+From: Kyle Zeng <kylebot@openai.com>
+
+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 <kylebot@openai.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Heming Zhao <heming.zhao@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch b/queue-6.6/ocfs2-fix-null-h_transaction-deref-in-ocfs2_assure_trans_credits.patch
new file mode 100644 (file)
index 0000000..ce39e7d
--- /dev/null
@@ -0,0 +1,67 @@
+From f9ab30c96b0f00c20c6dac93681bdae3a033d229 Mon Sep 17 00:00:00 2001
+From: Ian Bridges <icb@fastmail.org>
+Date: Thu, 11 Jun 2026 09:46:38 -0500
+Subject: ocfs2: fix NULL h_transaction deref in ocfs2_assure_trans_credits
+
+From: Ian Bridges <icb@fastmail.org>
+
+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 <icb@fastmail.org>
+Reported-by: syzbot+e9c15ff790cea6a0cfae@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=e9c15ff790cea6a0cfae
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Heming Zhao <heming.zhao@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ocfs2/journal.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/fs/ocfs2/journal.c
++++ b/fs/ocfs2/journal.c
+@@ -476,8 +476,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.6/ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch b/queue-6.6/ocfs2-reject-dinodes-whose-i_rdev-disagrees-with-the-file-type.patch
new file mode 100644 (file)
index 0000000..ce62aa4
--- /dev/null
@@ -0,0 +1,120 @@
+From 51407c2d249987a466416890a5c931a2354a46aa Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Tue, 19 May 2026 07:04:03 -0400
+Subject: ocfs2: reject dinodes whose i_rdev disagrees with the file type
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+Assisted-by: Claude:claude-opus-4-7
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Heming Zhao <heming.zhao@suse.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch b/queue-6.6/ocfs2-reject-dinodes-with-non-canonical-i_mode-type.patch
new file mode 100644 (file)
index 0000000..1d74d1c
--- /dev/null
@@ -0,0 +1,133 @@
+From 5366a017099c6a3c443be908a05f26fd72af12a1 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Tue, 19 May 2026 07:04:02 -0400
+Subject: ocfs2: reject dinodes with non-canonical i_mode type
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
+Assisted-by: Claude:claude-opus-4-7
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Heming Zhao <heming.zhao@suse.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch b/queue-6.6/ocfs2-reject-non-inline-dinodes-with-i_size-and-zero-i_clusters.patch
new file mode 100644 (file)
index 0000000..1988e3c
--- /dev/null
@@ -0,0 +1,135 @@
+From 7ebc672fab7a76e1e47e0f2fc1ee48118d27fde4 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+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 <michael.bommarito@gmail.com>
+
+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 <michael.bommarito@gmail.com>
+Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
+Assisted-by: Claude:claude-opus-4-7
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Heming Zhao <heming.zhao@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch b/queue-6.6/ocfs2-use-kzalloc-for-quota-recovery-bitmap-allocation.patch
new file mode 100644 (file)
index 0000000..5a19dd2
--- /dev/null
@@ -0,0 +1,43 @@
+From 93c8c6ea90be9e9df8fe14048ad4e3caad0770a6 Mon Sep 17 00:00:00 2001
+From: Tristan Madani <tristan@talencesecurity.com>
+Date: Sat, 18 Apr 2026 13:10:48 +0000
+Subject: ocfs2: use kzalloc for quota recovery bitmap allocation
+
+From: Tristan Madani <tristan@talencesecurity.com>
+
+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 <tristan@talencesecurity.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Heming Zhao <heming.zhao@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch b/queue-6.6/power-supply-charger-manager-fix-refcount-leak-in-is_full_charged.patch
new file mode 100644 (file)
index 0000000..7c1feaf
--- /dev/null
@@ -0,0 +1,43 @@
+From 4373cfa38ead58f980362c841b0d0bdf8c4d956c Mon Sep 17 00:00:00 2001
+From: WenTao Liang <vulab@iscas.ac.cn>
+Date: Thu, 11 Jun 2026 08:53:21 +0800
+Subject: power: supply: charger-manager: fix refcount leak in is_full_charged()
+
+From: WenTao Liang <vulab@iscas.ac.cn>
+
+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 <vulab@iscas.ac.cn>
+Link: https://patch.msgid.link/20260611005322.53096-1-vulab@iscas.ac.cn
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch b/queue-6.6/power-supply-cpcap-battery-fix-missing-nvmem_device_put-causing-reference-leak.patch
new file mode 100644 (file)
index 0000000..29a02ec
--- /dev/null
@@ -0,0 +1,51 @@
+From a2c14ff63e0e02e3c832385e523e9cc81301171c Mon Sep 17 00:00:00 2001
+From: Ma Ke <make24@iscas.ac.cn>
+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 <make24@iscas.ac.cn>
+
+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 <make24@iscas.ac.cn>
+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 <sebastian.reichel@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.6/proc-only-bump-parent-nlink-when-registering-directories.patch b/queue-6.6/proc-only-bump-parent-nlink-when-registering-directories.patch
new file mode 100644 (file)
index 0000000..9b299ff
--- /dev/null
@@ -0,0 +1,90 @@
+From 16b02eb4b9b272c221255c20d34ccd5db53a3ed3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= <kwilczynski@kernel.org>
+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 <kwilczynski@kernel.org>
+
+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/<bus>, 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 <kwilczynski@kernel.org>
+Link: https://patch.msgid.link/20260613211005.921692-1-kwilczynski@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+ }
+@@ -399,7 +401,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;
+@@ -698,6 +699,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--;
+ }
+ /*
+@@ -723,8 +726,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);
+@@ -783,8 +784,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.6/remoteproc-qcom-fix-leak-when-custom-dump_segments-addition-fails.patch b/queue-6.6/remoteproc-qcom-fix-leak-when-custom-dump_segments-addition-fails.patch
new file mode 100644 (file)
index 0000000..8e69b20
--- /dev/null
@@ -0,0 +1,63 @@
+From ecf9fc18e62c58eae1ceb65dab2bccb8a724de2d Mon Sep 17 00:00:00 2001
+From: Wasim Nazir <wasim.nazir@oss.qualcomm.com>
+Date: Wed, 18 Mar 2026 17:19:16 +0530
+Subject: remoteproc: qcom: Fix leak when custom dump_segments addition fails
+
+From: Wasim Nazir <wasim.nazir@oss.qualcomm.com>
+
+commit ecf9fc18e62c58eae1ceb65dab2bccb8a724de2d upstream.
+
+Free allocated minidump_region 'name' in qcom_add_minidump_segments()
+when failing before adding the region to 'dump_segments'. Otherwise,
+the 'name' is not tracked and is never freed by qcom_minidump_cleanup().
+
+Return error when adding to 'dump_segments' fails.
+
+Cc: stable@vger.kernel.org # v5.11
+Fixes: 8ed8485c4f05 ("remoteproc: qcom: Add capability to collect minidumps")
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Wasim Nazir <wasim.nazir@oss.qualcomm.com>
+Link: https://lore.kernel.org/r/20260318-rproc-memleak-v2-1-ade70ab858f2@oss.qualcomm.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/remoteproc/qcom_common.c |   14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -108,6 +108,7 @@ static int qcom_add_minidump_segments(st
+       struct minidump_region __iomem *ptr;
+       struct minidump_region region;
+       int seg_cnt, i;
++      int ret = 0;
+       dma_addr_t da;
+       size_t size;
+       char *name;
+@@ -128,17 +129,22 @@ static int qcom_add_minidump_segments(st
+               if (le32_to_cpu(region.valid) == MINIDUMP_REGION_VALID) {
+                       name = kstrndup(region.name, MAX_REGION_NAME_LENGTH - 1, GFP_KERNEL);
+                       if (!name) {
+-                              iounmap(ptr);
+-                              return -ENOMEM;
++                              ret = -ENOMEM;
++                              break;
+                       }
+                       da = le64_to_cpu(region.address);
+                       size = le64_to_cpu(region.size);
+-                      rproc_coredump_add_custom_segment(rproc, da, size, rproc_dumpfn_t, name);
++                      ret = rproc_coredump_add_custom_segment(rproc, da, size, rproc_dumpfn_t,
++                                                              name);
++                      if (ret) {
++                              kfree(name);
++                              break;
++                      }
+               }
+       }
+       iounmap(ptr);
+-      return 0;
++      return ret;
+ }
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
diff --git a/queue-6.6/riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch b/queue-6.6/riscv-cacheinfo-fix-node-reference-leak-in-populate_cache_leaves.patch
new file mode 100644 (file)
index 0000000..dced61f
--- /dev/null
@@ -0,0 +1,41 @@
+From bf4a195f063b0a0805c1417f6aad1dd32ea48f0f Mon Sep 17 00:00:00 2001
+From: Zishun Yi <vulab@iscas.ac.cn>
+Date: Sat, 6 Jun 2026 20:17:58 -0600
+Subject: riscv: cacheinfo: Fix node reference leak in populate_cache_leaves
+
+From: Zishun Yi <vulab@iscas.ac.cn>
+
+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 <vulab@iscas.ac.cn>
+Link: https://patch.msgid.link/20260509074040.1747800-1-vulab@iscas.ac.cn
+Signed-off-by: Paul Walmsley <pjw@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -128,7 +128,7 @@ int populate_cache_leaves(unsigned int c
+                       ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
+               levels = level;
+       }
+-      of_node_put(np);
++      of_node_put(prev);
+       return 0;
+ }
diff --git a/queue-6.6/scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch b/queue-6.6/scsi-sas-skip-opt_sectors-when-dma-reports-no-real-optimization-hint.patch
new file mode 100644 (file)
index 0000000..8447dc4
--- /dev/null
@@ -0,0 +1,143 @@
+From be8fcd4a8217a916344c88a4b1b84f5736dda17e Mon Sep 17 00:00:00 2001
+From: Ionut Nechita <ionut.nechita@windriver.com>
+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 <ionut.nechita@windriver.com>
+
+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 <john.g.garry@oracle.com>
+Signed-off-by: Ionut Nechita <ionut.nechita@windriver.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260519135238.373784-2-ionut.nechita@windriver.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/scsi_transport_sas.c |   41 +++++++++++++++++++++++++++++++++-----
+ 1 file changed, 36 insertions(+), 5 deletions(-)
+
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -27,6 +27,7 @@
+ #include <linux/module.h>
+ #include <linux/jiffies.h>
+ #include <linux/err.h>
++#include <linux/log2.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/blkdev.h>
+@@ -220,12 +221,45 @@ static int sas_bsg_initialize(struct Scs
+  * 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 transpo
+               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;
+ }
diff --git a/queue-6.6/scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch b/queue-6.6/scsi-smartpqi-use-shost_to_hba-in-pqi_scan_finished.patch
new file mode 100644 (file)
index 0000000..1040f3c
--- /dev/null
@@ -0,0 +1,41 @@
+From 57db1307afb1f83d45f5ff53b93f8d040100d13e Mon Sep 17 00:00:00 2001
+From: Martin Wilck <martin.wilck@suse.com>
+Date: Wed, 13 May 2026 19:42:35 +0200
+Subject: scsi: smartpqi: Use shost_to_hba() in pqi_scan_finished()
+
+From: Martin Wilck <martin.wilck@suse.com>
+
+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 <martin.wilck@suse.com>
+Reviewed-by: Don Brace <don.brace@microchip.com>
+Cc: Don Brace <don.brace@microchip.com>
+Cc: storagedev@microchip.com
+Cc: stable@vger.kernel.org
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260513174236.430465-2-mwilck@suse.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -2613,7 +2613,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);
+ }
index 9d0e506646d83eeb73ea4b8d278c26bb63258512..eb9f9862166c0310634193b350db5ed7b7b03555 100644 (file)
@@ -968,3 +968,42 @@ sunrpc-wait-for-in-flight-tls-handshake-callback-when-cancel-loses-race.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
 sunrpc-bound-check-xdr_buf_to_bvec-stores-before-writing.patch
+remoteproc-qcom-fix-leak-when-custom-dump_segments-addition-fails.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
+mm-damon-core-make-charge_addr_from-aware-of-end-address-exclusivity.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-validate-split-point-offset-in-indx_insert_into_buffer.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
+mm-damon-sysfs-schemes-fix-dir-put-orders-in-access_pattern_add_dirs.patch
+mm-damon-sysfs-schemes-put-stats-for-scheme_add_dirs-internal-error.patch
+proc-only-bump-parent-nlink-when-registering-directories.patch
+mm-mm_init-fix-uninitialized-struct-pages-for-zone_device.patch
+mtd-slram-remove-failed-entries-from-the-device-list.patch
+9p-skip-nlink-update-in-cacheless-mode-to-fix-warn_on.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