[PATCH 5.15.y 4/7] fs/ntfs3: Sequential field availability check in mi_enum_attr()
From: Sasha Levin <sashal@kernel.org>
Date: 2026-09-10 11:08:39
Subsystem:
filesystems (vfs and infrastructure), ntfs3 filesystem, the rest · Maintainers:
Alexander Viro, Christian Brauner, Konstantin Komarov, Linus Torvalds
From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
[ Upstream commit 090f612756a9720ec18b0b130e28be49839d7cb5 ]
The code is slightly reformatted to consistently check field availability
without duplication.
Fixes: 556bdf27c2dd ("ntfs3: Add bounds checking to mi_enum_attr()")
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Stable-dep-of: 7c4841e2a627 ("fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ntfs3/record.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
index e633fabdfbe5e..e8d25f6ff15ed 100644
--- a/fs/ntfs3/record.c
+++ b/fs/ntfs3/record.c@@ -232,6 +232,7 @@ struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi, } /* Can we use the first field (attr->type). */ + /* NOTE: this code also checks attr->size availability. */ if (off + 8 > used) { static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8); return NULL;
@@ -252,10 +253,6 @@ struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi, return NULL; asize = le32_to_cpu(attr->size); - if (asize < SIZEOF_RESIDENT) { - /* Impossible 'cause we should not return such attribute. */ - return NULL; - } /* Check overflow and boundary. */ if (off + asize < off || off + asize > used)
@@ -286,6 +283,10 @@ struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi, if (attr->non_res != 1) return NULL; + /* Can we use memory including attr->nres.valid_size? */ + if (asize < SIZEOF_NONRESIDENT) + return NULL; + t16 = le16_to_cpu(attr->nres.run_off); if (t16 > asize) return NULL;
@@ -312,7 +313,8 @@ struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi, if (!attr->nres.svcn && is_attr_ext(attr)) { /* First segment of sparse/compressed attribute */ - if (asize + 8 < SIZEOF_NONRESIDENT_EX) + /* Can we use memory including attr->nres.total_size? */ + if (asize < SIZEOF_NONRESIDENT_EX) return NULL; tot_size = le64_to_cpu(attr->nres.total_size);
@@ -322,9 +324,6 @@ struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi, if (tot_size > alloc_size) return NULL; } else { - if (asize + 8 < SIZEOF_NONRESIDENT) - return NULL; - if (attr->nres.c_unit) return NULL;
--
2.53.0