mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®