[lvc-project] [PATCH 2/3] ext2: validate bg_block_bitmap before sb_getblk() in read_block_bitmap()
Denis Zubov
d.zubov at tssltd.ru
Tue May 12 15:22:14 MSK 2026
read_block_bitmap() blindly trusts desc->bg_block_bitmap and calls
sb_getblk() on it. For a corrupt on-disk group descriptor that points
outside the filesystem, sb_getblk() returns a bh whose b_data sits on
a bdev-cache page that can be reclaimed back to the buddy allocator,
producing a KASAN use-after-free when ext2_try_to_allocate() writes
a bit via ext2_set_bit_atomic():
BUG: KASAN: use-after-free in ext2_try_to_allocate+0x5fd/0x840
Write of size 8 at addr ffff888007104000
...
ext2_try_to_allocate_with_rsv+0x121b/0x1580
ext2_new_blocks+0x671/0x1650
ext2_get_blocks+0x76b/0x2340
...
ext2_make_empty+0xff/0x7e0
ext2_mkdir+0x153/0x240
Reject bg_block_bitmap values outside [s_first_data_block,
s_blocks_count) before creating any buffer head for them.
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 | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index bc181aa47265..10e3b100d390 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -128,6 +128,7 @@ static int ext2_valid_block_bitmap(struct super_block *sb,
static struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
struct ext2_group_desc * desc;
struct buffer_head * bh = NULL;
ext2_fsblk_t bitmap_blk;
@@ -137,6 +138,16 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
if (!desc)
return NULL;
bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+
+ if (bitmap_blk < le32_to_cpu(sbi->s_es->s_first_data_block) ||
+ bitmap_blk >= le32_to_cpu(sbi->s_es->s_blocks_count)) {
+ ext2_error(sb, __func__,
+ "Invalid block_bitmap = %llu for group %u (s_blocks_count = %u)",
+ (unsigned long long)bitmap_blk, block_group,
+ le32_to_cpu(sbi->s_es->s_blocks_count));
+ return NULL;
+ }
+
bh = sb_getblk(sb, bitmap_blk);
if (unlikely(!bh)) {
ext2_error(sb, __func__,
--
2.53.0
More information about the lvc-project
mailing list