[lvc-project] [PATCH 1/3] ext2: reject out-of-range block_group in ext2_free_blocks()

Denis Zubov d.zubov at tssltd.ru
Tue May 12 15:22:13 MSK 2026


On a corrupt ext2 image, ext2_free_blocks() can compute block_group
beyond sbi->s_groups_count from an on-disk block pointer recovered
during inode eviction. ext2_get_group_desc() then issues a WARN; with
panic_on_warn set this panics the kernel:

WARNING: CPU: 0 PID: 207 at fs/ext2/balloc.c:49 ext2_get_group_desc+0x1f1/0x280
block_group >= groups_count - block_group = 1, groups_count = 1
...
read_block_bitmap+0x26/0x870
ext2_free_blocks+0x30b/0xaf0
__ext2_truncate_blocks+0xa0a/0xc90
ext2_evict_inode+0x3c3/0x500
...
ext2_mkdir+0x1b8/0x240

Validate block_group before calling read_block_bitmap() and log via
ext2_error().

Found by Linux Verification Center (linuxtesting.org) with Syzkaller.

Fixes: 8b91582500ae ("ext2: retry block allocation if new blocks are allocated from system zone")
Signed-off-by: Denis Zubov <d.zubov at tssltd.ru>
---
 fs/ext2/balloc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index b8cfab8f98b9..bc181aa47265 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -509,6 +509,14 @@ void ext2_free_blocks(struct inode * inode, ext2_fsblk_t block,
 		      EXT2_BLOCKS_PER_GROUP(sb);
 	bit = (block - le32_to_cpu(es->s_first_data_block)) %
 		      EXT2_BLOCKS_PER_GROUP(sb);
+
+	if (block_group >= sbi->s_groups_count) {
+		ext2_error(sb, "ext2_free_blocks",
+					"Freeing blocks in non-existent group %lu (groups_count = %lu): block = %llu, count = %lu",
+					block_group, sbi->s_groups_count,
+					(unsigned long long)block, count);
+		goto error_return;
+	}
 	/*
 	 * Check to see if we are freeing blocks across a group
 	 * boundary.
-- 
2.53.0




More information about the lvc-project mailing list