[PATCH] xfs: fix use-after-free in xfs_cui_release()

Ye Bin posted 1 patch 1 month, 2 weeks ago
fs/xfs/xfs_log_recover.c | 1 +
1 file changed, 1 insertion(+)
[PATCH] xfs: fix use-after-free in xfs_cui_release()
Posted by Ye Bin 1 month, 2 weeks ago
From: Ye Bin <yebin10@huawei.com>

There's issue as follows when do IO fault injection:
 XFS (loop0): Filesystem has been shut down due to log error (0x2).
 XFS (loop0): Please unmount the filesystem and rectify the problem(s).
 XFS (loop0): Failed to recover intents
 XFS (loop0): log mount finish failed
 ==================================================================
 BUG: KASAN: slab-use-after-free in xfs_cui_release+0x20/0xe0
 Read of size 4 at addr ffff88826d204098 by task kworker/u18:4/252

 CPU: 7 PID: 252 Comm: kworker/u18:4 Not tainted 6.3.0-next #446
 Workqueue: xfs-cil/loop0 xlog_cil_push_work
 Call Trace:
  <TASK>
  dump_stack_lvl+0xd9/0x150
  print_report+0xc1/0x5e0
  kasan_report+0x96/0xc0
  kasan_check_range+0x13f/0x1a0
  xfs_cui_release+0x20/0xe0
  xfs_cud_item_release+0x37/0x80
  xfs_trans_committed_bulk+0x337/0x8f0
  xlog_cil_committed+0xc08/0x1010
  xlog_cil_push_work+0x1cb4/0x25f0
  process_one_work+0x9cf/0x1610
  worker_thread+0x63a/0x10a0
  kthread+0x343/0x440
  ret_from_fork+0x1f/0x30
  </TASK>

 Allocated by task 8537:
  kasan_save_stack+0x22/0x40
  kasan_set_track+0x25/0x30
  __kasan_slab_alloc+0x7f/0x90
  slab_post_alloc_hook+0x65/0x560
  kmem_cache_alloc+0x1cf/0x440
  xfs_cui_init+0x1a8/0x1e0
  xlog_recover_cui_commit_pass2+0x137/0x440
  xlog_recover_items_pass2+0xd8/0x310
  xlog_recover_commit_trans+0x958/0xb20
  xlog_recovery_process_trans+0x13a/0x1e0
  xlog_recover_process_ophdr+0x1e9/0x410
  xlog_recover_process_data+0x19c/0x400
  xlog_recover_process+0x257/0x2e0
  xlog_do_recovery_pass+0x70c/0xf90
  xlog_do_log_recovery+0x9e/0x100
  xlog_do_recover+0xdf/0x5a0
  xlog_recover+0x2a8/0x500
  xfs_log_mount+0x36e/0x790
  xfs_mountfs+0x133a/0x2220
  xfs_fs_fill_super+0x1376/0x1f10
  get_tree_bdev+0x44a/0x770
  vfs_get_tree+0x8d/0x350
  path_mount+0x1228/0x1cc0
  do_mount+0xf7/0x110
  __x64_sys_mount+0x193/0x230
  do_syscall_64+0x39/0xb0
  entry_SYSCALL_64_after_hwframe+0x63/0xcd

 Freed by task 8537:
  kasan_save_stack+0x22/0x40
  kasan_set_track+0x25/0x30
  kasan_save_free_info+0x2e/0x40
  __kasan_slab_free+0x11f/0x1b0
  kmem_cache_free+0xf2/0x670
  xfs_cui_item_free+0xa4/0xc0
  xfs_cui_release+0xa0/0xe0
  xlog_recover_cancel_intents.isra.0+0xf4/0x200
  xlog_recover_finish+0x87f/0xa20
  xfs_log_mount_finish+0x325/0x570
  xfs_mountfs+0x16ba/0x2220
  xfs_fs_fill_super+0x1376/0x1f10
  get_tree_bdev+0x44a/0x770
  vfs_get_tree+0x8d/0x350
  path_mount+0x1228/0x1cc0
  do_mount+0xf7/0x110
  __x64_sys_mount+0x193/0x230
  do_syscall_64+0x39/0xb0
  entry_SYSCALL_64_after_hwframe+0x63/0xcd

As xlog_recover_process_intents() failed will trigger LOG shutdown will not
push CIL. Then xlog_recover_finish() will remove log item from AIL list and
release log item. However xlog_cil_push_work() perhaps concurrent
processing this log item, then trigger UAF.
To solve above issue, there's need to make sure all CIL is pushed before
cancel intent item.

Fixes: deb4cd8ba87f ("xfs: transfer recovered intent item ownership in ->iop_recover")
Signed-off-by: Ye Bin <yebin10@huawei.com>
---
 fs/xfs/xfs_log_recover.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 1997981827fb..54faa0608958 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3521,6 +3521,7 @@ xlog_recover_finish(
 		 * (inode reclaim does this) before we get around to
 		 * xfs_log_mount_cancel.
 		 */
+		xfs_log_force(log->l_mp, XFS_LOG_SYNC);
 		xlog_recover_cancel_intents(log);
 		xfs_alert(log->l_mp, "Failed to recover intents");
 		xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
-- 
2.31.1