Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

f2fs: fix to avoid UAF in f2fs_write_end_io()

As syzbot reported an use-after-free issue in f2fs_write_end_io().

It is caused by below race condition:

loop device umount
- worker_thread
- loop_process_work
- do_req_filebacked
- lo_rw_aio
- lo_rw_aio_complete
- blk_mq_end_request
- blk_update_request
- f2fs_write_end_io
- dec_page_count
- folio_end_writeback
- kill_f2fs_super
- kill_block_super
- f2fs_put_super
: free(sbi)
: get_pages(, F2FS_WB_CP_DATA)
accessed sbi which is freed

In kill_f2fs_super(), we will drop all page caches of f2fs inodes before
call free(sbi), it guarantee that all folios should end its writeback, so
it should be safe to access sbi before last folio_end_writeback().

Let's relocate ckpt thread wakeup flow before folio_end_writeback() to
resolve this issue.

Cc: stable@kernel.org
Fixes: e234088758fc ("f2fs: avoid wait if IO end up when do_checkpoint for better performance")
Reported-by: syzbot+b4444e3c972a7a124187@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=b4444e3c972a7a124187
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Chao Yu and committed by
Jaegeuk Kim
ce2739e4 3996b702

+9 -3
+9 -3
fs/f2fs/data.c
··· 378 378 folio->index != nid_of_node(folio)); 379 379 380 380 dec_page_count(sbi, type); 381 + 382 + /* 383 + * we should access sbi before folio_end_writeback() to 384 + * avoid racing w/ kill_f2fs_super() 385 + */ 386 + if (type == F2FS_WB_CP_DATA && !get_pages(sbi, type) && 387 + wq_has_sleeper(&sbi->cp_wait)) 388 + wake_up(&sbi->cp_wait); 389 + 381 390 if (f2fs_in_warm_node_list(sbi, folio)) 382 391 f2fs_del_fsync_node_entry(sbi, folio); 383 392 folio_clear_f2fs_gcing(folio); 384 393 folio_end_writeback(folio); 385 394 } 386 - if (!get_pages(sbi, F2FS_WB_CP_DATA) && 387 - wq_has_sleeper(&sbi->cp_wait)) 388 - wake_up(&sbi->cp_wait); 389 395 390 396 bio_put(bio); 391 397 }