summaryrefslogtreecommitdiff
path: root/tests/xfs/448
blob: 815f56cb4d1a7ebed3222f26e86ab7847c822e2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2018 FUJITSU LIMITED. All Rights Reserved.
#
# FS QA Test No. 448
#
# Regression test for commit:
# 46c59736d809 ("xfs: harden directory integrity checks some more")
#
# If a malicious XFS contains a block+ format directory wherein
# the directory inode's core.mode is corrupted, and there are
# subdirectories of the corrupted directory, an attempt to traverse
# up the directory tree by running xfs_scrub will crash the
# kernel in __xfs_dir3_data_check.
#
# Notice:
# we should have non fatal asserts configured, because assert
# failures triggered by the intentional corrupt would crash system.
#
. ./common/preamble
_begin_fstest auto quick fuzzers

# Import common functions.
. ./common/filter
. ./common/populate

# real QA test starts here
_supported_fs xfs
_require_scratch_nocheck
_require_xfs_io_command "scrub"
# Corrupt XFS on purpose, and skip if assert failures would crash system.
_require_no_xfs_bug_on_assert

rm -f "$seqres.full"

# Format and mount
_scratch_mkfs | _filter_mkfs > $seqres.full 2> $tmp.mkfs
test "${PIPESTATUS[0]}" -eq 0 || _fail "mkfs failed"
_scratch_mount

# Get directory block size
. $tmp.mkfs

# Create a block+(e.g. leaf) format directory
__populate_create_dir "${SCRATCH_MNT}/dir_leaf" "$((dirbsize / 12))"

# Get the block+ directory inode and a subdirectory inode of it
subdino=$(stat -c "%i" "$(find ${SCRATCH_MNT}/dir_leaf/* -type d | head -1)")
dino=$(stat -c "%i" "${SCRATCH_MNT}/dir_leaf")

# Get the subdirectory's generation number
_scratch_unmount
subdgen=$(_scratch_xfs_get_metadata_field "core.gen" "inode $subdino")

# Corrupt the directory inode's core.mode
setmode="0100755"
_scratch_xfs_set_metadata_field "core.mode" "$setmode" "inode $dino" >> $seqres.full
getmode=$(_scratch_xfs_get_metadata_field "core.mode" "inode $dino")
[ "$getmode" != "$setmode" ] && _fail "failed to set core.mode"

# Scrub parent directory in subdirectory (online)
_scratch_mount
$XFS_IO_PROG -x -c "scrub parent $subdino $subdgen" ${SCRATCH_MNT} >> $seqres.full

echo "Silence is golden"

# success, all done
status=0
exit