[PATCH v2 0/2] fs/ntfs3: fix out-of-bounds page_lcns[] access on log replay

Xiang Mei <[email protected]> Wed, 17 Jun 2026 16:13:41 -0700
Newsgroups dev.linux.lists.ntfs3,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
While mounting a crafted NTFS image, log_replay() can index a dirty page
entry's page_lcns[] array out of bounds. The array length is the on-disk
lcns_follow field, which is never validated against the space actually
available, so several replay paths read and write past the entry. There are
two independent ways the index goes out of range, so the fix is split into
two patches:

  1/2 - The entry's own lcns_follow (from the on-disk dirty page table) is
        not bounded against the entry size. check_dp_table() rejects any
        such entry once, right after check_rstbl(), so every consumer can
        trust lcns_follow as the real capacity. This closes the HotFix store
        and the v0->v1 conversion memmove:

          BUG: KASAN: slab-use-after-free in log_replay+0x55be/0xbbd0
          Read of size 8 at addr ffff88800dbb28b8 by task mount
          Call Trace:
           kasan_report+0xce/0x100
           log_replay+0x55be/0xbbd0
           ntfs_loadlog_and_replay+0x4a4/0x5c0
           ntfs_fill_super+0x2252/0x4570
           get_tree_bdev_flags+0x373/0x5f0
           vfs_get_tree+0x91/0x360
           path_mount+0x75a/0x2120
           __x64_sys_mount+0x298/0x310

  2/2 - In the copy_lcns loop and the redo shorten loop the index is driven
        by the *log record's* lcns_follow, which is checked only against the
        record length, not the target entry. dp_range_ok() bounds the run
        against the entry before each loop:

          BUG: KASAN: slab-out-of-bounds in log_replay+0xb7e0/0xbbe0
          Write of size 8 at addr ffff88800fff1518 by task mount
          Call Trace:
           kasan_report+0xce/0x100
           log_replay+0xb7e0/0xbbe0
           ntfs_loadlog_and_replay+0x4a4/0x5c0
           ntfs_fill_super+0x2252/0x4570
           get_tree_bdev_flags+0x373/0x5f0
           vfs_get_tree+0x91/0x360
           path_mount+0x75a/0x2120
           __x64_sys_mount+0x298/0x310
          The buggy address is 0 bytes to the right of a kmalloc-2k object.

Both are present since ntfs3 was first added (v5.15) and are reachable from
an unprivileged mount of a removable device on systems that allow it.

The two patches address distinct untrusted inputs (entry capacity vs. log
record count): 1/2 alone does not cover the record-driven loops fixed in
2/2. Verified with two KASAN reproducers that mount a malformed image, one
per patch:

  reproducer   without fix   1/2 only   1/2 + 2/2
  ----------   -----------   --------   ---------
  hotfix       crash         fixed      fixed
  copy_lcns    crash         crash      fixed

The reproducers and crash logs will be sent as a follow up email.

Xiang Mei (2):
  fs/ntfs3: validate dirty page table on log replay
  fs/ntfs3: bound page_lcns[] index by the log record

 fs/ntfs3/fslog.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

-- 
2.43.0