Skip to content

Commit 7b0033d

Browse files
Long LiJaegeuk Kim
Long Li
authored and
Jaegeuk Kim
committed
f2fs: fix race in concurrent f2fs_stop_gc_thread
In my test case, concurrent calls to f2fs shutdown report the following stack trace: Oops: general protection fault, probably for non-canonical address 0xc6cfff63bb5513fc: 0000 [#1] PREEMPT SMP PTI CPU: 0 UID: 0 PID: 678 Comm: f2fs_rep_shutdo Not tainted 6.12.0-rc5-next-20241029-g6fb2fa9805c5-dirty torvalds#85 Call Trace: <TASK> ? show_regs+0x8b/0xa0 ? __die_body+0x26/0xa0 ? die_addr+0x54/0x90 ? exc_general_protection+0x24b/0x5c0 ? asm_exc_general_protection+0x26/0x30 ? kthread_stop+0x46/0x390 f2fs_stop_gc_thread+0x6c/0x110 f2fs_do_shutdown+0x309/0x3a0 f2fs_ioc_shutdown+0x150/0x1c0 __f2fs_ioctl+0xffd/0x2ac0 f2fs_ioctl+0x76/0xe0 vfs_ioctl+0x23/0x60 __x64_sys_ioctl+0xce/0xf0 x64_sys_call+0x2b1b/0x4540 do_syscall_64+0xa7/0x240 entry_SYSCALL_64_after_hwframe+0x76/0x7e The root cause is a race condition in f2fs_stop_gc_thread() called from different f2fs shutdown paths: [CPU0] [CPU1] ---------------------- ----------------------- f2fs_stop_gc_thread f2fs_stop_gc_thread gc_th = sbi->gc_thread gc_th = sbi->gc_thread kfree(gc_th) sbi->gc_thread = NULL < gc_th != NULL > kthread_stop(gc_th->f2fs_gc_task) //UAF The commit c7f114d ("f2fs: fix to avoid use-after-free in f2fs_stop_gc_thread()") attempted to fix this issue by using a read semaphore to prevent races between shutdown and remount threads, but it fails to prevent all race conditions. Fix it by converting to write lock of s_umount in f2fs_do_shutdown(). Fixes: 7950e9a ("f2fs: stop gc/discard thread after fs shutdown") Signed-off-by: Long Li <leo.lilong@huawei.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent a7a7c1d commit 7b0033d

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

fs/f2fs/file.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -2365,9 +2365,12 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
23652365
if (readonly)
23662366
goto out;
23672367

2368-
/* grab sb->s_umount to avoid racing w/ remount() */
2368+
/*
2369+
* grab sb->s_umount to avoid racing w/ remount() and other shutdown
2370+
* paths.
2371+
*/
23692372
if (need_lock)
2370-
down_read(&sbi->sb->s_umount);
2373+
down_write(&sbi->sb->s_umount);
23712374

23722375
f2fs_stop_gc_thread(sbi);
23732376
f2fs_stop_discard_thread(sbi);
@@ -2376,7 +2379,7 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
23762379
clear_opt(sbi, DISCARD);
23772380

23782381
if (need_lock)
2379-
up_read(&sbi->sb->s_umount);
2382+
up_write(&sbi->sb->s_umount);
23802383

23812384
f2fs_update_time(sbi, REQ_TIME);
23822385
out:

0 commit comments

Comments
 (0)