Skip to content

Commit ce2739e

Browse files
chaseyuJaegeuk Kim
authored andcommitted
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: e234088 ("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>
1 parent 3996b70 commit ce2739e

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

fs/f2fs/data.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,14 +378,20 @@ static void f2fs_write_end_io(struct bio *bio)
378378
folio->index != nid_of_node(folio));
379379

380380
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+
381390
if (f2fs_in_warm_node_list(sbi, folio))
382391
f2fs_del_fsync_node_entry(sbi, folio);
383392
folio_clear_f2fs_gcing(folio);
384393
folio_end_writeback(folio);
385394
}
386-
if (!get_pages(sbi, F2FS_WB_CP_DATA) &&
387-
wq_has_sleeper(&sbi->cp_wait))
388-
wake_up(&sbi->cp_wait);
389395

390396
bio_put(bio);
391397
}

0 commit comments

Comments
 (0)