[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250603085056.191073-1-txpeng@tencent.com>
Date: Tue, 3 Jun 2025 16:50:56 +0800
From: luminosity1999@...il.com
To: chandan.babu@...cle.com
Cc: linux-xfs@...r.kernel.org,
linux-kernel@...r.kernel.org,
Tianxiang Peng <txpeng@...cent.com>,
Qing Zhang <diasyzhang@...cent.com>,
Hao Peng <flyingpeng@...cent.com>,
Jinliang Zheng <alexjlzheng@...cent.com>,
Hui Li <caelli@...cent.com>
Subject: [PATCH 5.4] xfs: Reset cnt_cur to NULL after deletion to prevent UAF
From: Tianxiang Peng <txpeng@...cent.com>
Our test environment detected a use-after-free bug in XFS:
[ 1396.210852] Allocated by task 26155:
[ 1396.212769] save_stack+0x21/0x90
[ 1396.214670] __kasan_kmalloc.constprop.8+0xc1/0xd0
[ 1396.216738] kasan_slab_alloc+0x11/0x20
[ 1396.218694] kmem_cache_alloc+0xfb/0x280
[ 1396.220750] kmem_zone_alloc+0xb9/0x240 [xfs]
[ 1396.222859] xfs_allocbt_init_cursor+0x60/0x270 [xfs]
[ 1396.225058] xfs_alloc_ag_vextent_near+0x2bc/0x1aa0 [xfs]
[ 1396.227312] xfs_alloc_ag_vextent+0x3a0/0x5a0 [xfs]
[ 1396.229503] xfs_alloc_vextent+0xc11/0xd80 [xfs]
[ 1396.231665] xfs_bmap_btalloc+0x632/0xf20 [xfs]
[ 1396.233804] xfs_bmap_alloc+0x78/0x90 [xfs]
[ 1396.235883] xfs_bmapi_allocate+0x243/0x760 [xfs]
[ 1396.238032] xfs_bmapi_convert_delalloc+0x3cf/0x850 [xfs]
[ 1396.240267] xfs_map_blocks+0x352/0x820 [xfs]
[ 1396.242379] xfs_do_writepage+0x2c2/0x8d0 [xfs]
[ 1396.244417] write_cache_pages+0x341/0x760
[ 1396.246490] xfs_vm_writepages+0xc8/0x120 [xfs]
[ 1396.248755] do_writepages+0x8f/0x160
[ 1396.250710] __filemap_fdatawrite_range+0x1a4/0x200
[ 1396.252823] filemap_flush+0x1c/0x20
[ 1396.254847] xfs_release+0x1b3/0x1f0 [xfs]
[ 1396.256920] xfs_file_release+0x15/0x20 [xfs]
[ 1396.258936] __fput+0x155/0x390
[ 1396.260781] ____fput+0xe/0x10
[ 1396.262620] task_work_run+0xbf/0xe0
[ 1396.264492] exit_to_usermode_loop+0x11d/0x120
[ 1396.266496] do_syscall_64+0x1c3/0x1f0
[ 1396.268391] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 1396.272067] Freed by task 26155:
[ 1396.273909] save_stack+0x21/0x90
[ 1396.275758] __kasan_slab_free+0x131/0x180
[ 1396.277722] kasan_slab_free+0xe/0x10
[ 1396.279627] kmem_cache_free+0x8c/0x2c0
[ 1396.281625] xfs_btree_del_cursor+0xb2/0x100 [xfs]
[ 1396.283739] xfs_alloc_ag_vextent_near+0x90b/0x1aa0 [xfs]
[ 1396.285932] xfs_alloc_ag_vextent+0x3a0/0x5a0 [xfs]
[ 1396.288049] xfs_alloc_vextent+0xc11/0xd80 [xfs]
[ 1396.290065] xfs_bmap_btalloc+0x632/0xf20 [xfs]
[ 1396.292008] xfs_bmap_alloc+0x78/0x90 [xfs]
[ 1396.293871] xfs_bmapi_allocate+0x243/0x760 [xfs]
[ 1396.295801] xfs_bmapi_convert_delalloc+0x3cf/0x850 [xfs]
[ 1396.297811] xfs_map_blocks+0x352/0x820 [xfs]
[ 1396.299706] xfs_do_writepage+0x2c2/0x8d0 [xfs]
[ 1396.301522] write_cache_pages+0x341/0x760
[ 1396.303379] xfs_vm_writepages+0xc8/0x120 [xfs]
[ 1396.305204] do_writepages+0x8f/0x160
[ 1396.306902] __filemap_fdatawrite_range+0x1a4/0x200
[ 1396.308756] filemap_flush+0x1c/0x20
[ 1396.310545] xfs_release+0x1b3/0x1f0 [xfs]
[ 1396.312386] xfs_file_release+0x15/0x20 [xfs]
[ 1396.314180] __fput+0x155/0x390
[ 1396.315825] ____fput+0xe/0x10
[ 1396.317442] task_work_run+0xbf/0xe0
[ 1396.319126] exit_to_usermode_loop+0x11d/0x120
[ 1396.320928] do_syscall_64+0x1c3/0x1f0
[ 1396.322648] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 1396.325958] The buggy address belongs to the object at ffff8898039945a0
which belongs to the cache xfs_btree_cur of size 224
[ 1396.330097] The buggy address is located 181 bytes inside of
224-byte region [ffff8898039945a0, ffff889803994680)
This issue stems from an incomplete backport of upstream commit
8ebbf262d468 ("xfs: don't block in busy flushing when freeing
extents") to the 5.4 LTS kernel. The backport introduced error
handling that may goto error0 when xfs_extent_busy_flush() fails:
- xfs_extent_busy_flush(args->mp, args->pag, busy_gen,
- alloc_flags);
+ error = xfs_extent_busy_flush(args->tp, args->pag,
+ busy_gen, alloc_flags);
+ if (error)
+ goto error0;
However, in the 5.4 codebase, the existing cursor deletion logic
failed to reset cnt_cur to NULL after deletion. While the original
code's goto restart path reinitialized the cursor, the new goto
error0 path attempts to delete an already-freed cursor (now
dangling pointer), causing a use-after-free. Reset cnt_cur to NULL
after deletion to prevent double-free. This aligns with the cursor
management pattern used at other deletion sites in the same
function.
This pitfall was eliminated in 5.15+ LTS kernels via XFS code
refactoring, making the fix unnecessary for newer versions.
Signed-off-by: Tianxiang Peng <txpeng@...cent.com>
Reviewed-by: Qing Zhang <diasyzhang@...cent.com>
Reviewed-by: Hao Peng <flyingpeng@...cent.com>
Reviewed-by: Jinliang Zheng <alexjlzheng@...cent.com>
Reviewed-by: Hui Li <caelli@...cent.com>
---
fs/xfs/libxfs/xfs_alloc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 1193fd6e4..ff0c05901 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -1417,6 +1417,7 @@ xfs_alloc_ag_vextent_near(
*/
if (bno_cur_lt == NULL && bno_cur_gt == NULL) {
xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
+ cnt_cur = NULL;
if (busy) {
trace_xfs_alloc_near_busy(args);
--
2.43.5
Powered by blists - more mailing lists