mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Guikun Yang <yangguikun19@qq.com>
To: Carlos Maiolino <cem@kernel.org>
Cc: "Darrick J. Wong" <djwong@kernel.org>,
	linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: xfs: XLOG_WAS_CONT_TRANS on a transaction with no buffered regions reads ri_buf[-1] - null deref Oops during mount log recovery
Date: Sun, 08 Nov 2026 12:00:00 +0800	[thread overview]
Message-ID: <tencent_9EC4DD29C8D43B8AC647292A2C35EF3B7E05@qq.com> (raw)
In-Reply-To: <c30-xfs-wascont-rideref-20261107@qq.com>

Hi,

One more from the same recovery path - this time in the inode item
handling, a different asymmetry from the two reported above.

## 6. ilf_len is used as the buffer read length without requiring
   whole filesystem blocks

xlog_recover_inode_commit_pass2() passes the logged ilf_len (a basic
block count) straight to xfs_buf_read()
(fs/xfs/xfs_inode_item_recover.c:351):

  error = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len,
                 0, &bp, &xfs_inode_buf_ops);

Nothing requires ilf_len to cover whole filesystem blocks. The
verifier, however, computes the number of inodes from the buffer
length rounded up (fs/xfs/libxfs/xfs_inode_buf.c):

  ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
  for (i = 0; i < ni; i++) {
          dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
          unlinked_ino = be32_to_cpu(dip->di_next_unlinked);
          ...

With a 512-byte block size on the log and a 4k filesystem block,
ilf_len = 1 reads a single 512-byte buffer (kmalloc-512), the rounding
produces 1 FSB * 8 inodes, and the loop walks 4096 bytes - reading
past the slab from the second inode on:

  BUG: KASAN: slab-out-of-bounds in xfs_inode_buf_verify+...
  Read of size 2 ...
   xfs_inode_buf_verify -> xfs_buf_read -> xlog_recover_inode_commit_pass2
  Allocated by: kmalloc-512 (the buffer from xfs_buf_read)

The readahead path passes ilf_len through unbounded as well
(fs/xfs/xfs_inode_item_recover.c:36,41).

9232301894 ("xfs: bound inode fork length against the fork size during
log recovery") added bounds for the logged fork regions in this same
function, but the buffer read length itself is still unchecked - the
same log record carries both fields, one is now bounded and the other
is not.

## Reproducer

The dirty-log image from a normal crash is modified in five bytes:
ilf_len in the inode log item from 32 to 1, plus the four CRC bytes of
the log record. ilf_blkno and ilf_boffset keep their original values.
The unmodified image recovers and mounts cleanly; the modified one
hits the KASAN report above at mount(2), 3/3.

## Suggested fix

The verifier is the defence layer for every caller, so bounding the
walk by what the buffer actually holds seems most robust:

  ni = XFS_BB_TO_FSB(mp, bp->b_length) * mp->m_sb.sb_inopblock;
  becomes something like
  ni = XFS_BB_TO_FSB(mp, min(bp->b_length, XFS_FSB_TO_BB(mp, 1))) * ...

or equivalently computing ni from the buffer length divided by the
inode size instead of rounding up to a filesystem block. Rejecting
non-block-aligned ilf_len before xfs_buf_read() would also work but
leaves the verifier as-is for other callers.

The reproducer (log scanner, image builder, ready-made image, serial
log) is available on request.

Thanks,
Guikun Yang


  parent reply	other threads:[~2026-11-08 10:22 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <c30-xfs-wascont-rideref-20261107@qq.com>
2026-11-07 12:00 ` Guikun Yang
     [not found] ` <c31-xfs-logged-sb-geometry-20261107@qq.com>
2026-11-08  4:00   ` Guikun Yang [this message]
     [not found] <x1-xfs-ilf-boffset-20261031@qq.com>
     [not found] ` <c34-xfs-ilf-len-oob-20261108@qq.com>
2026-11-08  6:00   ` [Bug report] xfs: unvalidated ilf_boffset in an inode log item reaches an out-of-bounds read during " Guikun Yang
2026-11-09  2:00   ` xfs: XLOG_WAS_CONT_TRANS on a transaction with no buffered regions reads ri_buf[-1] - null deref Oops during mount " Guikun Yang
     [not found]   ` <c37-xfs-ilf-size-short-region-20261109@qq.com>
2026-11-09  8:00     ` Guikun Yang
2026-11-07  2:00 Guikun Yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=tencent_9EC4DD29C8D43B8AC647292A2C35EF3B7E05@qq.com \
    --to=yangguikun19@qq.com \
    --cc=cem@kernel.org \
    --cc=djwong@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®