Re: ntfs3: two out-of-bounds reads in $LogFile replay (restart page resize, restart table offset)

From: Guikun Yang

Date: Sat Nov 07 2026 - 11:36:42 EST


Hi,

One more landing of the undo-pass lookup gap reported as item 3 - same
missing check, different field. The redo pass validates the
open-attribute table lookup three ways before using it; the undo pass
validates none of them.

Redo pass (fs/ntfs3/fslog.c:5105-5124):

t16 = le16_to_cpu(lrh->target_attr);
if (t16 >= bytes_per_rt(oatbl)) /* 1. bounds */
... goto out;
oe = Add2Ptr(oatbl, t16);
if (oe->next != RESTART_ENTRY_ALLOCATED_LE) /* 2. allocated */
... goto out;
oa = oe->ptr;
if (!oa) { /* 3. non-NULL */
... goto out;
}

Undo pass (fslog.c:5251):

oe = Add2Ptr(oatbl, le16_to_cpu(lrh->target_attr));
oa = oe->ptr;
t16 = le16_to_cpu(lrh->lcns_follow);
if (!t16)
goto add_allocated_vcns;
is_mapped = run_lookup_entry(oa->run1, ...);

Item 3 in my previous mail was the missing bounds check (an index past
the table reads outside the allocation). The same PoC with one field
changed - lcns_follow from 0 to 1 - selects an in-bounds but unused
entry (target_attr 0x18 points at entry 0 of a table with used=total=0,
so oe->ptr is NULL) and reaches run_lookup_entry(oa->run1, ...) with
oa == NULL:

Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
RIP: 0010:log_replay+0xabe6/0xf580 [ntfs3]
ntfs_loadlog_and_replay -> ntfs_fill_super

So one fix - mirroring all three redo-pass checks at the undo-pass
lookup, ideally in one helper shared by both - covers both landings and
the third one (in-bounds, allocated, but oe->ptr NULL) that I have not
built separately.

Both PoCs are the same four-record forged log as before, differing by
one field each; 3/3 with panic_on_warn=1, mount(2) alone, clean image
mounts fine. Unchanged in mainline as of 2026-11-07.

The reproducer bundle for items 3-5 plus this one is available on
request as a single archive - same base image, per-finding one-field
patches.

Thanks,
Guikun Yang