* [PATCH ntfs] fs/ntfs3: fix out-of-bounds read in check_log_rec()
@ 2026-09-29 7:24 Xue Boyang
0 siblings, 0 replies; only message in thread
From: Xue Boyang @ 2026-09-29 7:24 UTC (permalink / raw)
To: almaz.alexandrovich; +Cc: ntfs3, linux-kernel, Xue Boyang
During $LogFile replay, check_log_rec() validates the alignment of
redo_off/undo_off and that the record holds the fixed header, but never
checks that the declared data window fits inside the record:
if (le16_to_cpu(lr->redo_off) & 7)
return false;
if (le16_to_cpu(lr->undo_off) & 7)
return false;
...
check_length:
if (bytes < lrh_length(lr))
return false;
Every consumer of the window reads from (lrh + redo_off, redo_len) with
no source-side bound: the analysis-pass OpenNonresidentAttribute handler
memcpy()s bytes_per_attr_entry from lrh + redo_off into the open
attribute table, and the redo/undo passes feed the same pair to all
do_action() memmove()/memcpy() sources. Since redo_off is a raw u16
taken from disk, a crafted log record makes the kernel read up to ~64K
past the kmalloc(log->page_size) page buffer holding the record.
The destination side of do_action()'s UpdateNonresidentValue already
applies the equivalent bound (lco >= cbo + roff + dlen), so the
invariant exists at other call sites; check_log_rec() is the omission.
Reproduced deterministically on rw mount of a hand-crafted $LogFile
(QEMU x86_64, v7.3-rc4-0094-gf49a343b305c, CONFIG_KASAN=y): a single
RCRD page with an LfsClientRestart record followed by an
OpenNonresidentAttribute record with redo_off=0xFFF8, redo_len=0x28
triggers the read on every mount, no race. Multiple records with
different redo_off values were verified to select the read offset.
The KASAN report of the triggering record:
BUG: KASAN: use-after-free in log_replay.cold+0x3b12/0x4251
Read of size 40 at addr ffff88800420a028 by task mount/71
...
__asan_memcpy+0x23/0x60
log_replay.cold+0x3b12/0x4251
ntfs_loadlog_and_replay+0x2cb/0x300
ntfs_fill_super+0x1375/0x22d0
...
Both operands are u16 so the sum cannot overflow u32; with the checks
in place every consumer reads inside the record buffer itself.
Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS3 filesystem")
Assisted-by: GLM:zhipu-coding-plan/glm-5.3
Signed-off-by: Xue Boyang <fuchen.dust@gmail.com>
---
fs/ntfs3/fslog.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c
index ed50c1d0c23e..498f63da2b96 100644
--- a/fs/ntfs3/fslog.c
+++ b/fs/ntfs3/fslog.c
@@ -710,6 +710,13 @@ static bool check_log_rec(const struct LOG_REC_HDR *lr, u32 bytes, u32 tr,
if (le16_to_cpu(lr->undo_off) & 7)
return false;
+ /* The declared data window must fit inside the record itself. */
+ if (le16_to_cpu(lr->redo_off) + le16_to_cpu(lr->redo_len) > bytes)
+ return false;
+
+ if (le16_to_cpu(lr->undo_off) + le16_to_cpu(lr->undo_len) > bytes)
+ return false;
+
if (lr->target_attr)
goto check_lcns;
--
2.53.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-29 7:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29 7:24 [PATCH ntfs] fs/ntfs3: fix out-of-bounds read in check_log_rec() Xue Boyang
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®