mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Bryam Vargas <hexlabsecurity@proton.me>
To: Namjae Jeon <linkinjeon@kernel.org>, Hyunchul Lee <hyc.lee@gmail.com>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 2/3] ntfs: bound the look-ahead attribute-list entry in ntfs_external_attr_find()
Date: Wed, 03 Jun 2026 18:00:01 +0000	[thread overview]
Message-ID: <20260603175949.11665-2-hexlabsecurity@proton.me> (raw)
In-Reply-To: <20260603175949.11665-1-hexlabsecurity@proton.me>

When resolving an attribute lookup with a non-zero @lowest_vcn,
ntfs_external_attr_find() peeks at the next $ATTRIBUTE_LIST entry to
decide whether to keep searching, but bounds that not-yet-validated
entry only with "(u8 *)next_al_entry + 6 < al_end" (which proves just
bytes 0..6 are in range) and "(u8 *)next_al_entry + length <= al_end"
with an attacker-controlled, non-8-aligned length. It then reads
next_al_entry->lowest_vcn (an __le64 at offset 8) and the name at
next_al_entry->name_offset, both of which can lie past al_end -- the
exact end of the kvmalloc'd attribute-list buffer (allocated at the
on-disk attr_list_size, no rounding). A crafted on-disk $ATTRIBUTE_LIST
whose last entry sits a few bytes before al_end therefore yields a slab
out-of-bounds read when the inode is read.

Apply to the look-ahead entry the same bounds the main loop already
applies to the current entry: require the fixed header up to
offsetof(struct attr_list_entry, name) to be in range, and the name to
lie within the buffer, before dereferencing lowest_vcn and the name.

Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
v2: dropped the redundant Reported-by; reproducer and KASAN splat omitted on
    the public list -- available to the maintainers on request. Posting per
    security@kernel.org guidance that crafted-image filesystem bugs are out of
    the kernel security process's threat model.

Verified by mounting a crafted NTFS image under KASAN (fs/ntfs built as a
module against v7.1-rc5): a slab out-of-bounds read of next_al_entry->lowest_vcn
during inode read; a benign mkntfs image is KASAN-clean on the same kernel
(control). Arch-independent: the on-disk struct is __packed (lowest_vcn at
offset 8, fixed header up to offsetof(struct attr_list_entry, name) == 26) and
the over-read is an le64; identical geometry built -m32/-m64, so 32- and 64-bit
kernels are both affected.

Fixes note: this is in the fs/ntfs driver added during the v7.1 merge window.
The look-ahead expression is carried verbatim from the legacy fs/ntfs driver
(removed in v6.9; present unchanged since v2.6.12), where __ntfs_malloc()
rounded the list allocation up to a full kmalloc(PAGE_SIZE) and masked it; the
new driver's exact-size kvmalloc(attr_list_size) exposes it. Please add the
appropriate Fixes: tag for the commit that introduced ntfs_external_attr_find()
in the new driver.

 fs/ntfs/attrib.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 421c6cdcbb53..aed68b8e69ea 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1137,9 +1137,14 @@ static int ntfs_external_attr_find(const __le32 type,
 		 * we have reached the right one or the search has failed.
 		 */
 		if (lowest_vcn && (u8 *)next_al_entry >= al_start &&
-				(u8 *)next_al_entry + 6 < al_end &&
+				(u8 *)next_al_entry +
+						offsetof(struct attr_list_entry, name) <= al_end &&
 				(u8 *)next_al_entry + le16_to_cpu(
 					next_al_entry->length) <= al_end &&
+				(!next_al_entry->name_length ||
+				 (u8 *)next_al_entry + next_al_entry->name_offset +
+				 next_al_entry->name_length * sizeof(__le16) <=
+						al_end) &&
 				le64_to_cpu(next_al_entry->lowest_vcn) <=
 					lowest_vcn &&
 				next_al_entry->type == al_entry->type &&
-- 
2.43.0


  reply	other threads:[~2026-06-03 18:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-03 17:59 [PATCH v2 1/3] ntfs: validate resident attribute lists and harden the validator Bryam Vargas
2026-06-03 18:00 ` Bryam Vargas [this message]
2026-06-03 18:00 ` [PATCH v2 3/3] ntfs: bound the attribute-list entry in ntfs_read_inode_mount() Bryam Vargas
2026-06-04  4:29 ` [PATCH v3 1/3] ntfs: validate resident attribute lists and harden the validator Bryam Vargas
2026-06-04  4:29   ` [PATCH v3 2/3] ntfs: bound the look-ahead attribute-list entry in ntfs_external_attr_find() Bryam Vargas
2026-06-04  8:41     ` Hyunchul Lee
2026-06-04  4:29   ` [PATCH v3 3/3] ntfs: bound the attribute-list entry in ntfs_read_inode_mount() Bryam Vargas
2026-06-04  8:44     ` Hyunchul Lee
2026-06-08  1:51       ` Bryam Vargas
2026-06-04  8:40   ` [PATCH v3 1/3] ntfs: validate resident attribute lists and harden the validator Hyunchul Lee

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260603175949.11665-2-hexlabsecurity@proton.me \
    --to=hexlabsecurity@proton.me \
    --cc=hyc.lee@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox