linux-stable/fs/xfs
Darrick J. Wong 0e98a97f77 xfs: verify buffer contents when we skip log replay
commit 22ed903eee upstream.

syzbot detected a crash during log recovery:

XFS (loop0): Mounting V5 Filesystem bfdc47fc-10d8-4eed-a562-11a831b3f791
XFS (loop0): Torn write (CRC failure) detected at log block 0x180. Truncating head block from 0x200.
XFS (loop0): Starting recovery (logdev: internal)
==================================================================
BUG: KASAN: slab-out-of-bounds in xfs_btree_lookup_get_block+0x15c/0x6d0 fs/xfs/libxfs/xfs_btree.c:1813
Read of size 8 at addr ffff88807e89f258 by task syz-executor132/5074

CPU: 0 PID: 5074 Comm: syz-executor132 Not tainted 6.2.0-rc1-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0x1b1/0x290 lib/dump_stack.c:106
 print_address_description+0x74/0x340 mm/kasan/report.c:306
 print_report+0x107/0x1f0 mm/kasan/report.c:417
 kasan_report+0xcd/0x100 mm/kasan/report.c:517
 xfs_btree_lookup_get_block+0x15c/0x6d0 fs/xfs/libxfs/xfs_btree.c:1813
 xfs_btree_lookup+0x346/0x12c0 fs/xfs/libxfs/xfs_btree.c:1913
 xfs_btree_simple_query_range+0xde/0x6a0 fs/xfs/libxfs/xfs_btree.c:4713
 xfs_btree_query_range+0x2db/0x380 fs/xfs/libxfs/xfs_btree.c:4953
 xfs_refcount_recover_cow_leftovers+0x2d1/0xa60 fs/xfs/libxfs/xfs_refcount.c:1946
 xfs_reflink_recover_cow+0xab/0x1b0 fs/xfs/xfs_reflink.c:930
 xlog_recover_finish+0x824/0x920 fs/xfs/xfs_log_recover.c:3493
 xfs_log_mount_finish+0x1ec/0x3d0 fs/xfs/xfs_log.c:829
 xfs_mountfs+0x146a/0x1ef0 fs/xfs/xfs_mount.c:933
 xfs_fs_fill_super+0xf95/0x11f0 fs/xfs/xfs_super.c:1666
 get_tree_bdev+0x400/0x620 fs/super.c:1282
 vfs_get_tree+0x88/0x270 fs/super.c:1489
 do_new_mount+0x289/0xad0 fs/namespace.c:3145
 do_mount fs/namespace.c:3488 [inline]
 __do_sys_mount fs/namespace.c:3697 [inline]
 __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3674
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f89fa3f4aca
Code: 83 c4 08 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fffd5fb5ef8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00646975756f6e2c RCX: 00007f89fa3f4aca
RDX: 0000000020000100 RSI: 0000000020009640 RDI: 00007fffd5fb5f10
RBP: 00007fffd5fb5f10 R08: 00007fffd5fb5f50 R09: 000000000000970d
R10: 0000000000200800 R11: 0000000000000206 R12: 0000000000000004
R13: 0000555556c6b2c0 R14: 0000000000200800 R15: 00007fffd5fb5f50
 </TASK>

The fuzzed image contains an AGF with an obviously garbage
agf_refcount_level value of 32, and a dirty log with a buffer log item
for that AGF.  The ondisk AGF has a higher LSN than the recovered log
item.  xlog_recover_buf_commit_pass2 reads the buffer, compares the
LSNs, and decides to skip replay because the ondisk buffer appears to be
newer.

Unfortunately, the ondisk buffer is corrupt, but recovery just read the
buffer with no buffer ops specified:

	error = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno,
			buf_f->blf_len, buf_flags, &bp, NULL);

Skipping the buffer leaves its contents in memory unverified.  This sets
us up for a kernel crash because xfs_refcount_recover_cow_leftovers
reads the buffer (which is still around in XBF_DONE state, so no read
verification) and creates a refcountbt cursor of height 32.  This is
impossible so we run off the end of the cursor object and crash.

Fix this by invoking the verifier on all skipped buffers and aborting
log recovery if the ondisk buffer is corrupt.  It might be smarter to
force replay the log item atop the buffer and then see if it'll pass the
write verifier (like ext4 does) but for now let's go with the
conservative option where we stop immediately.

Link: https://syzkaller.appspot.com/bug?extid=7e9494b8b399902e994e
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-06-14 11:09:59 +02:00
..
libxfs xfs: don't leak btree cursor when insrec fails after a split 2023-03-22 13:30:06 +01:00
scrub treewide: Change list_sort to use const pointers 2021-09-30 10:11:04 +02:00
Kconfig xfs: fix Kconfig asking about XFS_SUPPORT_V4 when XFS_FS=n 2020-10-16 15:34:28 -07:00
Makefile
kmem.c xfs: remove kmem_realloc() 2020-09-06 18:05:51 -07:00
kmem.h xfs: Remove kmem_zalloc_large() 2020-09-15 20:52:41 -07:00
mrlock.h
xfs.h
xfs_acl.c xfs: Remove kmem_zalloc_large() 2020-09-15 20:52:41 -07:00
xfs_acl.h
xfs_aops.c xfs: drop submit side trans alloc for append ioends 2023-04-26 11:27:37 +02:00
xfs_aops.h
xfs_attr_inactive.c
xfs_attr_list.c xfs: Convert xfs_attr_sf macros to inline functions 2020-09-15 20:52:42 -07:00
xfs_bio_io.c
xfs_bmap_item.c treewide: Change list_sort to use const pointers 2021-09-30 10:11:04 +02:00
xfs_bmap_item.h
xfs_bmap_util.c xfs: set prealloc flag in xfs_alloc_file_space() 2023-03-22 13:30:07 +01:00
xfs_bmap_util.h
xfs_buf.c treewide: Change list_sort to use const pointers 2021-09-30 10:11:04 +02:00
xfs_buf.h xfs: reuse _xfs_buf_read for re-reading the superblock 2020-09-15 20:52:39 -07:00
xfs_buf_item.c xfs: remove dead stale buf unpin handling code 2022-08-03 12:00:51 +02:00
xfs_buf_item.h xfs: move the buffer retry logic to xfs_buf.c 2020-09-15 20:52:38 -07:00
xfs_buf_item_recover.c xfs: verify buffer contents when we skip log replay 2023-06-14 11:09:59 +02:00
xfs_dir2_readdir.c
xfs_discard.c
xfs_discard.h
xfs_dquot.c xfs: fix incorrect root dquot corruption error when switching group/project quota types 2022-06-09 10:21:29 +02:00
xfs_dquot.h xfs: refactor default quota grace period setting code 2020-09-15 20:52:40 -07:00
xfs_dquot_item.c xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_dquot_item.h
xfs_dquot_item_recover.c xfs: rename the ondisk dquot d_flags to d_type 2020-07-28 20:24:14 -07:00
xfs_error.c xfs: ensure xfs_errortag_random_default matches XFS_ERRTAG_MAX 2022-07-07 17:52:19 +02:00
xfs_error.h
xfs_export.c xfs: delete duplicated words + other fixes 2020-08-05 08:49:58 -07:00
xfs_export.h
xfs_extent_busy.c xfs: don't reuse busy extents on extent trim 2023-04-05 11:23:43 +02:00
xfs_extent_busy.h treewide: Change list_sort to use const pointers 2021-09-30 10:11:04 +02:00
xfs_extfree_item.c xfs: use kmem_cache_free() for kmem_cache objects 2022-07-02 16:39:23 +02:00
xfs_extfree_item.h
xfs_file.c xfs: set prealloc flag in xfs_alloc_file_space() 2023-03-22 13:30:07 +01:00
xfs_filestream.c xfs: fix soft lockup via spinning in filestream ag selection loop 2022-09-05 10:28:59 +02:00
xfs_filestream.h
xfs_fsmap.c xfs: fix deadlock and streamline xfs_getfsmap performance 2020-10-07 08:40:29 -07:00
xfs_fsmap.h xfs: fix deadlock and streamline xfs_getfsmap performance 2020-10-07 08:40:29 -07:00
xfs_fsops.c xfs: fix overfilling of reserve pool 2022-09-05 10:28:58 +02:00
xfs_fsops.h
xfs_globals.c
xfs_health.c
xfs_icache.c xfs: fix I_DONTCACHE 2022-08-21 15:15:21 +02:00
xfs_icache.h xfs: remove SYNC_WAIT and SYNC_TRYLOCK 2020-07-14 08:47:33 -07:00
xfs_icreate_item.c xfs: Remove kmem_zone_zalloc() usage 2020-07-28 20:24:14 -07:00
xfs_icreate_item.h
xfs_inode.c xfs: reorder iunlink remove operation in xfs_ifree 2022-09-28 11:10:28 +02:00
xfs_inode.h xfs: widen ondisk inode timestamps to deal with y2038+ 2020-09-15 20:52:41 -07:00
xfs_inode_item.c xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_inode_item.h xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_inode_item_recover.c xfs: logging the on disk inode LSN can make it go backwards 2022-08-03 12:00:51 +02:00
xfs_ioctl.c xfs: reject crazy array sizes being fed to XFS_IOC_GETBMAP* 2022-08-31 17:15:14 +02:00
xfs_ioctl.h xfs: prevent a WARN_ONCE() in xfs_ioc_attr_list() 2022-08-31 17:15:14 +02:00
xfs_ioctl32.c
xfs_ioctl32.h
xfs_iomap.c xfs: only set IOMAP_F_SHARED when providing a srcmap to a write 2022-08-21 15:15:21 +02:00
xfs_iomap.h
xfs_iops.c xfs: use setattr_copy to set vfs inode attributes 2023-03-22 13:30:07 +01:00
xfs_iops.h xfs: remove xfs_setattr_time() declaration 2023-03-22 13:30:08 +01:00
xfs_itable.c
xfs_itable.h
xfs_iwalk.c xfs: fix the forward progress assertion in xfs_iwalk_run_callbacks 2022-06-06 08:42:41 +02:00
xfs_iwalk.h
xfs_linux.h xfs: fix fallocate functions when rtextsize is larger than 1 2020-10-21 09:05:19 -07:00
xfs_log.c xfs: force the log offline when log intent item recovery fails 2022-08-03 12:00:51 +02:00
xfs_log.h xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_log_cil.c xfs: prevent UAF in xfs_log_item_in_current_chkpt 2022-08-03 12:00:51 +02:00
xfs_log_priv.h xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_log_recover.c mm: Add kvrealloc() 2022-08-21 15:15:21 +02:00
xfs_message.c
xfs_message.h treewide: Convert macro and uses of __section(foo) to __section("foo") 2020-10-25 14:51:49 -07:00
xfs_mount.c xfs: don't assert fail on perag references on teardown 2023-03-22 13:30:06 +01:00
xfs_mount.h xfs: remove infinite loop when reserving free block pool 2022-09-05 10:28:58 +02:00
xfs_mru_cache.c
xfs_mru_cache.h
xfs_ondisk.h xfs: Remove typedef xfs_attr_shortform_t 2020-09-15 20:52:42 -07:00
xfs_pnfs.c xfs: use setattr_copy to set vfs inode attributes 2023-03-22 13:30:07 +01:00
xfs_pnfs.h
xfs_pwork.c
xfs_pwork.h
xfs_qm.c xfs: purge dquots after inode walk fails during quotacheck 2023-03-22 13:30:06 +01:00
xfs_qm.h xfs: refactor quota expiration timer modification 2020-09-15 20:52:40 -07:00
xfs_qm_bhv.c xfs: rename XFS_DQ_{USER,GROUP,PROJ} to XFS_DQTYPE_* 2020-07-28 20:24:14 -07:00
xfs_qm_syscalls.c xfs: refactor default quota grace period setting code 2020-09-15 20:52:40 -07:00
xfs_quota.h xfs: move the buffer retry logic to xfs_buf.c 2020-09-15 20:52:38 -07:00
xfs_quotaops.c xfs: create xfs_dqtype_t to represent quota types 2020-07-28 20:24:14 -07:00
xfs_refcount_item.c treewide: Change list_sort to use const pointers 2021-09-30 10:11:04 +02:00
xfs_refcount_item.h
xfs_reflink.c xfs: fix xfs_reflink_unshare usage of filemap_write_and_wait_range 2022-07-07 17:52:20 +02:00
xfs_reflink.h
xfs_rmap_item.c treewide: Change list_sort to use const pointers 2021-09-30 10:11:04 +02:00
xfs_rmap_item.h
xfs_rtalloc.c xfs: annotate grabbing the realtime bitmap/summary locks in growfs 2020-10-13 08:41:31 -07:00
xfs_rtalloc.h
xfs_stats.c xfs: periodically relog deferred intent items 2020-10-07 08:40:28 -07:00
xfs_stats.h xfs: periodically relog deferred intent items 2020-10-07 08:40:28 -07:00
xfs_super.c xfs: only bother with sync_filesystem during readonly remount 2022-08-31 17:15:14 +02:00
xfs_super.h
xfs_symlink.c xfs: set inode size after creating symlink 2022-06-09 10:21:29 +02:00
xfs_symlink.h
xfs_sysctl.c xfs: remove deprecated sysctl options 2020-09-25 11:34:08 -07:00
xfs_sysctl.h
xfs_sysfs.c
xfs_sysfs.h xfs: Fix UBSAN null-ptr-deref in xfs_sysfs_init 2020-08-07 11:50:17 -07:00
xfs_trace.c
xfs_trace.h xfs: periodically relog deferred intent items 2020-10-07 08:40:28 -07:00
xfs_trans.c xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_trans.h xfs: xfs_log_force_lsn isn't passed a LSN 2022-08-03 12:00:50 +02:00
xfs_trans_ail.c xfs: delete duplicated words + other fixes 2020-08-05 08:49:58 -07:00
xfs_trans_buf.c xfs: simplify xfs_trans_getsb 2020-09-15 20:52:39 -07:00
xfs_trans_dquot.c xfs: shut down the filesystem if we screw up quota reservation 2023-04-05 11:23:43 +02:00
xfs_trans_priv.h
xfs_xattr.c