summaryrefslogtreecommitdiffstats
path: root/tests/device-test
blob: c8b53bbfc6cc56cede62d08889798232c83cab46 (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
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#!/bin/bash

[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
MNT_DIR="./mnt_luks"
DEV_NAME="dummy"
DEV_NAME2="ymmud"
PWD1="93R4P4pIqAH8"
PWD2="mymJeD8ivEhE"
FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
SKIP_COUNT=0

CRYPTSETUP_VALGRIND=../.libs/cryptsetup
CRYPTSETUP_LIB_VALGRIND=../.libs

cleanup() {
	[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
	udevadm settle >/dev/null 2>&1
	if [ -d "$MNT_DIR" ] ; then
		umount -f $MNT_DIR 2>/dev/null
		rmdir $MNT_DIR 2>/dev/null
	fi
	rmmod scsi_debug >/dev/null 2>&1
}

fail()
{
	[ -n "$1" ] && echo "FAIL $1"
	echo "FAILED backtrace:"
	while caller $frame; do ((frame++)); done
	cleanup
	exit 100
}

skip()
{
	echo "TEST SKIPPED: $1"
	cleanup
	exit 77
}

function valgrind_setup()
{
	command -v valgrind >/dev/null || fail "Cannot find valgrind."
	[ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
	export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
}

function valgrind_run()
{
	INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
}

add_device() {
	rmmod scsi_debug >/dev/null 2>&1
	[ -d /sys/module/scsi_debug ] && skip "Cannot use scsi_debug module (in use or compiled-in)."

	modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
	[ $? -ne 0 ] && skip "This kernel seems to not support proper scsi_debug module."

	sleep 1
	SCSI_DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)

	[ -b "/dev/$SCSI_DEV" ] || fail "Cannot find $SCSI_DEV."
}

add_image()
{
	dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
}

function dm_crypt_features()
{
	modprobe dm-crypt >/dev/null 2>&1 || fail "dm-crypt failed to load"
	VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
	[ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."

	VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
	VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
	VER_PTC=$(echo $VER_STR | cut -f 3 -d.)

	[ $VER_MAJ -lt 1 ] && return
	[ $VER_MAJ -gt 1 ] && {
		DM_PERF_CPU=1
		DM_SECTOR_SIZE=1
		test -d /proc/sys/kernel/keys && DM_KEYRING=1
		return
	}

	[ $VER_MIN -lt 14 ] && return
	DM_PERF_CPU=1
	if [ $VER_MIN -ge 17 -o \( $VER_MIN -eq 14 -a $VER_PTC -ge 5 \) ]; then
		DM_SECTOR_SIZE=1
	fi
	if [ $VER_MIN -gt 18 -o \( $VER_MIN -eq 18 -a $VER_PTC -ge 1 \) ]; then
		 test -d /proc/sys/kernel/keys && DM_KEYRING=1
	fi

	[ $VER_MIN -lt 22 ] && return
	DM_PERF_NO_WORKQUEUE=1
}

function dm_crypt_keyring_support()
{
	VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
	[ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."

	VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
	VER_MIN=$(echo $VER_STR | cut -f 2 -d.)

	# run the test with dm-crypt v1.15.0+ on purpose
	# the fix is in dm-crypt v1.18.1+
	[ $VER_MAJ -gt 1 ] && return 0
	[ $VER_MAJ -lt 1 ] && return 1
	[ $VER_MIN -ge 15 ]
}

format() # format
{
	add_image

	echo $PWD1 | $CRYPTSETUP luksFormat --type $1 $DEV -q  $FAST_PBKDF_OPT -c aes-cbc-essiv:sha256
	[ $? -ne 0 ] && fail "Format failed."

	# test some operation, just in case
	echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $DEV -i1 --new-key-slot 1
	[ $? -ne 0 ] && fail "Keyslot add failed."

	$CRYPTSETUP -q luksKillSlot $DEV 1
	[ $? -ne 0 ] && fail "Keyslot removal failed."
}

check_sector_size() # $1 expected sector size
{
	$CRYPTSETUP status $DEV_NAME | grep "sector size" | grep -q $1 || fail
	if [ $S -gt 512 ]; then
		dmsetup table $DEV_NAME | grep -q "sector_size:$1" || fail
	fi
}

check_io()
{
	dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M count=32 iflag=direct 2>/dev/null || fail
	dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M count=32 oflag=direct 2>/dev/null || fail
}

[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
if [ $(id -u) != 0 ]; then
	skip "You must be root to run this test, test skipped."
fi

dm_crypt_features

[ ! -d $MNT_DIR ] && mkdir $MNT_DIR

echo "[1] Using tmpfs for image"
DEV="$MNT_DIR/test.img"
mount -t tmpfs none $MNT_DIR || skip "Mounting tmpfs not available."

add_image
echo "[2] Kernel dmcrypt performance options"
if [ -z "$DM_PERF_CPU" ]; then
	echo "TEST SKIPPED: dmcrypt options not available"
	SKIP_COUNT=$((SKIP_COUNT+1))
else
	echo -n "PLAIN: same_cpu_crypt submit_from_cpus "
	echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	check_io
	$CRYPTSETUP close $DEV_NAME || fail
	echo -n "allow_discards "
	echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	check_io
	$CRYPTSETUP close $DEV_NAME || fail
	echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
	# Hash affects volume key for plain device. Check we can detect it
	echo -e "$PWD1" | $CRYPTSETUP refresh -q $DEV_NAME --hash sha512 --perf-same_cpu_crypt --allow-discards 2>/dev/null && fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --allow-discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards && fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 $DEV $DEV_NAME2 2>/dev/null && fail
	if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then
		echo -n "no_read_workqueue no_write_workqueue"
		echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
		check_io
	fi
	$CRYPTSETUP close $DEV_NAME || fail
	echo

	format luks1
	echo -n "LUKS: same_cpu_crypt submit_from_cpus "
	echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	$CRYPTSETUP close $DEV_NAME || fail
	echo -n "allow_discards "
	echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP close $DEV_NAME || fail
	echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME --allow-discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME --allow-discards --perf-same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards && fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME2 2>/dev/null && fail
	if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then
		echo -n "no_read_workqueue no_write_workqueue"
		echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME  --perf-no_read_workqueue --perf-no_write_workqueue || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
	fi
	$CRYPTSETUP close $DEV_NAME || fail
	echo

	format luks2
	echo -n "LUKS2: same_cpu_crypt submit_from_cpus "
	echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus --persistent || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	$CRYPTSETUP close $DEV_NAME || fail
	# Stored in metadata
	echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	$CRYPTSETUP close $DEV_NAME || fail
	echo -n "allow_discards [persistent flags] "
	echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards --persistent || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP close $DEV_NAME || fail
	echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP close $DEV_NAME || fail

	echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME --persistent || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus --persistent || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards --persistent || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-submit_from_crypt_cpus || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME || fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --persistent || fail
	$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
	$CRYPTSETUP status $DEV_NAME | grep -q discards && fail
	$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus && fail
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --disable-keyring || fail
	$CRYPTSETUP status $DEV_NAME | grep -q keyring && fail
	if [ -n "$DM_KEYRING" ]; then
		echo -n "keyring "
		echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME || fail
		$CRYPTSETUP status $DEV_NAME | grep -q keyring || fail
	fi
	if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then
		echo -n "no_read_workqueue no_write_workqueue"
		echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue --persistent || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
		$CRYPTSETUP close $DEV_NAME || fail
		echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
		$CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
	fi
	echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME2 2>/dev/null && fail
	$CRYPTSETUP close $DEV_NAME || fail
	echo
fi

echo "[3] Kernel dmcrypt sector size options"
echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --sector-size 4096 >/dev/null 2>&1
ret=$?
[ -z "$DM_SECTOR_SIZE" -a $ret -eq 0 ] && fail "cryptsetup activated device with --sector-size option on incompatible kernel!"
if [ $ret -ne 0 ] ; then
	SKIP_COUNT=$((SKIP_COUNT+1))
	if [ $SKIP_COUNT -ge 2 ]; then
		skip "dmcrypt sector-size option not available"
	fi
	echo "TEST SKIPPED: dmcrypt sector-size option not available"
else
	$CRYPTSETUP close $DEV_NAME || fail

	echo -n "PLAIN sector size:"
	echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --sector-size 1234 >/dev/null 2>&1 && fail
	for S in 512 1024 2048 4096; do
		echo -n "[$S]"
		echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --sector-size $S || fail
		check_sector_size $S
		$CRYPTSETUP close $DEV_NAME || fail
	done

	echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --iv-large-sectors >/dev/null 2>&1 && fail
	for S in 1024 2048 4096; do
		echo -n "[$S/IV]"
		echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --sector-size $S --iv-large-sectors || fail
		check_sector_size $S
		dmsetup table $DEV_NAME | grep -q "iv_large_sectors" || fail
		$CRYPTSETUP close $DEV_NAME || fail
	done
	echo

	echo -n "LUKS2 sector size:"
	echo -e "$PWD1" | $CRYPTSETUP luksFormat --type luks2 -$DEV --sector-size 1234 >/dev/null 2>&1 && fail
	for S in 512 1024 2048 4096; do
		echo -n "[$S]"
		echo -e "$PWD1" | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf pbkdf2 --pbkdf-force-iterations 1000 $DEV --sector-size $S || fail
		echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
		check_sector_size $S
		$CRYPTSETUP close $DEV_NAME || fail
	done
	echo
fi

echo "[4] Disappeared device test:"
KEY="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
for F in LUKS1 LUKS2 BITLK TCRYPT; do
	add_device dev_size_mb=1 sector_size=512 num_tgts=1 lbpu=1
	echo -n "$F"
	# Fake CRYPT UUID to force code to parse type-specific path
	dmsetup create $DEV_NAME --uuid CRYPT-$F-$DEV_NAME --table "0 1024 crypt aes-xts-plain64 $KEY 16 /dev/$SCSI_DEV 16"
	$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
	echo 1 > /sys/block/$SCSI_DEV/device/delete
	udevadm settle >/dev/null 2>&1
	$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
	dmsetup remove $DEV_NAME --retry || fail
	rmmod scsi_debug >/dev/null 2>&1
	echo -n "[OK] "
done
echo

cleanup
exit 0