[PATCH] ocfs2: use validated allocator metadata for move extents

From: Jiale Yao

Date: Sun Oct 18 2026 - 07:43:36 EST


ocfs2_find_victim_alloc_group() reads the allocator inode and group
descriptors as raw blocks. It then uses their chain counts, bitmap sizes,
and chain indices without validation. Malformed metadata can therefore
cause out-of-bounds chain or bitmap accesses.

Obtain the allocator system inode and use the standard inode and group
descriptor readers so all metadata is validated before use.

Fixes: 1c06b9126130 ("Ocfs2/move_extents: find the victim alloc group, where the given #blk fits.")
Signed-off-by: Jiale Yao <yaojiale02@xxxxxxx>
---
fs/ocfs2/move_extents.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index ad1678ee7cc4..38c3757251ad 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -370,26 +370,23 @@ static int ocfs2_find_victim_alloc_group(struct inode *inode,
int *vict_bit,
struct buffer_head **ret_bh)
{
- int ret, i, len, bits_per_unit = 0;
- u64 blkno;
- char namebuf[40];
-
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct buffer_head *ac_bh = NULL, *gd_bh = NULL;
struct ocfs2_chain_list *cl;
struct ocfs2_chain_rec *rec;
struct ocfs2_dinode *ac_dinode;
struct ocfs2_group_desc *bg;
+ struct inode *alloc_inode;
+ int ret, i, bits_per_unit = 0;
+ u64 blkno;

- len = ocfs2_sprintf_system_inode_name(namebuf, sizeof(namebuf), type, slot);
- ret = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf, len, &blkno);
-
- if (ret) {
- ret = -ENOENT;
+ alloc_inode = ocfs2_get_system_file_inode(osb, type, slot);
+ if (!alloc_inode) {
+ ret = -EIO;
goto out;
}

- ret = ocfs2_read_blocks_sync(osb, blkno, 1, &ac_bh);
+ ret = ocfs2_read_inode_block(alloc_inode, &ac_bh);
if (ret) {
mlog_errno(ret);
goto out;
@@ -431,7 +428,8 @@ static int ocfs2_find_victim_alloc_group(struct inode *inode,
gd_bh = NULL;
}

- ret = ocfs2_read_blocks_sync(osb, blkno, 1, &gd_bh);
+ ret = ocfs2_read_group_descriptor(alloc_inode, ac_dinode,
+ blkno, &gd_bh);
if (ret) {
mlog_errno(ret);
goto out;
@@ -458,6 +456,7 @@ static int ocfs2_find_victim_alloc_group(struct inode *inode,
ret = -EINVAL;
out:
brelse(ac_bh);
+ iput(alloc_inode);

/*
* caller has to release the gd_bh properly.
--
2.34.1