From: Eric Sandeen <sandeen@redhat.com>
To: linux-ext4@vger.kernel.org
Cc: tytso@mit.edu, sandeen@redhat.com, agruenba@redhat.com
Subject: [PATCH 1/8] e2fsck: fix in-inode extended attribute checking
Date: Thu, 24 Sep 2026 17:23:35 -0500 [thread overview]
Message-ID: <20260924222944.3683556-2-sandeen@redhat.com> (raw)
In-Reply-To: <20260924222944.3683556-1-sandeen@redhat.com>
From: Andreas Gruenbacher <agruenba@redhat.com>
Extended attribute areas in inodes and on separate blocks are stored in
the following format: (1) first comes the list of name records, (2)
followed by an end marker, followed by any (3) free space that remains,
followed by (4) any attribute values that are not stored in separate
inodes. The name records and values are all variable-length and 4-byte
aligned. The end marker is mandatory.
A lot of the loops iterating over those extended attribute areas get this
wrong. This patch fixes the loop in check_ea_in_inode:
- First, we can safely assume that the total size is at least 4 bytes.
Take 4 bytes (the size of the end marker) off of the remaining space
to make sure that enough space remains available for the end marker.
(We can safely assume that the total size is at least 4 bytes.)
- Second, at the top of the loop, we can assume that the area contains
at least an end marker, but we cannot assume that the list still
contains an entire ext2_ext_attr_entry header.
- Third, since the loop condition now no longer checks if we have a
complete ext2_ext_attr_entry header, check if we still have a complete
name record of size EXT2_EXT_ATTR_LEN(entry->e_name_len). The length
of the name is stored in the first byte of the entry, so we can safely
access it.
- Fourth, value are 4-byte aligned, so take that into consideration when
calculating the remaining free space.
With these changes to check_ea_in_inode(), an 'Extended attribute in
inode has Aa namelen which is invalid' error is detected before
allocation is checked, which masks the previous 'Inode extended attribute
is corrupt (allocation collision)' error in test f_inode_ea_collision.
Adjust the expected test result.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
e2fsck/pass1.c | 32 ++++++++++-------------------
tests/f_inode_ea_collision/expect.1 | 3 ++-
2 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index c9711446..555429b6 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -501,36 +501,31 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx,
goto fix;
}
- while (remain >= sizeof(struct ext2_ext_attr_entry) &&
- !EXT2_EXT_IS_LAST_ENTRY(entry)) {
+ while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
__u32 hash;
- if (region_allocate(region, (char *)entry - (char *)header,
- EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
- problem = PR_1_INODE_EA_ALLOC_COLLISION;
- goto fix;
- }
-
- /* header eats this space */
- remain -= sizeof(struct ext2_ext_attr_entry);
-
- /* is attribute name valid? */
- if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
+ /* entry->e_name_len is within the first four bytes */
+ if (EXT2_EXT_ATTR_LEN(entry->e_name_len) > remain) {
pctx->num = entry->e_name_len;
problem = PR_1_ATTR_NAME_LEN;
goto fix;
}
+ remain -= EXT2_EXT_ATTR_LEN(entry->e_name_len);
- /* attribute len eats this space */
- remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
+ if (region_allocate(region, (char *)entry - (char *)header,
+ EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
+ problem = PR_1_INODE_EA_ALLOC_COLLISION;
+ goto fix;
+ }
if (entry->e_value_inum == 0) {
/* check value size */
- if (entry->e_value_size > remain) {
+ if (EXT2_EXT_ATTR_SIZE(entry->e_value_size) > remain) {
pctx->num = entry->e_value_size;
problem = PR_1_ATTR_VALUE_SIZE;
goto fix;
}
+ remain -= EXT2_EXT_ATTR_SIZE(entry->e_value_size);
if (entry->e_value_size &&
region_allocate(region,
@@ -571,11 +566,6 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx,
ea_ibody_quota->inodes++;
}
- /* If EA value is stored in external inode then it does not
- * consume space here */
- if (entry->e_value_inum == 0)
- remain -= entry->e_value_size;
-
entry = EXT2_EXT_ATTR_NEXT(entry);
}
diff --git a/tests/f_inode_ea_collision/expect.1 b/tests/f_inode_ea_collision/expect.1
index a67a5f19..dfe49a9f 100644
--- a/tests/f_inode_ea_collision/expect.1
+++ b/tests/f_inode_ea_collision/expect.1
@@ -1,7 +1,8 @@
Pass 1: Checking inodes, blocks, and sizes
Inode 12 extended attribute is corrupt (allocation collision). Clear? yes
-Inode 13 extended attribute is corrupt (allocation collision). Clear? yes
+Extended attribute in inode 13 has a namelen (98) which is invalid
+Clear? yes
Inode 14 extended attribute is corrupt (allocation collision). Clear? yes
--
2.55.0
next prev parent reply other threads:[~2026-09-24 22:29 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 22:23 [PATCH 0/8] e2fsprogs: fix extended attribute iteration loop bounds checking Eric Sandeen
2026-09-24 22:23 ` Eric Sandeen [this message]
2026-09-24 22:23 ` [PATCH 2/8] e2fsck: fix extended attribute block checking Eric Sandeen
2026-09-24 22:23 ` [PATCH 3/8] e2fsck: fix ea loop in inc_ea_inode_refs Eric Sandeen
2026-09-24 22:23 ` [PATCH 4/8] libext2fs: fix ea loop in ext2fs_ext_attr_block_rehash Eric Sandeen
2026-09-24 22:23 ` [PATCH 5/8] libext2fs: fix ea loop in read_xattrs_from_buffer Eric Sandeen
2026-09-24 22:23 ` [PATCH 6/8] tune2fs: fix ea loop in update_xattr_entry_hashes Eric Sandeen
2026-09-24 22:23 ` [PATCH 7/8] resize2fs: " Eric Sandeen
2026-09-24 22:23 ` [PATCH 8/8] libext2fs: fix ea loop in ext2fs_xattr_inode_max_size Eric Sandeen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260924222944.3683556-2-sandeen@redhat.com \
--to=sandeen@redhat.com \
--cc=agruenba@redhat.com \
--cc=linux-ext4@vger.kernel.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox