From: Tianxiang Peng <txpeng@xxxxxxxxxxx> 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@xxxxxxxxxxx> Reviewed-by: Qing Zhang <diasyzhang@xxxxxxxxxxx> Reviewed-by: Hao Peng <flyingpeng@xxxxxxxxxxx> Reviewed-by: Jinliang Zheng <alexjlzheng@xxxxxxxxxxx> Reviewed-by: Hui Li <caelli@xxxxxxxxxxx> --- 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