From: Greg Kroah-Hartman Date: Fri, 17 Jul 2026 09:34:13 +0000 (+0200) Subject: 6.12-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ab169dfdb914984b1040c02734e72a628a00dc44;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: xfs-clamp-timestamp-nanoseconds-correctly.patch xfs-don-t-wrap-around-quota-ids-in-dqiterate.patch xfs-don-t-zap-bmbt-forks-if-they-are-maxlevels-tall.patch xfs-fail-recovery-on-a-committed-log-item-with-no-regions.patch xfs-fix-null-pointer-dereference-in-tracepoint.patch xfs-fully-check-the-parent-handle-when-it-points-to-the-rootdir.patch xfs-resample-the-data-fork-mapping-after-cycling-ilock.patch xfs-set-xfarray-killable-sort-correctly.patch --- diff --git a/queue-6.12/series b/queue-6.12/series index 635d9437dc..259480629d 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -347,3 +347,11 @@ fuse-re-lock-request-before-returning-from-fuse_ref_folio.patch fuse-clear-intr_entry-in-fuse_resend-and-fuse_remove_pending_req.patch usb-gadget-f_fs-initialize-epfile-in-early-to-fix-endpoint-direction-checks.patch smb-client-reject-overlapping-data-areas-in-smb2-responses.patch +xfs-fix-null-pointer-dereference-in-tracepoint.patch +xfs-fail-recovery-on-a-committed-log-item-with-no-regions.patch +xfs-resample-the-data-fork-mapping-after-cycling-ilock.patch +xfs-don-t-wrap-around-quota-ids-in-dqiterate.patch +xfs-set-xfarray-killable-sort-correctly.patch +xfs-clamp-timestamp-nanoseconds-correctly.patch +xfs-fully-check-the-parent-handle-when-it-points-to-the-rootdir.patch +xfs-don-t-zap-bmbt-forks-if-they-are-maxlevels-tall.patch diff --git a/queue-6.12/xfs-clamp-timestamp-nanoseconds-correctly.patch b/queue-6.12/xfs-clamp-timestamp-nanoseconds-correctly.patch new file mode 100644 index 0000000000..b6d73470e2 --- /dev/null +++ b/queue-6.12/xfs-clamp-timestamp-nanoseconds-correctly.patch @@ -0,0 +1,34 @@ +From 15e38a9366b31d3d61081ead115f1dff59379e24 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 13 Jul 2026 23:07:15 -0700 +Subject: xfs: clamp timestamp nanoseconds correctly + +From: Darrick J. Wong + +commit 15e38a9366b31d3d61081ead115f1dff59379e24 upstream. + +LOLLM noticed an off-by-one error in the nsec clamping; fix that so that +we never have tv_nsec == 1e9. + +Cc: stable@vger.kernel.org # v6.8 +Fixes: 2d295fe65776d1 ("xfs: repair inode records") +Signed-off-by: "Darrick J. Wong" +Assisted-by: LOLLM # finding obvious bugs +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/inode_repair.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/scrub/inode_repair.c ++++ b/fs/xfs/scrub/inode_repair.c +@@ -1568,7 +1568,7 @@ xrep_clamp_timestamp( + struct xfs_inode *ip, + struct timespec64 *ts) + { +- ts->tv_nsec = clamp_t(long, ts->tv_nsec, 0, NSEC_PER_SEC); ++ ts->tv_nsec = clamp_t(long, ts->tv_nsec, 0, NSEC_PER_SEC - 1); + *ts = timestamp_truncate(*ts, VFS_I(ip)); + } + diff --git a/queue-6.12/xfs-don-t-wrap-around-quota-ids-in-dqiterate.patch b/queue-6.12/xfs-don-t-wrap-around-quota-ids-in-dqiterate.patch new file mode 100644 index 0000000000..38c1e19a6d --- /dev/null +++ b/queue-6.12/xfs-don-t-wrap-around-quota-ids-in-dqiterate.patch @@ -0,0 +1,36 @@ +From d766e4e5e85d829629c3ba503802fe1303d7b591 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 13 Jul 2026 23:04:55 -0700 +Subject: xfs: don't wrap around quota ids in dqiterate + +From: Darrick J. Wong + +commit d766e4e5e85d829629c3ba503802fe1303d7b591 upstream. + +LOLLM noticed that q_id is an unsigned 32-bit variable. If it happens +to be set to XFS_DQ_ID_MAX due to a filesystem that actually has a dquot +for ID_MAX, then this addition will truncate to zero and the iteration +starts over. Fix this by casting to u64. + +Cc: stable@vger.kernel.org # v6.8 +Fixes: 21d7500929c8a0 ("xfs: improve dquot iteration for scrub") +Signed-off-by: "Darrick J. Wong" +Assisted-by: LOLLM # finding obvious bugs +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/dqiterate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/scrub/dqiterate.c ++++ b/fs/xfs/scrub/dqiterate.c +@@ -205,7 +205,7 @@ xchk_dquot_iter( + if (error) + return error; + +- cursor->id = dq->q_id + 1; ++ cursor->id = (uint64_t)dq->q_id + 1; + *dqpp = dq; + return 1; + } diff --git a/queue-6.12/xfs-don-t-zap-bmbt-forks-if-they-are-maxlevels-tall.patch b/queue-6.12/xfs-don-t-zap-bmbt-forks-if-they-are-maxlevels-tall.patch new file mode 100644 index 0000000000..5381595db7 --- /dev/null +++ b/queue-6.12/xfs-don-t-zap-bmbt-forks-if-they-are-maxlevels-tall.patch @@ -0,0 +1,35 @@ +From 59c462b0f5cfa107794228051724b34ae9334168 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 13 Jul 2026 23:07:30 -0700 +Subject: xfs: don't zap bmbt forks if they are MAXLEVELS tall + +From: Darrick J. Wong + +commit 59c462b0f5cfa107794228051724b34ae9334168 upstream. + +LOLLM noticed a discrepancy between the bmbt level checks in the libxfs +bmbt code vs. the inode repair code. We do actually allow a bmbt root +that proclaims to have a height of XFS_BM_MAXLEVELS. + +Cc: stable@vger.kernel.org # v6.8 +Fixes: e744cef2060559 ("xfs: zap broken inode forks") +Signed-off-by: "Darrick J. Wong" +Assisted-by: LOLLM # finding obvious bugs +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/inode_repair.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/scrub/inode_repair.c ++++ b/fs/xfs/scrub/inode_repair.c +@@ -848,7 +848,7 @@ xrep_dinode_bad_bmbt_fork( + + if (nrecs == 0 || xfs_bmdr_space_calc(nrecs) > dfork_size) + return true; +- if (level == 0 || level >= XFS_BM_MAXLEVELS(sc->mp, whichfork)) ++ if (level == 0 || level > XFS_BM_MAXLEVELS(sc->mp, whichfork)) + return true; + + dmxr = xfs_bmdr_maxrecs(dfork_size, 0); diff --git a/queue-6.12/xfs-fail-recovery-on-a-committed-log-item-with-no-regions.patch b/queue-6.12/xfs-fail-recovery-on-a-committed-log-item-with-no-regions.patch new file mode 100644 index 0000000000..8735e4cbee --- /dev/null +++ b/queue-6.12/xfs-fail-recovery-on-a-committed-log-item-with-no-regions.patch @@ -0,0 +1,69 @@ +From 2094dab19d45c487285617b7b68913d0cc0c1211 Mon Sep 17 00:00:00 2001 +From: Weiming Shi +Date: Thu, 2 Jul 2026 09:20:00 -0700 +Subject: xfs: fail recovery on a committed log item with no regions + +From: Weiming Shi + +commit 2094dab19d45c487285617b7b68913d0cc0c1211 upstream. + +If the first op of a transaction is a bare transaction header +(len == sizeof(struct xfs_trans_header)), xlog_recover_add_to_trans() +adds an item but no region, leaving it on r_itemq with ri_cnt == 0 and +ri_buf == NULL. + +The header can be split across op records, so later ops may still add +regions; the item is only invalid if the transaction commits with none. +The runtime commit path never emits such a transaction, so this only +happens on a crafted log. It came from an AI-assisted code audit of the +recovery parser. + +xlog_recover_reorder_trans() calls ITEM_TYPE() on the item, which reads +*(unsigned short *)item->ri_buf[0].iov_base and faults on the NULL +ri_buf. Reject it there, before the commit handlers that also read +ri_buf[0]. + + KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] + RIP: 0010:xlog_recover_reorder_trans (fs/xfs/xfs_log_recover.c:1836) + xlog_recover_commit_trans (fs/xfs/xfs_log_recover.c:2043) + xlog_recover_process_data (fs/xfs/xfs_log_recover.c:2501) + xlog_do_recovery_pass (fs/xfs/xfs_log_recover.c:3244) + xlog_recover (fs/xfs/xfs_log_recover.c:3493) + xfs_log_mount (fs/xfs/xfs_log.c:618) + xfs_mountfs (fs/xfs/xfs_mount.c:1034) + xfs_fs_fill_super (fs/xfs/xfs_super.c:1938) + vfs_get_tree (fs/super.c:1695) + path_mount (fs/namespace.c:4161) + __x64_sys_mount (fs/namespace.c:4367) + +Fixes: 89cebc847729 ("xfs: validate transaction header length on log recovery") +Cc: stable@vger.kernel.org # v4.3 +Reported-by: Xiang Mei +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Weiming Shi +Reviewed-by: Christoph Hellwig +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_log_recover.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -1901,6 +1901,15 @@ xlog_recover_reorder_trans( + list_for_each_entry_safe(item, n, &sort_list, ri_list) { + enum xlog_recover_reorder fate = XLOG_REORDER_ITEM_LIST; + ++ /* a committed item with no regions has a NULL ri_buf[0] */ ++ if (!item->ri_cnt || !item->ri_buf) { ++ xfs_warn(log->l_mp, ++ "%s: committed log item has no regions", ++ __func__); ++ error = -EFSCORRUPTED; ++ break; ++ } ++ + item->ri_ops = xlog_find_item_ops(item); + if (!item->ri_ops) { + xfs_warn(log->l_mp, diff --git a/queue-6.12/xfs-fix-null-pointer-dereference-in-tracepoint.patch b/queue-6.12/xfs-fix-null-pointer-dereference-in-tracepoint.patch new file mode 100644 index 0000000000..78d24fc2f8 --- /dev/null +++ b/queue-6.12/xfs-fix-null-pointer-dereference-in-tracepoint.patch @@ -0,0 +1,34 @@ +From 9202ee546b0cd71004eed7598546efe4660097da Mon Sep 17 00:00:00 2001 +From: Andrey Albershteyn +Date: Thu, 9 Jul 2026 17:24:07 +0200 +Subject: xfs: fix null pointer dereference in tracepoint + +From: Andrey Albershteyn + +commit 9202ee546b0cd71004eed7598546efe4660097da upstream. + +If dfp is not NULL we exit early here, when dfp is NULL it's allocated +in xfs_defer_alloc() but not assigned. The tracepoint tries to +dereference members of dfp struct. + +Signed-off-by: Andrey Albershteyn +Cc: stable@vger.kernel.org # v6.8 +Fixes: 3f3cec031099c3 ("xfs: force small EFIs for reaping btree extents") +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_defer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/libxfs/xfs_defer.c ++++ b/fs/xfs/libxfs/xfs_defer.c +@@ -872,7 +872,7 @@ xfs_defer_add_barrier( + if (dfp) + return; + +- xfs_defer_alloc(&tp->t_dfops, &xfs_barrier_defer_type); ++ dfp = xfs_defer_alloc(&tp->t_dfops, &xfs_barrier_defer_type); + + trace_xfs_defer_add_item(tp->t_mountp, dfp, NULL); + } diff --git a/queue-6.12/xfs-fully-check-the-parent-handle-when-it-points-to-the-rootdir.patch b/queue-6.12/xfs-fully-check-the-parent-handle-when-it-points-to-the-rootdir.patch new file mode 100644 index 0000000000..695e964a65 --- /dev/null +++ b/queue-6.12/xfs-fully-check-the-parent-handle-when-it-points-to-the-rootdir.patch @@ -0,0 +1,57 @@ +From ba150ce63453ccd74bae1404c1dfedbd01ecfd55 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 13 Jul 2026 23:06:59 -0700 +Subject: xfs: fully check the parent handle when it points to the rootdir + +From: Darrick J. Wong + +commit ba150ce63453ccd74bae1404c1dfedbd01ecfd55 upstream. + +LOLLM noticed that the directory tree path checking declares the path to +be ok if the inumber in the parent pointer reaches the root directory. +Unfortunately, it neglects to check that the generation is correct. Fix +that by moving the generation check up. + +Cc: stable@vger.kernel.org # v6.10 +Fixes: 928b721a11789a ("xfs: teach online scrub to find directory tree structure problems") +Signed-off-by: "Darrick J. Wong" +Assisted-by: LOLLM # finding obvious bugs +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/dirtree.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/fs/xfs/scrub/dirtree.c ++++ b/fs/xfs/scrub/dirtree.c +@@ -382,6 +382,14 @@ xchk_dirpath_step_up( + goto out_scanlock; + } + ++ /* The handle encoded in the parent pointer must match. */ ++ if (VFS_I(dp)->i_generation != be32_to_cpu(dl->pptr_rec.p_gen)) { ++ trace_xchk_dirpath_badgen(dl->sc, dp, path->path_nr, ++ path->nr_steps, &dl->xname, &dl->pptr_rec); ++ error = -EFSCORRUPTED; ++ goto out_scanlock; ++ } ++ + /* We've reached the root directory; the path is ok. */ + if (parent_ino == dl->root_ino) { + xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_OK); +@@ -410,14 +418,6 @@ xchk_dirpath_step_up( + goto out_scanlock; + } + +- /* The handle encoded in the parent pointer must match. */ +- if (VFS_I(dp)->i_generation != be32_to_cpu(dl->pptr_rec.p_gen)) { +- trace_xchk_dirpath_badgen(dl->sc, dp, path->path_nr, +- path->nr_steps, &dl->xname, &dl->pptr_rec); +- error = -EFSCORRUPTED; +- goto out_scanlock; +- } +- + /* Parent pointer must point up to a directory. */ + if (!S_ISDIR(VFS_I(dp)->i_mode)) { + trace_xchk_dirpath_nondir_parent(dl->sc, dp, path->path_nr, diff --git a/queue-6.12/xfs-resample-the-data-fork-mapping-after-cycling-ilock.patch b/queue-6.12/xfs-resample-the-data-fork-mapping-after-cycling-ilock.patch new file mode 100644 index 0000000000..7e804376a3 --- /dev/null +++ b/queue-6.12/xfs-resample-the-data-fork-mapping-after-cycling-ilock.patch @@ -0,0 +1,100 @@ +From 2f4acd0fcd862e22eab45690ec2c08c80b6ef2e7 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 13 Jul 2026 23:03:44 -0700 +Subject: xfs: resample the data fork mapping after cycling ILOCK + +From: Darrick J. Wong + +commit 2f4acd0fcd862e22eab45690ec2c08c80b6ef2e7 upstream. + +xfs_reflink_fill_{cow_hole,delalloc} are both presented with an inode, +a data fork mapping, and a cow fork mapping. Unfortunately, these two +helpers cycle the ILOCK to grab a transaction, which means that the +mappings are stale as soon as we reacquire the ILOCK. Currently we +refresh the cow fork mapping by re-calling xfs_find_trim_cow_extent, but +we don't refresh the data fork mapping beforehand, which means that the +xfs_bmap_trim_cow in that function queries the refcount btree about the +wrong physical blocks and returns an inaccurate value in *shared. + +If *shared is now false, the directio write proceeds with a stale data +fork mapping. Fix this by querying the data fork mapping if the +sequence counter changes across the ILOCK cycle. + +Cc: hch@lst.de +Cc: stable@vger.kernel.org # v4.11 +Fixes: 3c68d44a2b49a0 ("xfs: allocate direct I/O COW blocks in iomap_begin") +Signed-off-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Reviewed-by: Carlos Maiolino +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_reflink.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/fs/xfs/xfs_reflink.c ++++ b/fs/xfs/xfs_reflink.c +@@ -390,6 +390,7 @@ xfs_reflink_fill_cow_hole( + struct xfs_trans *tp; + xfs_filblks_t resaligned; + xfs_extlen_t resblks; ++ unsigned int seq_before = READ_ONCE(ip->i_df.if_seq); + int nimaps; + int error; + bool found; +@@ -408,6 +409,22 @@ xfs_reflink_fill_cow_hole( + + *lockmode = XFS_ILOCK_EXCL; + ++ /* ++ * The data fork mapping may have changed while we dropped the ILOCK ++ * (a racing O_DIRECT writer under IOLOCK_SHARED can complete a full ++ * CoW cycle including xfs_reflink_end_cow(), which remaps this offset ++ * and drops the refcount of the old shared block). Re-read it so the ++ * shared-status recheck below and the caller's in-place iomap both ++ * operate on the current mapping rather than a stale physical block. ++ */ ++ if (seq_before != READ_ONCE(ip->i_df.if_seq)) { ++ nimaps = 1; ++ error = xfs_bmapi_read(ip, imap->br_startoff, ++ imap->br_blockcount, imap, &nimaps, 0); ++ if (error) ++ goto out_trans_cancel; ++ } ++ + error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); + if (error || !*shared) + goto out_trans_cancel; +@@ -454,6 +471,8 @@ xfs_reflink_fill_delalloc( + bool found; + + do { ++ unsigned int seq_before = READ_ONCE(ip->i_df.if_seq); ++ + xfs_iunlock(ip, *lockmode); + *lockmode = 0; + +@@ -464,6 +483,23 @@ xfs_reflink_fill_delalloc( + + *lockmode = XFS_ILOCK_EXCL; + ++ /* ++ * The data fork mapping may have changed while we dropped the ++ * ILOCK (a racing O_DIRECT writer under IOLOCK_SHARED can ++ * complete a full CoW cycle including xfs_reflink_end_cow(), ++ * which remaps this offset and drops the refcount of the old ++ * shared block). Re-read it so the shared-status recheck ++ * below and the caller's in-place iomap both operate on the ++ * current mapping rather than a stale physical block. ++ */ ++ if (seq_before != READ_ONCE(ip->i_df.if_seq)) { ++ nimaps = 1; ++ error = xfs_bmapi_read(ip, imap->br_startoff, ++ imap->br_blockcount, imap, &nimaps, 0); ++ if (error) ++ goto out_trans_cancel; ++ } ++ + error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, + &found); + if (error || !*shared) diff --git a/queue-6.12/xfs-set-xfarray-killable-sort-correctly.patch b/queue-6.12/xfs-set-xfarray-killable-sort-correctly.patch new file mode 100644 index 0000000000..379bb3bd64 --- /dev/null +++ b/queue-6.12/xfs-set-xfarray-killable-sort-correctly.patch @@ -0,0 +1,66 @@ +From 540ddc626245f12f56326ee0c1601f71ebb41d64 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 13 Jul 2026 23:06:12 -0700 +Subject: xfs: set xfarray killable sort correctly + +From: Darrick J. Wong + +commit 540ddc626245f12f56326ee0c1601f71ebb41d64 upstream. + +LOLLM noticed that we *disable* interruptible sorts when the KILLABLE +flag is set. This is backwards. Fix the incorrect logic, and rename +the variable to make the connection more obvious. + +Cc: stable@vger.kernel.org # v6.10 +Fixes: 271557de7cbfde ("xfs: reduce the rate of cond_resched calls inside scrub") +Signed-off-by: "Darrick J. Wong" +Assisted-by: LOLLM # finding obvious bugs +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/scrub.h | 6 +++--- + fs/xfs/scrub/xfarray.c | 3 +-- + 2 files changed, 4 insertions(+), 5 deletions(-) + +--- a/fs/xfs/scrub/scrub.h ++++ b/fs/xfs/scrub/scrub.h +@@ -11,7 +11,7 @@ struct xfs_scrub; + struct xchk_relax { + unsigned long next_resched; + unsigned int resched_nr; +- bool interruptible; ++ bool killable; + }; + + /* Yield to the scheduler at most 10x per second. */ +@@ -21,7 +21,7 @@ struct xchk_relax { + (struct xchk_relax){ \ + .next_resched = XCHK_RELAX_NEXT, \ + .resched_nr = 0, \ +- .interruptible = true, \ ++ .killable = true, \ + } + + /* +@@ -45,7 +45,7 @@ static inline int xchk_maybe_relax(struc + widget->next_resched = XCHK_RELAX_NEXT; + } + +- if (widget->interruptible && fatal_signal_pending(current)) ++ if (widget->killable && fatal_signal_pending(current)) + return -EINTR; + + return 0; +--- a/fs/xfs/scrub/xfarray.c ++++ b/fs/xfs/scrub/xfarray.c +@@ -487,8 +487,7 @@ xfarray_sortinfo_alloc( + xfarray_sortinfo_lo(si)[0] = 0; + xfarray_sortinfo_hi(si)[0] = array->nr - 1; + si->relax = INIT_XCHK_RELAX; +- if (flags & XFARRAY_SORT_KILLABLE) +- si->relax.interruptible = false; ++ si->relax.killable = !!(flags & XFARRAY_SORT_KILLABLE); + + trace_xfarray_sort(si, nr_bytes); + *infop = si;