]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: fail recovery on a committed log item with no regions
authorWeiming Shi <bestswngs@gmail.com>
Thu, 2 Jul 2026 16:20:00 +0000 (09:20 -0700)
committerCarlos Maiolino <cem@kernel.org>
Wed, 8 Jul 2026 12:53:59 +0000 (14:53 +0200)
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 <xmei5@asu.edu>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/xfs/xfs_log_recover.c

index 103b2a79667b761473bf2a3d8978afb6ea411166..fdb011e6ef60011b2b90144f8c702a206e3f798d 100644 (file)
@@ -1907,6 +1907,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,