[lvc-project] [PATCH] ext2: fix use-after-free in read_block_bitmap()

Fedor Pchelkin pchelkin at ispras.ru
Sun Apr 26 17:19:18 MSK 2026


On Sun, 26. Apr 12:17, Denis Zubov wrote:
> When bh_read() returns 0 (buffer already uptodate), read_block_bitmap()
> skips ext2_valid_block_bitmap() and returns the buffer_head without
> validation. On a corrupt filesystem with an invalid block bitmap this
> allows a corrupt bh to propagate to ext2_try_to_allocate(), where
> ext2_set_bit_atomic() writes to bitmap_bh->b_data of an already freed
> page, causing a use-after-free write.
> 
> The comment 'continue with corrupt bitmap' suggests this was intentional,
> however continuing with an invalid bitmap leads to memory corruption.
> The correct behavior on a corrupt filesystem is to return NULL so all
> callers handle the error safely via the existing io_error path.
> 
> Fix by always running ext2_valid_block_bitmap() before returning bh,
> regardless of whether the buffer was cached or freshly read, and
> returning NULL with brelse() on validation failure.
> 
> Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
> 
> Signed-off-by: Denis Zubov <d.zubov at tssltd.ru>

Для фикс патчей нужен тег Fixes, позволяющий понять коммит, после которого
возможны условия для возникновения ошибки.
https://portal.linuxtesting.ru/How-to-send-patches-to-kernel.html#Fixes

> ---
>  fs/ext2/balloc.c | 30 +++++++++++++-----------------
>  1 file changed, 13 insertions(+), 17 deletions(-)
> 
> diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
> index b8cfab8f98b9..3345a25b4bde 100644
> --- a/fs/ext2/balloc.c
> +++ b/fs/ext2/balloc.c
> @@ -146,23 +146,19 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
>  		return NULL;
>  	}
>  	ret = bh_read(bh, 0);
> -	if (ret > 0)
> -		return bh;
> -	if (ret < 0) {
> -		brelse(bh);
> -		ext2_error(sb, __func__,
> -			    "Cannot read block bitmap - "
> -			    "block_group = %d, block_bitmap = %u",
> -			    block_group, le32_to_cpu(desc->bg_block_bitmap));
> -		return NULL;
> -	}
> -
> -	ext2_valid_block_bitmap(sb, desc, block_group, bh);
> -	/*
> -	 * file system mounted not to panic on error, continue with corrupt
> -	 * bitmap
> -	 */
> -	return bh;

Просьба всегда прогонять scripts/checkpatch.pl на патч.  В патче серьёзные
проблемы с отступами, нужно настроить текстовый редактор для работы с
кодом ядра.

  perl scripts/checkpatch.pl /path/to/patch/file

ERROR: code indent should use tabs where possible
#54: FILE: fs/ext2/balloc.c:149:
+        if (ret < 0) {$

WARNING: please, no spaces at the start of a line
#54: FILE: fs/ext2/balloc.c:149:
+        if (ret < 0) {$

ERROR: code indent should use tabs where possible
#55: FILE: fs/ext2/balloc.c:150:
+                brelse(bh);$

WARNING: please, no spaces at the start of a line
#55: FILE: fs/ext2/balloc.c:150:
+                brelse(bh);$

ERROR: code indent should use tabs where possible
#56: FILE: fs/ext2/balloc.c:151:
+                ext2_error(sb, __func__,$

...

total: 13 errors, 14 warnings, 1 checks, 36 lines checked


> +        if (ret < 0) {
> +                brelse(bh);
> +                ext2_error(sb, __func__,
> +                            "Cannot read block bitmap - "
> +                            "block_group = %d, block_bitmap = %u",
> +                            block_group, le32_to_cpu(desc->bg_block_bitmap));
> +                return NULL;
> +        }
> +        if (!ext2_valid_block_bitmap(sb, desc, block_group, bh)) {
> +                brelse(bh);
> +                return NULL;
> +        }
> +        return bh;

По сути наполовину откатываете изменения коммита 8b91582500ae ("ext2:
retry block allocation if new blocks are allocated from system zone") — он
их всё же для какой-то обозначенной цели делал, поэтому прежде чем
что-либо менять, следует в этом разобраться.

При встрече ошибок/повреждений файловой системы ext2 (и многих других)
есть обычно три варианта, определяемые пользователем:

* errors=continue - вариант Сизколлера, когда при обнаружении повреждения
  метаданных драйвер файловой системы громко ругается в лог ядра (может и
  без WARNING), но продолжает своё функционирование дальше;
* errors=remount-ro - при обнаружении повреждений фс перемонтируется как
  только для чтения, что позволяет снизить вероятность дальнейших проблем;
* errors=panic - ядро запаникует.

В случае проверок внутри ext2_valid_block_bitmap() эти три варианта
выбираются, см. ext2_error().


Пока что на основании коммита 8b91582500ae можно полагать, что файловая
система по крайней мере в этом месте не должна возвращать ошибку о
повреждении наверх.

Следует понять, что именно в поврежденной битовой карте ведёт уже к
проблеме KASAN - возможно какую-то дополнительную обработку нужно делать
ближе к тому месту.

>  }
>  
>  static void group_adjust_blocks(struct super_block *sb, int group_no,
> -- 
> 2.53.0



More information about the lvc-project mailing list