[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20260115040008.13549-1-jiashengjiangcool@gmail.com>
Date: Thu, 15 Jan 2026 04:00:08 +0000
From: Jiasheng Jiang <jiashengjiangcool@...il.com>
To: Mark Fasheh <mark@...heh.com>,
Joel Becker <jlbec@...lplan.org>,
Joseph Qi <joseph.qi@...ux.alibaba.com>,
linux-kernel@...r.kernel.org
Cc: ocfs2-devel@...ts.linux.dev,
Jiasheng Jiang <jiashengjiangcool@...il.com>
Subject: [PATCH] ocfs2: validate max leaf clusters in ocfs2_figure_merge_contig_type
In 'ocfs2_figure_merge_contig_type', the variable 'split_rec' is used to
determine if a split extent can be merged with its neighbors. However,
the function fails to validate if the resulting merged extent would
exceed the 'et_max_leaf_clusters' limit.
In contrast, its peer function 'ocfs2_figure_contig_type' (used for
inserting new extents) explicitly performs this validation checks
against 'et_max_leaf_clusters' to prevent creating oversized extents.
This inconsistency is particularly problematic for xattr trees, where
'et_max_leaf_clusters' is set to a non-zero value (derived from
OCFS2_MAX_XATTR_TREE_LEAF_SIZE). If a merge occurs that exceeds this
limit, it creates an extent that violates the filesystem's structural
invariants, potentially leading to corruption or failure when accessing
extended attributes.
This patch adds the missing verification logic to
'ocfs2_figure_merge_contig_type'. It ensures that before indicating
CONTIG_LEFT or CONTIG_RIGHT, the combined length of the existing record
and the split record is checked against 'et_max_leaf_clusters' if the
limit is set.
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@...il.com>
---
fs/ocfs2/alloc.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 58bf58b68955..7d9400736791 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -4424,6 +4424,12 @@ static int ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
ret = CONTIG_RIGHT;
} else {
ret = ocfs2_et_extent_contig(et, rec, split_rec);
+ if (ret != CONTIG_NONE && et->et_max_leaf_clusters) {
+ if (le16_to_cpu(rec->e_leaf_clusters) +
+ le16_to_cpu(split_rec->e_leaf_clusters) >
+ et->et_max_leaf_clusters)
+ ret = CONTIG_NONE;
+ }
}
}
@@ -4470,6 +4476,12 @@ static int ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
enum ocfs2_contig_type contig_type;
contig_type = ocfs2_et_extent_contig(et, rec, split_rec);
+ if (contig_type != CONTIG_NONE && et->et_max_leaf_clusters) {
+ if (le16_to_cpu(rec->e_leaf_clusters) +
+ le16_to_cpu(split_rec->e_leaf_clusters) >
+ et->et_max_leaf_clusters)
+ contig_type = CONTIG_NONE;
+ }
if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
ret = CONTIG_LEFTRIGHT;
--
2.25.1
Powered by blists - more mailing lists