diff mbox series

[2/8] e2fsck: fix extended attribute block checking

Message ID 20260924222944.3683556-3-sandeen@redhat.com
State New
Headers show
Series e2fsprogs: fix extended attribute iteration loop bounds checking | expand

Commit Message

Eric Sandeen Sept. 24, 2026, 10:23 p.m. UTC
From: Andreas Gruenbacher <agruenba@redhat.com>

Fix the same problems as in check_ea_in_inode().

The 'entry->e_value_offs + entry->e_value_size > fs->blocksize' check is
covered by the region_allocate() check that follows it, so it can be
removed.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
 e2fsck/pass1.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 555429b6..f66a2908 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2493,6 +2493,7 @@  static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
 	char *		end;
 	struct ext2_ext_attr_header *header;
 	struct ext2_ext_attr_entry *first, *entry;
+	unsigned int	remain;
 	blk64_t		quota_blocks = EXT2FS_C2B(fs, 1);
 	__u64		quota_inodes = 0;
 	region_t	region = 0;
@@ -2630,10 +2631,19 @@  static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
 
 	first = (struct ext2_ext_attr_entry *)(header+1);
 	end = block_buf + fs->blocksize;
+	/* take finish entry 0UL into account */
+	remain = end - (char *)first - sizeof(__u32);
 	entry = first;
-	while ((char *)entry < end && *(__u32 *)entry) {
+	while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
 		__u32 hash;
 
+		/* entry->e_name_len is within the first four bytes */
+		if (EXT2_EXT_ATTR_LEN(entry->e_name_len) > remain) {
+			if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
+				goto clear_extattr;
+			break;
+		}
+		remain -= EXT2_EXT_ATTR_LEN(entry->e_name_len);
 		if (region_allocate(region, (char *)entry - (char *)header,
 			           EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
 			if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
@@ -2649,13 +2659,12 @@  static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
 			break;
 		}
 		if (entry->e_value_inum == 0) {
-			if (entry->e_value_size > EXT2_XATTR_SIZE_MAX ||
-			    (entry->e_value_offs + entry->e_value_size >
-			     fs->blocksize)) {
+			if (EXT2_EXT_ATTR_SIZE(entry->e_value_size) > remain) {
 				if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
 					goto clear_extattr;
 				break;
 			}
+			remain -= EXT2_EXT_ATTR_SIZE(entry->e_value_size);
 			if (entry->e_value_size &&
 			    region_allocate(region, entry->e_value_offs,
 					    EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
@@ -2697,7 +2706,7 @@  static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
 
 		entry = EXT2_EXT_ATTR_NEXT(entry);
 	}
-	if (region_allocate(region, (char *)entry - (char *)header, 4)) {
+	if (region_allocate(region, (char *)entry - (char *)header, sizeof(__u32))) {
 		if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
 			goto clear_extattr;
 	}