[lvc-project] [PATCH] f2fs: Add a flush_work() call before destroying raw_super

Andrey Tsygunka aitsygunka at yandex.ru
Wed Apr 29 13:32:06 MSK 2026


KASAN reports a use-after-free in f2fs_record_stop_reason(), called
from f2fs_record_error_work() during the execution of s_error_work.

The error occurs when attempting to access sbi->raw_super after it
was freed in f2fs_fill_super().

The reason for this error is that some superblock initialization error
handling in f2fs_fill_super() frees raw_super while s_error_work has
not yet completed execution, leading to a race condition
and use-after-free.

To prevent this race condition, add flush_work(&sbi->s_error_work)
before kfree(raw_super).

Reported by syzkaller:
 BUG: KASAN: slab-use-after-free in f2fs_record_stop_reason fs/f2fs/super.c:4151 [inline]
 BUG: KASAN: slab-use-after-free in f2fs_record_error_work+0x11e/0x210 fs/f2fs/super.c:4256
 Write of size 16 at addr ffff888026d52aea by task kworker/1:4/862

 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
 Workqueue:events f2fs_record_error_work
 Call Trace:
  <TASK>
  __dump_stack lib/dump_stack.c:94 [inline]
  dump_stack_lvl+0xcf/0x130 lib/dump_stack.c:120
  print_address_description mm/kasan/report.c:377 [inline]
  print_report+0xc1/0x600 mm/kasan/report.c:481
  kasan_report+0xbd/0xf0 mm/kasan/report.c:594
  check_region_inline mm/kasan/generic.c:183 [inline]
  kasan_check_range+0xf4/0x1a0 mm/kasan/generic.c:189
  __asan_memcpy+0x3d/0x60 mm/kasan/shadow.c:106
  f2fs_record_stop_reason fs/f2fs/super.c:4151 [inline]
  f2fs_record_error_work+0x11e/0x210 fs/f2fs/super.c:4256
  process_one_work+0x91e/0x1a60 kernel/workqueue.c:3252
  process_scheduled_works kernel/workqueue.c:3333 [inline]
  worker_thread+0x677/0xe80 kernel/workqueue.c:3414
  kthread+0x333/0x440 kernel/kthread.c:389
  ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:152
  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
  </TASK>

 Allocated by task 5537:
  kasan_save_stack+0x24/0x50 mm/kasan/common.c:48
  kasan_save_track+0x14/0x30 mm/kasan/common.c:69
  poison_kmalloc_redzone mm/kasan/common.c:378 [inline]
  __kasan_kmalloc+0x7f/0x90 mm/kasan/common.c:395
  kmalloc_noprof include/linux/slab.h:878 [inline]
  kzalloc_noprof include/linux/slab.h:1014 [inline]
  read_raw_super_block fs/f2fs/super.c:4047 [inline]
  f2fs_fill_super+0x3a9/0x8ab0 fs/f2fs/super.c:4517
  mount_bdev+0x1e9/0x2e0 fs/super.c:1693
  legacy_get_tree+0x10c/0x220 fs/fs_context.c:662
  vfs_get_tree+0x94/0x380 fs/super.c:1814
  do_new_mount fs/namespace.c:3564 [inline]
  path_mount+0x6b2/0x1f90 fs/namespace.c:3891
  do_mount fs/namespace.c:3904 [inline]
  __do_sys_mount fs/namespace.c:4114 [inline]
  __se_sys_mount fs/namespace.c:4091 [inline]
  __x64_sys_mount+0x284/0x310 fs/namespace.c:4091
  do_syscall_x64 arch/x86/entry/common.c:47 [inline]
  do_syscall_64+0x68/0x140 arch/x86/entry/common.c:78
  entry_SYSCALL_64_after_hwframe+0x76/0x7e

 Freed by task 5537:
  kasan_save_stack+0x24/0x50 mm/kasan/common.c:48
  kasan_save_track+0x14/0x30 mm/kasan/common.c:69
  kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:579
  poison_slab_object mm/kasan/common.c:248 [inline]
  __kasan_slab_free+0x38/0x50 mm/kasan/common.c:265
  kasan_slab_free include/linux/kasan.h:234 [inline]
  slab_free_hook mm/slub.c:2393 [inline]
  slab_free mm/slub.c:4651 [inline]
  kfree+0x13d/0x4a0 mm/slub.c:4803
  f2fs_fill_super+0x437b/0x8ab0 fs/f2fs/super.c:4957
  mount_bdev+0x1e9/0x2e0 fs/super.c:1693
  legacy_get_tree+0x10c/0x220 fs/fs_context.c:662
  vfs_get_tree+0x94/0x380 fs/super.c:1814
  do_new_mount fs/namespace.c:3564 [inline]
  path_mount+0x6b2/0x1f90 fs/namespace.c:3891
  do_mount fs/namespace.c:3904 [inline]
  __do_sys_mount fs/namespace.c:4114 [inline]
  __se_sys_mount fs/namespace.c:4091 [inline]
  __x64_sys_mount+0x284/0x310 fs/namespace.c:4091
  do_syscall_x64 arch/x86/entry/common.c:47 [inline]
  do_syscall_64+0x68/0x140 arch/x86/entry/common.c:78
  entry_SYSCALL_64_after_hwframe+0x76/0x7e

Fixes: b62e71be2110 ("f2fs: support errors=remount-ro|continue|panic mountoption")
Signed-off-by: Andrey Tsygunka <aitsygunka at yandex.ru>
---
 fs/f2fs/super.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index ccf806b676f5..e9fe57e4aef2 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -5449,6 +5449,8 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
 	/* no need to free dummy_enc_policy, we just keep it in ctx when failed */
 	swap(F2FS_CTX_INFO(ctx).dummy_enc_policy, F2FS_OPTION(sbi).dummy_enc_policy);
 free_sb_buf:
+	/* flush s_error_work before raw_super destroy */
+	flush_work(&sbi->s_error_work);
 	kfree(raw_super);
 free_sbi:
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-- 
2.25.1




More information about the lvc-project mailing list