4 # Test the XFS filestreams allocator for use-after-free inode access. The
5 # filestreams allocator uses the MRU and historically kept around unreferenced
6 # inode pointers in each element. These pointers could outlive the inodes they
7 # referred to and thus lead to access of freed or reused memory when the MRU
8 # element was reaped. Test for this problem by performing filestream allocations
9 # against short-lived parent directory inodes.
11 # Note that some form of kernel debug mechanism for use-after-free detection
12 # (i.e., KASAN) is required for this test to reproduce the original problem.
13 # This is because XFS uses a kmem cache for xfs_inode objects which means that
14 # the backing pages for freed inodes may still reside in the cache with the
15 # freed inodes in a partially initialized state.
17 #-----------------------------------------------------------------------
18 # Copyright (c) 2018 Red Hat, Inc. All Rights Reserved.
20 # This program is free software; you can redistribute it and/or
21 # modify it under the terms of the GNU General Public License as
22 # published by the Free Software Foundation.
24 # This program is distributed in the hope that it would be useful,
25 # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 # GNU General Public License for more details.
29 # You should have received a copy of the GNU General Public License
30 # along with this program; if not, write the Free Software Foundation,
31 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #-----------------------------------------------------------------------
36 seqres=$RESULT_DIR/$seq
37 echo "QA output created by $seq"
41 status=1 # failure is the default!
42 trap "_cleanup; exit \$status" 0 1 2 3 15
50 # get standard environment, filters and checks
53 . ./common/filestreams
55 # remove previous $seqres.full before test
58 # real QA test starts here
62 echo 2 > /proc/sys/vm/drop_caches
67 # Modify as appropriate.
70 _require_scratch_size $((2*1024*1024)) # kb
72 # check for filestreams
73 _check_filestreams_support || _notrun "filestreams not available"
75 # use small AGs for frequent stream switching
76 _scratch_mkfs_xfs -d agsize=20m,size=2g >> $seqres.full 2>&1 ||
78 _scratch_mount "-o filestreams"
80 # start background inode reclaim
84 # Stress the filestreams allocator via continuous allocation to a file under
85 # different parent dirs. Remove the old dirs as the file is moved so the MRU
86 # references point to an unlinked inode by the time they are removed. If the
87 # old dir inodes are reclaimed and associated memory reused, MRU cleanup can
88 # access the inode after it's been freed.
90 for i in $(seq 0 90); do
92 $XFS_IO_PROG -fc "falloc $(($i * 20))m 20m" $dir/$i/file
94 mkdir -p $dir/$((i + 1))
95 mv $dir/$i/file $dir/$((i + 1))/file
98 # throttle to ensure this loop sees several cache reclaims
102 kill $pid 2> /dev/null
103 wait $pid 2> /dev/null
105 echo Silence is golden