From: Joseph Qi <joseph.qi@linux.alibaba.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Heming Zhao <heming.zhao@suse.com>
Cc: Mark Fasheh <mark@fasheh.com>, Joel Becker <jlbec@evilplan.org>,
ocfs2-devel@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH v2 1/2] ocfs2: allow xattr bucket entries to span multiple blocks
Date: Thu, 3 Sep 2026 21:13:12 +0800 [thread overview]
Message-ID: <20260903131313.2396208-2-joseph.qi@linux.alibaba.com> (raw)
In-Reply-To: <20260903131313.2396208-1-joseph.qi@linux.alibaba.com>
ocfs2_validate_xattr_bucket() limits the entry array to the first
bucket block, but the write path stores entries across the whole
OCFS2_XATTR_BUCKET_SIZE region. With 512-byte blocks a bucket spans
eight blocks, and a bucket filled with small xattrs places its last
entries past offset 512. Reading such a bucket back errors out:
OCFS2: ERROR (device loop0): ocfs2_validate_xattr_bucket: Invalid xattr bucket 86072: entry count 32 exceeds maximum 31
On-disk corruption discovered. Please run fsck.ocfs2 once the filesystem is unmounted.
OCFS2: File system is now read-only.
This is reproducible by setting ~33 xattrs with 100-byte values on a
file on a blocksize-512 volume; fsck.ocfs2 reports the resulting
image clean.
Check the entry count against the full bucket region instead. The
per-block bounds checks for names and values stay as they are, since
ocfs2_bucket_align_free_start() keeps each name+value pair within a
single block.
The entry array is one contiguous region, so a bucket from a corrupted
xattr tree whose first block is not aligned to OCFS2_XATTR_BUCKET_SIZE
could straddle a page and make the validation loop read out of bounds.
Buckets allocated within clusters are always aligned, so reject any
other block number while validating.
Fixes: 2cf82b46d5e4 ("ocfs2: validate external xattr entries when reading metadata")
Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com>
---
fs/ocfs2/xattr.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 34f102db2a0e..c71fa7983b73 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1153,11 +1153,30 @@ static int ocfs2_validate_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
struct ocfs2_xattr_header *xh = bucket_xh(bucket);
u16 xattr_count = le16_to_cpu(xh->xh_count);
size_t region_size = (size_t)sb->s_blocksize * bucket->bu_blocks;
- size_t entries_limit = sb->s_blocksize;
+ /*
+ * The entry array grows up from the header across the whole
+ * bucket region, so it may extend beyond the first bucket block
+ * when the blocksize is smaller than OCFS2_XATTR_BUCKET_SIZE.
+ * Name/value pairs, however, always live within a single block.
+ */
+ size_t entries_limit = region_size;
size_t nv_limit = sb->s_blocksize;
size_t max_entries;
int i, ret;
+ /*
+ * The entry array is one contiguous region that may span the
+ * bucket's buffer_heads. Buckets are allocated within clusters,
+ * so their first block is always aligned to
+ * OCFS2_XATTR_BUCKET_SIZE and the whole bucket fits in one page.
+ * A corrupted xattr tree can point a bucket at blocks straddling
+ * a page, so reject it before touching the entry array.
+ */
+ if (blkno & (bucket->bu_blocks - 1))
+ return ocfs2_error(sb,
+ "Invalid xattr bucket %llu: unaligned block number\n",
+ (unsigned long long)blkno);
+
if (region_size < sizeof(*xh))
return ocfs2_error(sb,
"Invalid xattr bucket %llu: region size %zu is too small\n",
--
2.39.3
next prev parent reply other threads:[~2026-09-03 13:13 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 12:41 [PATCH] " Joseph Qi
2026-09-03 13:13 ` [PATCH v2 0/2] ocfs2: xattr bucket validation fixes Joseph Qi
2026-09-03 13:13 ` Joseph Qi [this message]
2026-09-03 13:13 ` [PATCH v2 2/2] ocfs2: reject inconsistent xattr bucket during defrag Joseph Qi
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=20260903131313.2396208-2-joseph.qi@linux.alibaba.com \
--to=joseph.qi@linux.alibaba.com \
--cc=akpm@linux-foundation.org \
--cc=heming.zhao@suse.com \
--cc=jlbec@evilplan.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark@fasheh.com \
--cc=ocfs2-devel@lists.linux.dev \
/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
all inboxes | Powered by JetHome®