From: Vasiliy Kovalev <kovalev@xxxxxxxxxxxx> Detect a failed sb_getblk() call (before copying data) so that null pointer dereferences should not happen any more. Found by Syzkaller: KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f] CPU: 1 PID: 1069 Comm: mark_buffer_dir Tainted: G W 6.10.0-un-def-alt0.rc7 RIP: 0010:bfs_get_block+0x3ab/0xe80 [bfs] Call Trace: <TASK> ? show_regs+0x8d/0xa0 ? die_addr+0x50/0xd0 ? exc_general_protection+0x148/0x220 ? asm_exc_general_protection+0x22/0x30 ? bfs_get_block+0x3ab/0xe80 [bfs] ? bfs_get_block+0x370/0xe80 [bfs] ? __pfx_bfs_get_block+0x10/0x10 [bfs] __block_write_begin_int+0x4ae/0x16a0 ? __pfx_bfs_get_block+0x10/0x10 [bfs] ? __pfx___block_write_begin_int+0x10/0x10 block_write_begin+0xb5/0x410 ? __pfx_bfs_get_block+0x10/0x10 [bfs] bfs_write_begin+0x32/0xe0 [bfs] generic_perform_write+0x265/0x610 ? __pfx_generic_perform_write+0x10/0x10 ? generic_write_checks+0x323/0x4a0 ? __pfx_generic_file_write_iter+0x10/0x10 __generic_file_write_iter+0x16a/0x1b0 generic_file_write_iter+0xf0/0x360 ? __pfx_generic_file_write_iter+0x10/0x10 vfs_write+0x670/0x1120 ? __pfx_vfs_write+0x10/0x10 ksys_write+0x127/0x260 ? __pfx_ksys_write+0x10/0x10 do_syscall_64+0x9f/0x190 ? __ct_user_enter+0x74/0xc0 ? syscall_exit_to_user_mode+0xbb/0x1d0 ? do_syscall_64+0xab/0x190 ? ct_kernel_exit.isra.0+0xbb/0xe0 ? __ct_user_enter+0x74/0xc0 ? syscall_exit_to_user_mode+0xbb/0x1d0 ? do_syscall_64+0xab/0x190 ? ct_kernel_exit.isra.0+0xbb/0xe0 ? clear_bhb_loop+0x45/0xa0 ? clear_bhb_loop+0x45/0xa0 ? clear_bhb_loop+0x45/0xa0 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f2bc708ed29 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot+d98fd19acd08b36ff422@xxxxxxxxxxxxxxxxxxxxxxxxx Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Vasiliy Kovalev <kovalev@xxxxxxxxxxxx> --- fs/bfs/file.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 0dceefc54b48a..e99dc8ace2027 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -34,16 +34,22 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) { struct buffer_head *bh, *new; + int ret = 0; bh = sb_bread(sb, from); if (!bh) return -EIO; new = sb_getblk(sb, to); + if (unlikely(!new)) { + ret = -EIO; + goto out_err_new; + } memcpy(new->b_data, bh->b_data, bh->b_size); mark_buffer_dirty(new); - bforget(bh); brelse(new); - return 0; +out_err_new: + bforget(bh); + return ret; } static int bfs_move_blocks(struct super_block *sb, unsigned long start, -- 2.33.8