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

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


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.

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
+	 * 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