Skip to content

Commit d41b382

Browse files
mjbommargregkh
authored andcommitted
fs/ntfs3: bound NTFS_DE view.data_off in UpdateRecordData{Root,Allocation}
commit 3e12782 upstream. In do_action()'s UpdateRecordDataRoot (fslog.c:3489) and UpdateRecordDataAllocation (fslog.c:3697) cases, the memmove destination is `Add2Ptr(e, le16_to_cpu(e->view.data_off))`, where e->view.data_off comes from an on-disk NTFS_DE inside an INDEX_ROOT or INDEX_BUFFER. Neither case validates view.data_off + dlen against e->size; the existing check_if_index_root / check_if_alloc_index helpers walk the entry chain and validate the entry's offset, but not its internal view fields. The neighbouring read sites (e.g., fs/ntfs3/index.c when iterating view entries) check view.data_off + view.data_size <= e->size. Apply the same bound at the two memmove sites. Reproduced under UML+KASAN on mainline 8d90b09e6741 via pr_warn-only probe instrumentation: with view.data_off forced to 0xFFFC, the memmove writes 32 bytes past the end of the NTFS_DE. This is similar in shape to Pavitra Jha's 2026-05-02 patch "fs/ntfs3: prevent oob in case UpdateRecordDataRoot" (<20260502105008.21827-1-jhapavitra98@gmail.com>) which proposes calling ntfs3_bad_de_range(); that helper does not exist in mainline. This patch uses inline checks. Fixes: b46acd6 ("fs/ntfs3: Add NTFS journal") Cc: stable@vger.kernel.org Reported-by: Pavitra Jha <jhapavitra98@gmail.com> Closes: https://lore.kernel.org/ntfs3/20260502105008.21827-1-jhapavitra98@gmail.com/ Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 65357a8 commit d41b382

1 file changed

Lines changed: 18 additions & 0 deletions

File tree

fs/ntfs3/fslog.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3515,6 +3515,18 @@ static int do_action(struct ntfs_log *log, struct OPEN_ATTR_ENRTY *oe,
35153515

35163516
e = Add2Ptr(attr, le16_to_cpu(lrh->attr_off));
35173517

3518+
/*
3519+
* e->view.data_off and dlen come from the on-disk
3520+
* INDEX_ROOT entry / LRH. The neighbouring read sites
3521+
* (e.g. fs/ntfs3/index.c) check that
3522+
* view.data_off + view.data_size <= e->size; mirror that
3523+
* bound here so the memmove cannot reach past the entry.
3524+
*/
3525+
if (le16_to_cpu(e->view.data_off) > le16_to_cpu(e->size) ||
3526+
le16_to_cpu(e->view.data_off) + dlen >
3527+
le16_to_cpu(e->size))
3528+
goto dirty_vol;
3529+
35183530
memmove(Add2Ptr(e, le16_to_cpu(e->view.data_off)), data, dlen);
35193531

35203532
mi->dirty = true;
@@ -3723,6 +3735,12 @@ static int do_action(struct ntfs_log *log, struct OPEN_ATTR_ENRTY *oe,
37233735
goto dirty_vol;
37243736
}
37253737

3738+
/* See UpdateRecordDataRoot for the rationale. */
3739+
if (le16_to_cpu(e->view.data_off) > le16_to_cpu(e->size) ||
3740+
le16_to_cpu(e->view.data_off) + dlen >
3741+
le16_to_cpu(e->size))
3742+
goto dirty_vol;
3743+
37263744
memmove(Add2Ptr(e, le16_to_cpu(e->view.data_off)), data, dlen);
37273745

37283746
a_dirty = true;

0 commit comments

Comments
 (0)