forked from kdave/xfstests
-
Notifications
You must be signed in to change notification settings - Fork 0
/
verity
244 lines (213 loc) · 6.43 KB
/
verity
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# SPDX-License-Identifier: GPL-2.0
# Copyright 2018 Google LLC
#
# Functions for setting up and testing fs-verity
_require_scratch_verity()
{
_require_scratch
_require_command "$FSVERITY_PROG" fsverity
if ! _scratch_mkfs_verity &>>$seqres.full; then
# ext4: need e2fsprogs v1.44.5 or later (but actually v1.45.2+
# is needed for some tests to pass, due to an e2fsck bug)
# f2fs: need f2fs-tools v1.11.0 or later
_notrun "$FSTYP userspace tools don't support fs-verity"
fi
# Try to mount the filesystem. If this fails then either the kernel
# isn't aware of fs-verity, or the mkfs options were not compatible with
# verity (e.g. ext4 with block size != PAGE_SIZE).
if ! _try_scratch_mount &>>$seqres.full; then
_notrun "kernel is unaware of $FSTYP verity feature," \
"or mkfs options are not compatible with verity"
fi
# The filesystem may be aware of fs-verity but have it disabled by
# CONFIG_FS_VERITY=n. Detect support via sysfs.
if [ ! -e /sys/fs/$FSTYP/features/verity ]; then
_notrun "kernel $FSTYP isn't configured with verity support"
fi
# The filesystem may have fs-verity enabled but not actually usable by
# default. E.g., ext4 only supports verity on extent-based files, so it
# doesn't work on ext3-style filesystems. So, try actually using it.
echo foo > $SCRATCH_MNT/tmpfile
_disable_fsverity_signatures
if ! _fsv_enable $SCRATCH_MNT/tmpfile; then
_restore_fsverity_signatures
_notrun "$FSTYP verity isn't usable by default with these mkfs options"
fi
_restore_fsverity_signatures
rm -f $SCRATCH_MNT/tmpfile
_scratch_unmount
# Merkle tree block size. Currently all filesystems only support
# PAGE_SIZE for this. This is also the default for 'fsverity enable'.
FSV_BLOCK_SIZE=$(get_page_size)
}
# Check for CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y.
_require_fsverity_builtin_signatures()
{
if [ ! -e /proc/sys/fs/verity/require_signatures ]; then
_notrun "kernel doesn't support fs-verity builtin signatures"
fi
}
# Disable mandatory signatures for fs-verity files, if they are supported.
_disable_fsverity_signatures()
{
if [ -e /proc/sys/fs/verity/require_signatures ]; then
if [ -z "$FSVERITY_SIG_CTL_ORIG" ]; then
FSVERITY_SIG_CTL_ORIG=$(</proc/sys/fs/verity/require_signatures)
fi
echo 0 > /proc/sys/fs/verity/require_signatures
fi
}
# Enable mandatory signatures for fs-verity files.
# This assumes that _require_fsverity_builtin_signatures() was called.
_enable_fsverity_signatures()
{
if [ -z "$FSVERITY_SIG_CTL_ORIG" ]; then
FSVERITY_SIG_CTL_ORIG=$(</proc/sys/fs/verity/require_signatures)
fi
echo 1 > /proc/sys/fs/verity/require_signatures
}
# Restore the original signature verification setting.
_restore_fsverity_signatures()
{
if [ -n "$FSVERITY_SIG_CTL_ORIG" ]; then
echo "$FSVERITY_SIG_CTL_ORIG" > /proc/sys/fs/verity/require_signatures
fi
}
_scratch_mkfs_verity()
{
case $FSTYP in
ext4|f2fs)
_scratch_mkfs -O verity
;;
*)
_notrun "No verity support for $FSTYP"
;;
esac
}
_scratch_mkfs_encrypted_verity()
{
case $FSTYP in
ext4)
_scratch_mkfs -O encrypt,verity
;;
f2fs)
# f2fs-tools as of v1.11.0 doesn't allow comma-separated
# features with -O. Instead -O must be supplied multiple times.
_scratch_mkfs -O encrypt -O verity
;;
*)
_notrun "$FSTYP not supported in _scratch_mkfs_encrypted_verity"
;;
esac
}
_fsv_scratch_begin_subtest()
{
local msg=$1
rm -rf "${SCRATCH_MNT:?}"/*
echo -e "\n# $msg"
}
_fsv_enable()
{
$FSVERITY_PROG enable "$@"
}
_fsv_measure()
{
$FSVERITY_PROG measure "$@" | awk '{print $1}'
}
_fsv_sign()
{
$FSVERITY_PROG sign "$@"
}
# Generate a file, then enable verity on it.
_fsv_create_enable_file()
{
local file=$1
shift
head -c $((FSV_BLOCK_SIZE * 2)) /dev/zero > "$file"
_fsv_enable "$file" "$@"
}
_fsv_have_hash_algorithm()
{
local hash_alg=$1
local test_file=$2
rm -f $test_file
head -c 4096 /dev/zero > $test_file
if ! _fsv_enable --hash-alg=$hash_alg $test_file &>> $seqres.full; then
# no kernel support
return 1
fi
rm -f $test_file
return 0
}
#
# _fsv_scratch_corrupt_bytes - Write some bytes to a file, bypassing the filesystem
#
# Write the bytes sent on stdin to the given offset in the given file, but do so
# by writing directly to the extents on the block device, with the filesystem
# unmounted. This can be used to corrupt a verity file for testing purposes,
# bypassing the restrictions imposed by the filesystem.
#
# The file is assumed to be located on $SCRATCH_DEV.
#
_fsv_scratch_corrupt_bytes()
{
local file=$1
local offset=$2
local lstart lend pstart pend
local dd_cmds=()
local cmd
sync # Sync to avoid unwritten extents
cat > $tmp.bytes
local end=$(( offset + $(_get_filesize $tmp.bytes ) ))
# For each extent that intersects the requested range in order, add a
# command that writes the next part of the data to that extent.
while read -r lstart lend pstart pend; do
lstart=$((lstart * 512))
lend=$(((lend + 1) * 512))
pstart=$((pstart * 512))
pend=$(((pend + 1) * 512))
if (( lend - lstart != pend - pstart )); then
_fail "Logical and physical extent lengths differ for file '$file'"
elif (( offset < lstart )); then
_fail "Hole in file '$file' at byte $offset. Next extent begins at byte $lstart"
elif (( offset < lend )); then
local len=$((lend - offset))
local seek=$((pstart + (offset - lstart)))
dd_cmds+=("head -c $len | dd of=$SCRATCH_DEV oflag=seek_bytes seek=$seek status=none")
(( offset += len ))
fi
done < <($XFS_IO_PROG -r -c "fiemap $offset $((end - offset))" "$file" \
| _filter_xfs_io_fiemap)
if (( offset < end )); then
_fail "Extents of file '$file' ended at byte $offset, but needed until $end"
fi
# Execute the commands to write the data
_scratch_unmount
for cmd in "${dd_cmds[@]}"; do
eval "$cmd"
done < $tmp.bytes
sync # Sync to flush the block device's pagecache
_scratch_mount
}
#
# _fsv_scratch_corrupt_merkle_tree - Corrupt a file's Merkle tree
#
# Like _fsv_scratch_corrupt_bytes(), but this corrupts the file's fs-verity
# Merkle tree. The offset is given as a byte offset into the Merkle tree.
#
_fsv_scratch_corrupt_merkle_tree()
{
local file=$1
local offset=$2
case $FSTYP in
ext4|f2fs)
# ext4 and f2fs store the Merkle tree after the file contents
# itself, starting at the next 65536-byte aligned boundary.
(( offset += ($(_get_filesize $file) + 65535) & ~65535 ))
_fsv_scratch_corrupt_bytes $file $offset
;;
*)
_fail "_fsv_scratch_corrupt_merkle_tree() unimplemented on $FSTYP"
;;
esac
}