[PATCH] ext4: guard against NULL s_group_info in ext4_get_group_info

Junzhe Yu <[email protected]>
Newsgroups org.kernel.vger.linux-kernel,org.kernel.vger.linux-ext4
Message-ID <[email protected]>
Resend: previous attempt was rejected by vger for containing HTML.

==================================================================

ext4_mark_group_bitmap_corrupted() already treats a NULL return from
ext4_get_group_info() as "nothing to do", but ext4_get_group_info()
indexes s_group_info without checking whether the array exists.

During mount, fast-commit replay runs inside jbd2_journal_load() from
ext4_load_and_init_journal(), which is before ext4_mb_init() allocates
s_group_info. Replaying an FC UNLINK for an inode whose bitmap bit is
already clear takes:

   ext4_fc_replay_unlink -> iput -> ext4_evict_inode -> ext4_free_inode
     -> ext4_mark_group_bitmap_corrupted -> ext4_get_group_info

and faults on the NULL s_group_info base. Userspace only mounts a dirty
ext4 image; this is a supported recovery path.

Return NULL when s_group_info (or the per-block grp_info row) is unset
so the existing caller check is effective during early mount.

Tested on Linux v6.6.145 KASAN: crafted FC-unlink image previously
triggered KASAN null-ptr-deref / panic in ext4_get_group_info; with this
patch, mount succeeds (EXT4 "bit already cleared" may still log). Also
observed on v6.6.144; still present on torvalds/linux as of
f5098b6bae76 (2026-07-26).

A self-contained Docker/QEMU reproducer (craft + mount + patch verify) is
available on request.

Signed-off-by: Yu Junzhe <[email protected]>
---
  fs/ext4/balloc.c | 4 ++++
  1 file changed, 4 insertions(+)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 3a2dfc5..80c81bc 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -329,9 +329,13 @@ struct ext4_group_info *ext4_get_group_info(struct 
super_block *sb,

      if (unlikely(group >= EXT4_SB(sb)->s_groups_count))
          return NULL;
+    if (unlikely(!EXT4_SB(sb)->s_group_info))
+        return NULL;
      indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
      indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
      grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
+    if (unlikely(!grp_info))
+        return NULL;
      return grp_info[indexh];
  }

-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.