[PATCH] ntfs: validate final EA attribute size

Namjae Jeon <[email protected]> Thu, 16 Jul 2026 11:46:35 +0900
Newsgroups dev.linux.lists.ntfs,org.kernel.vger.linux-fsdevel
Message-ID <[email protected]>
A replacement first removes the existing EA record, then adds the
replacement. Check the size of that final $EA stream before mutating
the current stream.

This avoids committing the shortened $EA stream or $EA_INFORMATION before
discovering that the replacement exceeds the AttrDef size limit.

Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations")
Signed-off-by: Namjae Jeon <[email protected]>
---
 fs/ntfs/ea.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/fs/ntfs/ea.c b/fs/ntfs/ea.c
index 0cd192752b7c..0eba3f41c7bb 100644
--- a/fs/ntfs/ea.c
+++ b/fs/ntfs/ea.c
@@ -250,6 +250,14 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
 			goto out;
 		}
 
+		/* Check the final $EA size before removing the old entry. */
+		if (val_size &&
+		    ntfs_attr_size_bounds_check(ni->vol, AT_EA,
+					ea_info_qsize - ea_size + new_ea_size)) {
+			err = -EFBIG;
+			goto out;
+		}
+
 		p_ea = (struct ea_attr *)(ea_buf + ea_off);
 
 		if (val_size &&
@@ -285,6 +293,12 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
 			err = -ENODATA;
 			goto out;
 		}
+
+		if (ntfs_attr_size_bounds_check(ni->vol, AT_EA,
+					ea_info_qsize + new_ea_size)) {
+			err = -EFBIG;
+			goto out;
+		}
 	}
 	kvfree(ea_buf);
 
@@ -312,8 +326,7 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
 	p_ea_info->ea_length = cpu_to_le16(ea_packed);
 	p_ea_info->ea_query_length = cpu_to_le32(ea_info_qsize + new_ea_size);
 
-	if (ea_packed > 0xffff ||
-	    ntfs_attr_size_bounds_check(ni->vol, AT_EA, new_ea_size)) {
+	if (ea_packed > 0xffff) {
 		err = -EFBIG;
 		goto out;
 	}
-- 
2.25.1