[PATCH 3/3] tune2fs: Add bounds checking for extended attribute processing

Josh Hunt <[email protected]> Thu, 30 Jul 2026 20:37:01 -0700
Newsgroups org.kernel.vger.linux-ext4
Message-ID <[email protected]>
From: Kit Knox <[email protected]>

Add validation to prevent buffer overflow when processing extended
attributes:

- Check ea_inode size against maximum (64KB) before reading
- Validate xattr entry bounds before accessing next entry

This prevents malformed filesystem images from causing out-of-bounds memory
access during UUID or checksum updates.

Signed-off-by: Kit Knox <[email protected]>
---
 misc/tune2fs.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 3db57632..8c292686 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -744,18 +744,25 @@ struct rewrite_context {
 		exit(1);			\
 	} while (0);
 
+#define EA_INODE_SIZE_MAX	(64 * 1024)
+
 static void update_ea_inode_hash(struct rewrite_context *ctx, ext2_ino_t ino,
 				 struct ext2_inode *inode)
 {
 	errcode_t retval;
 	ext2_file_t file;
 	__u32 hash;
+	__u64 ea_size = EXT2_I_SIZE(inode);
+
+	if (ea_size > EA_INODE_SIZE_MAX)
+		fatal_err(EXT2_ET_EA_BAD_VALUE_SIZE,
+			  "ea_inode %u has invalid size %llu", ino,
+			  (unsigned long long) ea_size);
 
 	retval = ext2fs_file_open(ctx->fs, ino, 0, &file);
 	if (retval)
 		fatal_err(retval, "open ea_inode");
-	retval = ext2fs_file_read(file, ctx->ea_buf, inode->i_size,
-				  NULL);
+	retval = ext2fs_file_read(file, ctx->ea_buf, ea_size, NULL);
 	if (retval)
 		fatal_err(retval, "read ea_inode");
 	retval = ext2fs_file_close(file);
@@ -763,7 +770,7 @@ static void update_ea_inode_hash(struct rewrite_context *ctx, ext2_ino_t ino,
 		fatal_err(retval, "close ea_inode");
 
 	hash = ext2fs_crc32c_le(ctx->fs->csum_seed,
-				(unsigned char *) ctx->ea_buf, inode->i_size);
+				(unsigned char *) ctx->ea_buf, ea_size);
 	ext2fs_set_ea_inode_hash(inode, hash);
 }
 
@@ -775,6 +782,9 @@ static int update_xattr_entry_hashes(ext2_filsys fs,
 	errcode_t retval;
 
 	while (entry < end && !EXT2_EXT_IS_LAST_ENTRY(entry)) {
+		if ((char *)end < (char *)entry + sizeof(*entry))
+			fatal_err(EXT2_ET_EA_BAD_NAME_LEN,
+				  "xattr entry exceeds buffer bounds");
 		if (entry->e_value_inum) {
 			retval = ext2fs_ext_attr_hash_entry2(fs, entry, NULL,
 							     &entry->e_hash);
@@ -784,6 +794,9 @@ static int update_xattr_entry_hashes(ext2_filsys fs,
 		}
 		entry = EXT2_EXT_ATTR_NEXT(entry);
 	}
+	if (entry > end)
+		fatal_err(EXT2_ET_EA_BAD_NAME_LEN,
+			  "xattr entry exceeds buffer bounds");
 	return modified;
 }
 
-- 
2.34.1