[PATCH v4 1/2] ext4: Fix out-of-bounds read in ext4_get_group_info()

From: Jinjie Ruan

Date: Fri Sep 04 2026 - 03:47:03 EST


A plain read of s_groups_count in ext4_get_group_info() allows CPU
load-load reordering. On weak memory models, speculative prefetch of
s_group_info prior to the boundary check could lead to an out-of-bounds
read if a concurrent online resize expands the array and increments
s_groups_count.

The data race occurs between the ioctl configuration path (holding the
resize lock via ext4_resize_begin) and the lockless metadata lookup path:

CPU 0 (Writer, Resize Lock) CPU 1 (Reader, Lockless)
--------------------------- ------------------------
ext4_ioctl()
[EXT4_IOC_GROUP_ADD]
ext4_ioctl_group_add()
ext4_resize_begin() // Takes lock
ext4_group_add()
ext4_mb_alloc_groupinfo()
// Publishes expanded array via RCU
rcu_assign_pointer(s_group_info, ...)

ext4_flex_group_add()
ext4_update_super()
ext4_get_group_info()
// Speculative / out-of-order read
[Loads old/smaller s_group_info pointer]
[Plain C store / smp_wmb()]
sbi->s_groups_count += ...;
// Reads new s_groups_count,
// boundary check passes
if (group >= s_groups_count)

// Out-of-bounds array access!
sbi_array_rcu_deref(..., s_group_info)

Fix this by using ext4_get_groups_count() to enforce acquire semantics.

Cc: stable@xxxxxxxxxxxxxxx
Fixes: 5354b2af3406 ("ext4: allow ext4_get_group_info() to fail")
Link: https://sashiko.dev/#/patchset/20260825095422.3166067-1-ruanjinjie%40huawei.com
Reviewed-by: Zhang Yi <yi.zhang@xxxxxxxxxx>
Reviewed-by: Jan Kara <jack@xxxxxxx>
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
Cc: Theodore Ts'o <tytso@xxxxxxx>
Cc: Andreas Dilger <adilger.kernel@xxxxxxxxx>
Cc: Baokun Li <libaokun@xxxxxxxxxxxxxxxxx>
Cc: Jan Kara <jack@xxxxxxx>
Cc: Ojaswin Mujoo <ojaswin@xxxxxxxxxxxxx>
Cc: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx>
Cc: Zhang Yi <yi.zhang@xxxxxxxxxx>
---
fs/ext4/balloc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 52f4c5169f91..778fe8788f06 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -329,7 +329,7 @@ struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
struct ext4_group_info **grp_info;
long indexv, indexh;

- if (unlikely(group >= EXT4_SB(sb)->s_groups_count))
+ if (unlikely(group >= ext4_get_groups_count(sb)))
return NULL;
if (unlikely(!EXT4_SB(sb)->s_group_info))
return NULL;
--
2.34.1