* [PATCH] fs/ntfs3: validate that EA entry size covers its name and value
@ 2026-07-23 22:10 Your Name
0 siblings, 0 replies; only message in thread
From: Your Name @ 2026-07-23 22:10 UTC (permalink / raw)
To: ntfs3; +Cc: almaz.alexandrovich, linux-kernel, Aldo Ariel Panzardo, stable
From: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
ntfs_read_ea() walks the on-disk $EA attribute and checks each EA_FULL
entry for consistency. For an entry with a non-zero ef->size (the
offset to the next entry) the loop only verifies that this stride fits
in the remaining buffer, and then continues:
if (ef->size) {
ea_size = le32_to_cpu(ef->size);
if (ea_size > bytes)
goto out1;
continue;
}
It never verifies that the entry's own name (ef->name_len) and value
(ef->elength) actually fit inside ef->size. A later reader trusts
ef->elength unconditionally; ntfs_get_ea() does:
len = le16_to_cpu(ea->elength); /* up to 0xffff */
...
if (len > size) /* size is the user buffer */
return -ERANGE;
memcpy(buffer, ea->name + ea->name_len + 1, len);
A crafted image with a small but valid ef->size (e.g. 24) and
ef->elength == 0xffff therefore passes validation, and a getxattr()
with a large enough user buffer copies up to 64 KiB starting just past
the short entry -- an out-of-bounds read of the ea_all allocation that
leaks adjacent kernel heap memory to userspace.
BUG: KASAN: slab-out-of-bounds in ntfs_get_ea+0x2b8/0x3f0
Read of size 65535 ...
ntfs_get_ea -> ntfs_getxattr -> vfs_getxattr -> do_getxattr
The zero-ef->size branch already computes the same struct_size() to
derive the stride; mirror that in the non-zero branch and reject the
entry when its declared size cannot hold the name and value.
Fixes: 0e8235d28f3a ("fs/ntfs3: Check fields while reading")
Cc: stable@vger.kernel.org
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---
fs/ntfs3/xattr.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c
index 04814dd29375..57114fb726f7 100644
--- a/fs/ntfs3/xattr.c
+++ b/fs/ntfs3/xattr.c
@@ -155,6 +155,24 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea,
ea_size = le32_to_cpu(ef->size);
if (ea_size > bytes)
goto out1;
+
+ /* Check if we can use fields ef->name_len and ef->elength. */
+ if (bytes < offsetof(struct EA_FULL, name))
+ goto out1;
+
+ /*
+ * The declared entry size (ef->size) must be large
+ * enough to hold the name and value. Otherwise a later
+ * reader such as ntfs_get_ea() copies ef->elength bytes
+ * starting past the entry, reading out of bounds of the
+ * ea buffer and leaking adjacent heap memory to
+ * userspace via getxattr().
+ */
+ if (struct_size(ef, name,
+ 1 + ef->name_len +
+ le16_to_cpu(ef->elength)) >
+ ea_size)
+ goto out1;
continue;
}
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-23 22:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 22:10 [PATCH] fs/ntfs3: validate that EA entry size covers its name and value Your Name
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.