2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2018 Red Hat, Inc. All Rights Reserved.
7 # Test the XFS filestreams allocator for use-after-free inode access. The
8 # filestreams allocator uses the MRU and historically kept around unreferenced
9 # inode pointers in each element. These pointers could outlive the inodes they
10 # referred to and thus lead to access of freed or reused memory when the MRU
11 # element was reaped. Test for this problem by performing filestream allocations
12 # against short-lived parent directory inodes.
14 # Note that some form of kernel debug mechanism for use-after-free detection
15 # (i.e., KASAN) is required for this test to reproduce the original problem.
16 # This is because XFS uses a kmem cache for xfs_inode objects which means that
17 # the backing pages for freed inodes may still reside in the cache with the
18 # freed inodes in a partially initialized state.
21 _begin_fstest auto quick filestreams
23 # Import common functions.
25 . ./common/filestreams
27 # real QA test starts here
31 echo 2 > /proc/sys/vm/drop_caches
36 # Modify as appropriate.
38 _require_scratch_size $((2*1024*1024)) # kb
39 _require_xfs_io_command "falloc"
41 # check for filestreams
42 _check_filestreams_support || _notrun "filestreams not available"
44 # Disable the scratch rt device to avoid test failures relating to the rt
45 # bitmap consuming free space in our small data device and throwing off the
46 # filestreams allocator.
49 # use small AGs for frequent stream switching
50 _scratch_mkfs_xfs -d agsize=20m,size=2g >> $seqres.full 2>&1 ||
52 _scratch_mount "-o filestreams"
54 # start background inode reclaim
58 # Stress the filestreams allocator via continuous allocation to a file under
59 # different parent dirs. Remove the old dirs as the file is moved so the MRU
60 # references point to an unlinked inode by the time they are removed. If the
61 # old dir inodes are reclaimed and associated memory reused, MRU cleanup can
62 # access the inode after it's been freed.
64 for i in $(seq 0 90); do
66 $XFS_IO_PROG -fc "falloc $(($i * 20))m 20m" $dir/$i/file
68 mkdir -p $dir/$((i + 1))
69 mv $dir/$i/file $dir/$((i + 1))/file
72 # throttle to ensure this loop sees several cache reclaims
76 kill $pid 2> /dev/null
77 wait $pid 2> /dev/null
79 echo Silence is golden