[lvc-project] [PATCH 3/3] ext2: refuse to return a non-uptodate bh from read_block_bitmap()

Fedor Pchelkin pchelkin at ispras.ru
Tue May 12 17:29:55 MSK 2026


On Tue, 12. May 15:22, Denis Zubov wrote:
> bh_read() can return >= 0 while leaving the buffer not uptodate on
> some failure paths. read_block_bitmap() previously ignored this and
> returned the bh anyway, which let callers operate on unreliable
> b_data.
> 
> Treat !buffer_uptodate() after bh_read() as a hard failure: release
> the buffer and return NULL so callers take the existing io_error
> path. This complements the bg_block_bitmap range check and makes
> read_block_bitmap() reject all known ways of producing a buffer
> whose data cannot be trusted.

Есть основания полагать, что используете ЛЛМ для генерации описания и/или
diff патчей.  Это не упрёк и не что-либо подобное (может быть вы его и не
используете вовсе, знать не могу), но на всякий случай предупрежу - эта
штука может даже закоренелых мэйнтейнеров уболтать в самой что ни на есть
заковыристой форме, не говоря уже о нас с вами.


Не понимаю, в чём решаемая патчем проблема, как вы её встретили и
отладили.  Вроде как bh_read() делает всё от неё зависящее для возврата
uptodate буфера, в ином случае она выдаёт отрицательный статус ошибки,
который в этом коде обрабатывается.

> 
> 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 | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
> index 10e3b100d390..06045aec68d4 100644
> --- a/fs/ext2/balloc.c
> +++ b/fs/ext2/balloc.c
> @@ -168,6 +168,20 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
>  		return NULL;
>  	}
>  
> +	/*
> +	 * bh_read could return 0 ("already in cache") or 1 ("read OK"),
> +	 * but the buffer may still be !uptodate if the underlying I/O
> +	 * silently failed. In that case b_data is unreliable and using

Как то что выше соотносится с собственно реализацией этой функции?

/* Returns 1 if buffer uptodated, 0 on success, and -EIO on error. */
static inline int bh_read(struct buffer_head *bh, blk_opf_t op_flags)
{
	if (bh_uptodate_or_lock(bh))
		return 1;
	return __bh_read(bh, op_flags, true);
}

/**
 * __bh_read - Submit read for a locked buffer
 * @bh: struct buffer_head
 * @op_flags: appending REQ_OP_* flags besides REQ_OP_READ
 * @wait: wait until reading finish
 *
 * Returns zero on success or don't wait, and -EIO on error.
 */
int __bh_read(struct buffer_head *bh, blk_opf_t op_flags, bool wait)
{
	int ret = 0;

	BUG_ON(!buffer_locked(bh));

	get_bh(bh);
	bh->b_end_io = end_buffer_read_sync;
	submit_bh(REQ_OP_READ | op_flags, bh);
	if (wait) {
		wait_on_buffer(bh);
		if (!buffer_uptodate(bh))
			ret = -EIO;
	}
	return ret;
}
EXPORT_SYMBOL(__bh_read);

> +	 * it leads to UAF/OOB in ext2_try_to_allocate / ext2_free_blocks.
> +	 */
> +	if (!buffer_uptodate(bh)) {
> +		brelse(bh);
> +		ext2_error(sb, __func__,
> +			   "Block bitmap not uptodate - 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
> -- 
> 2.53.0



More information about the lvc-project mailing list