linux-stable/fs/xfs/libxfs
Guo Xuenan c540284d84 xfs: fix exception caused by unexpected illegal bestcount in leaf dir
[ Upstream commit 13cf24e006 ]

For leaf dir, In most cases, there should be as many bestfree slots
as the dir data blocks that can fit under i_size (except for [1]).

Root cause is we don't examin the number bestfree slots, when the slots
number less than dir data blocks, if we need to allocate new dir data
block and update the bestfree array, we will use the dir block number as
index to assign bestfree array, while we did not check the leaf buf
boundary which may cause UAF or other memory access problem. This issue
can also triggered with test cases xfs/473 from fstests.

According to Dave Chinner & Darrick's suggestion, adding buffer verifier
to detect this abnormal situation in time.
Simplify the testcase for fstest xfs/554 [1]

The error log is shown as follows:
==================================================================
BUG: KASAN: use-after-free in xfs_dir2_leaf_addname+0x1995/0x1ac0
Write of size 2 at addr ffff88810168b000 by task touch/1552
CPU: 5 PID: 1552 Comm: touch Not tainted 6.0.0-rc3+ #101
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0x4d/0x66
 print_report.cold+0xf6/0x691
 kasan_report+0xa8/0x120
 xfs_dir2_leaf_addname+0x1995/0x1ac0
 xfs_dir_createname+0x58c/0x7f0
 xfs_create+0x7af/0x1010
 xfs_generic_create+0x270/0x5e0
 path_openat+0x270b/0x3450
 do_filp_open+0x1cf/0x2b0
 do_sys_openat2+0x46b/0x7a0
 do_sys_open+0xb7/0x130
 do_syscall_64+0x35/0x80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7fe4d9e9312b
Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00 00 00 85 c0
75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00
f0 ff ff 0f 87 91 00 00 00 48 8b 4c 24 28 64 48 33 0c 25
RSP: 002b:00007ffda4c16c20 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fe4d9e9312b
RDX: 0000000000000941 RSI: 00007ffda4c17f33 RDI: 00000000ffffff9c
RBP: 00007ffda4c17f33 R08: 0000000000000000 R09: 0000000000000000
R10: 00000000000001b6 R11: 0000000000000246 R12: 0000000000000941
R13: 00007fe4d9f631a4 R14: 00007ffda4c17f33 R15: 0000000000000000
 </TASK>

The buggy address belongs to the physical page:
page:ffffea000405a2c0 refcount:0 mapcount:0 mapping:0000000000000000
index:0x0 pfn:0x10168b
flags: 0x2fffff80000000(node=0|zone=2|lastcpupid=0x1fffff)
raw: 002fffff80000000 ffffea0004057788 ffffea000402dbc8 0000000000000000
raw: 0000000000000000 0000000000170000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff88810168af00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff88810168af80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88810168b000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
                   ^
 ffff88810168b080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
 ffff88810168b100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================
Disabling lock debugging due to kernel taint
00000000: 58 44 44 33 5b 53 35 c2 00 00 00 00 00 00 00 78
XDD3[S5........x
XFS (sdb): Internal error xfs_dir2_data_use_free at line 1200 of file
fs/xfs/libxfs/xfs_dir2_data.c.  Caller
xfs_dir2_data_use_free+0x28a/0xeb0
CPU: 5 PID: 1552 Comm: touch Tainted: G    B              6.0.0-rc3+
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0x4d/0x66
 xfs_corruption_error+0x132/0x150
 xfs_dir2_data_use_free+0x198/0xeb0
 xfs_dir2_leaf_addname+0xa59/0x1ac0
 xfs_dir_createname+0x58c/0x7f0
 xfs_create+0x7af/0x1010
 xfs_generic_create+0x270/0x5e0
 path_openat+0x270b/0x3450
 do_filp_open+0x1cf/0x2b0
 do_sys_openat2+0x46b/0x7a0
 do_sys_open+0xb7/0x130
 do_syscall_64+0x35/0x80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7fe4d9e9312b
Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00 00 00 85 c0
75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00
f0 ff ff 0f 87 91 00 00 00 48 8b 4c 24 28 64 48 33 0c 25
RSP: 002b:00007ffda4c16c20 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fe4d9e9312b
RDX: 0000000000000941 RSI: 00007ffda4c17f46 RDI: 00000000ffffff9c
RBP: 00007ffda4c17f46 R08: 0000000000000000 R09: 0000000000000001
R10: 00000000000001b6 R11: 0000000000000246 R12: 0000000000000941
R13: 00007fe4d9f631a4 R14: 00007ffda4c17f46 R15: 0000000000000000
 </TASK>
XFS (sdb): Corruption detected. Unmount and run xfs_repair

[1] https://lore.kernel.org/all/20220928095355.2074025-1-guoxuenan@huawei.com/
Reviewed-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Guo Xuenan <guoxuenan@huawei.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
Acked-by: Chandan Babu R <chandanbabu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-11-28 16:56:26 +00:00
..
xfs_ag.c xfs: don't assert fail on perag references on teardown 2023-02-22 12:57:04 +01:00
xfs_ag.h xfs: fix perag reference leak on iteration race with growfs 2022-07-29 17:25:09 +02:00
xfs_ag_resv.c New code for 5.14: 2021-07-02 14:30:27 -07:00
xfs_ag_resv.h xfs: move perag structure and setup to libxfs/xfs_ag.[ch] 2021-06-02 10:48:24 +10:00
xfs_alloc.c xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_alloc.h xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_alloc_btree.c xfs: introduce xfs_buf_daddr() 2021-08-19 10:07:14 -07:00
xfs_alloc_btree.h xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_attr.c xfs: Fix the free logic of state in xfs_attr_node_hasname 2022-07-02 16:41:13 +02:00
xfs_attr.h xfs: rename xfs_has_attr() 2021-08-19 10:07:11 -07:00
xfs_attr_leaf.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_attr_leaf.h xfs: Make attr name schemes consistent 2021-06-09 09:34:05 -07:00
xfs_attr_remote.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_attr_remote.h xfs: Rename __xfs_attr_rmtval_remove 2021-08-11 09:12:45 -07:00
xfs_attr_sf.h xfs: Convert xfs_attr_sf macros to inline functions 2020-09-15 20:52:42 -07:00
xfs_bit.c
xfs_bit.h xfs: Use the correct style for SPDX License Identifier 2020-05-13 15:32:45 -07:00
xfs_bmap.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_bmap.h xfs: mark xfs_bmap_set_attrforkoff static 2021-06-02 14:58:59 -07:00
xfs_bmap_btree.c xfs: introduce xfs_buf_daddr() 2021-08-19 10:07:14 -07:00
xfs_bmap_btree.h xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_btree.c xfs: don't leak btree cursor when insrec fails after a split 2023-02-22 12:57:04 +01:00
xfs_btree.h xfs: constify btree function parameters that are not modified 2021-08-18 18:46:02 -07:00
xfs_btree_staging.c xfs: fix maxlevels comparisons in the btree staging code 2022-07-29 17:25:08 +02:00
xfs_btree_staging.h xfs: xfs_btree_staging.h: delete duplicated words 2020-07-28 20:24:14 -07:00
xfs_cksum.h
xfs_da_btree.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_da_btree.h xfs: Refactor xfs_da_state_alloc() helper 2020-07-28 20:24:14 -07:00
xfs_da_format.h xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_defer.c xfs: only relog deferred intent items if free space in the log gets low 2020-10-07 08:40:29 -07:00
xfs_defer.h xfs: fix an incore inode UAF in xfs_bui_recover 2020-10-07 08:40:28 -07:00
xfs_dir2.c xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_dir2.h xfs: fix an ABBA deadlock in xfs_rename 2021-01-22 16:54:43 -08:00
xfs_dir2_block.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_dir2_data.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_dir2_leaf.c xfs: fix exception caused by unexpected illegal bestcount in leaf dir 2023-11-28 16:56:26 +00:00
xfs_dir2_node.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_dir2_priv.h xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_dir2_sf.c xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_dquot_buf.c xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_errortag.h xfs: add error injection for per-AG resv failure 2021-03-25 16:47:53 -07:00
xfs_format.h xfs: kill xfs_sb_version_has_v3inode() 2021-08-19 10:07:14 -07:00
xfs_fs.h xfs: restore old ioctl definitions 2021-05-20 08:31:22 -07:00
xfs_health.h xfs: Use the correct style for SPDX License Identifier 2020-05-13 15:32:45 -07:00
xfs_ialloc.c xfs: kill xfs_sb_version_has_v3inode() 2021-08-19 10:07:14 -07:00
xfs_ialloc.h xfs: make the record pointer passed to query_range functions const 2021-08-18 18:46:01 -07:00
xfs_ialloc_btree.c xfs: introduce xfs_buf_daddr() 2021-08-19 10:07:14 -07:00
xfs_ialloc_btree.h xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_iext_tree.c xfs: prevent metadata files from being inactivated 2021-03-25 16:47:50 -07:00
xfs_inode_buf.c xfs: validate inode fork size against fork format 2022-09-28 11:11:45 +02:00
xfs_inode_buf.h xfs: kill xfs_sb_version_has_v3inode() 2021-08-19 10:07:14 -07:00
xfs_inode_fork.c xfs: don't leak memory when attr fork loading fails 2023-11-28 16:56:25 +00:00
xfs_inode_fork.h xfs: remove XFS_IFEXTENTS 2021-04-15 09:35:51 -07:00
xfs_log_format.h xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_log_recover.h xfs: convert buf_cancel_table allocation to kmalloc_array 2023-11-28 16:56:25 +00:00
xfs_log_rlimit.c xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_quota_defs.h xfs: remove the active vs running quota differentiation 2021-08-06 11:05:37 -07:00
xfs_refcount.c xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_refcount.h xfs: make the record pointer passed to query_range functions const 2021-08-18 18:46:01 -07:00
xfs_refcount_btree.c xfs: introduce xfs_buf_daddr() 2021-08-19 10:07:14 -07:00
xfs_refcount_btree.h xfs: convert refcount btree cursor to use perags 2021-06-02 10:48:24 +10:00
xfs_rmap.c xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_rmap.h xfs: make the record pointer passed to query_range functions const 2021-08-18 18:46:01 -07:00
xfs_rmap_btree.c xfs: introduce xfs_buf_daddr() 2021-08-19 10:07:14 -07:00
xfs_rmap_btree.h xfs: fix silly whitespace problems with kernel libxfs 2021-08-09 11:13:17 -07:00
xfs_rtbitmap.c xfs: make xfs_rtalloc_query_range input parameters const 2021-08-18 18:46:00 -07:00
xfs_sb.c xfs: don't consider future format versions valid 2023-05-11 23:00:18 +09:00
xfs_sb.h xfs: open code sb verifier feature checks 2021-08-19 10:07:13 -07:00
xfs_shared.h xfs: sort variable alphabetically to avoid repeated declaration 2021-06-02 14:54:09 -07:00
xfs_symlink_remote.c xfs: convert bp->b_bn references to xfs_buf_daddr() 2021-08-19 10:07:15 -07:00
xfs_trans_inode.c xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_trans_resv.c xfs: fix inode reservation space for removing transaction 2023-11-28 16:56:26 +00:00
xfs_trans_resv.h xfs: remove support for disabling quota accounting on a mounted file system 2021-08-06 11:05:36 -07:00
xfs_trans_space.h xfs: convert xfs_sb_version_has checks to use mount features 2021-08-19 10:07:14 -07:00
xfs_types.c xfs: replace xfs_sb_version checks with feature flag checks 2021-08-19 10:07:12 -07:00
xfs_types.h xfs: resolve fork names in trace output 2021-08-19 10:07:10 -07:00