Makefile: Add security compiling option (RELRO, SC, and FORTIFY)
[platform/upstream/cryptsetup.git] / tests / blockwise-compat-test
1 #!/bin/bash
2
3 # set _FORCE_LOCAL environment variable to run blockwise unit tests even on local
4 # nfs. Some tests will fail because nfs is eager to write for example 4095 bytes
5 # in O_DIRECT mode.
6
7 BW_UNIT=./unit-utils-io
8 STRACE=strace
9 MNT_DIR=./mnt_bwunit
10 LOCAL_FILE=./blockwise_localfile
11
12 # $1 path to scsi debug bdev
13 scsi_debug_teardown() {
14         local _tries=15;
15
16         while [ -b "$1" -a $_tries -gt 0 ]; do
17                 rmmod scsi_debug >/dev/null 2>&1
18                 if [ -b "$1" ]; then
19                         sleep .1
20                         _tries=$((_tries-1))
21                 fi
22         done
23
24         test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
25 }
26
27 cleanup() {
28         if [ -d "$MNT_DIR" ] ; then
29             umount -f $MNT_DIR 2>/dev/null
30             rmdir $MNT_DIR 2>/dev/null
31         fi
32         rm -f $LOCAL_FILE 2> /dev/null
33         scsi_debug_teardown "$DEV" || exit 100
34 }
35
36 fail()
37 {
38         if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
39         cleanup
40         exit 100
41 }
42
43 fail_count()
44 {
45         echo "$MSG[FAIL]"
46         FAILS=$((FAILS+1))
47 }
48
49 warn_count()
50 {
51         echo "$MSG[WARNING]"
52         WARNS=$((WARNS+1))
53 }
54
55 skip()
56 {
57         echo "TEST SKIPPED: $1"
58         cleanup
59         exit 77
60 }
61
62 add_device() {
63         rmmod scsi_debug >/dev/null 2>&1
64         if [ -d /sys/module/scsi_debug ] ; then
65                 skip "Cannot use scsi_debug module (in use or compiled-in)."
66         fi
67         modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
68         if [ $? -ne 0 ] ; then
69                 skip "This kernel seems to not support proper scsi_debug module."
70         fi
71         grep -q scsi_debug /sys/block/*/device/model || sleep 2
72         DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
73         DEV="/dev/$DEV"
74         [ -b $DEV ] || fail "Cannot find $DEV."
75 }
76
77 falloc() {
78         dd if=/dev/zero of=$2 bs=1M count=$1 2> /dev/null
79 }
80
81 run_all_in_fs() {
82         for file in $(ls img_fs_*.img.xz) ; do
83                 echo "Run tests in $file put on top block device."
84                 xz -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
85                 [ ! -d $MNT_DIR ] && mkdir $MNT_DIR
86                 mount $DEV $MNT_DIR
87                 if [ $? -ne 0 ]; then
88                         echo "Mounting image $file failed, skipped."
89                         continue;
90                 fi
91                 rm -rf $MNT_DIR/* 2>/dev/null
92                 local tfile=$MNT_DIR/bwunit_tstfile
93                 falloc $DEVSIZEMB $tfile || fail "enospc?"
94                 local iobsize=$(stat -c "%o" $tfile)
95                 test -n "$iobsize" -a $iobsize -gt 0 || fail
96                 local oldbsize=$BSIZE
97                 BSIZE=$iobsize
98                 run_all $tfile
99                 BSIZE=$oldbsize
100                 umount $MNT_DIR
101         done
102 }
103
104 trunc_file() {
105         test $1 -eq 0 || truncate -c -s $1 $2 2>/dev/null || dd if=/dev/zero of=$2 bs=$1 count=1 2>/dev/null || fail "Failed to truncate test file $2."
106 }
107
108 RUN() {
109         local _res=$1
110         shift
111         local _dev=$1
112         shift
113         local _fn=$1
114         shift
115         local _type="bdev"
116         local _fsize=0
117
118         test -b $_dev || {
119                 _type="file"
120                 _fsize=$(stat -c "%s" $_dev)
121         }
122
123         case "$_res" in
124         P)
125                 MSG="Testing $_fn on $_type with params $@ [expecting TRUE]..."
126                 $BW_UNIT $_dev $_fn $@
127                 if [ $? -ne 0 ]; then
128                         if [ $_type = "file" ]; then
129                                 warn_count
130                         else
131                                 fail_count
132                         fi
133                         trunc_file $_fsize $_dev
134                         test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-pass.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
135                 else
136                         MSG="$MSG[OK]"
137                 fi
138                 ;;
139         F)
140                 MSG="Testing $_fn on $_type with params $@ [expecting FALSE]..."
141                 $BW_UNIT $_dev $_fn $@ 2> /dev/null
142                 if [ $? -eq 0 ]; then
143                         if [ $_type = "file" ]; then
144                                 warn_count
145                         else
146                                 fail_count
147                         fi
148                         trunc_file $_fsize $_dev
149                         test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-fail.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
150                 else
151                         MSG="$MSG[OK]"
152                 fi
153                 ;;
154         *)
155                 fail "Internal test error"
156                 ;;
157         esac
158
159         trunc_file $_fsize $_dev
160 }
161
162 run_all() {
163         if [ -b "$1" ]; then
164                 BD_FAIL="F"
165         else
166                 BD_FAIL="P"
167         fi
168
169         # buffer io support only blocksize aligned ios
170         # device/file fn_name length
171         RUN "P" $1 read_buffer $BSIZE
172         RUN "P" $1 read_buffer $((2*BSIZE))
173         RUN "F" $1 read_buffer $((BSIZE-1))
174         RUN "F" $1 read_buffer $((BSIZE+1))
175         RUN "P" $1 read_buffer 0
176
177         RUN "P" $1 write_buffer $BSIZE
178         RUN "P" $1 write_buffer $((2*BSIZE))
179
180         RUN "F" $1 write_buffer $((BSIZE-1))
181         RUN "F" $1 write_buffer $((BSIZE+1))
182         RUN "F" $1 write_buffer 0
183
184         # basic blockwise functions
185         # device/file fn_name length bsize
186         RUN "P" $1 read_blockwise 0 $BSIZE
187         RUN "P" $1 read_blockwise $((BSIZE)) $BSIZE
188         RUN "P" $1 read_blockwise $((BSIZE-1)) $BSIZE
189         RUN "P" $1 read_blockwise $((BSIZE+1)) $BSIZE
190         RUN "P" $1 read_blockwise $((DEVSIZE)) $BSIZE
191         RUN "P" $1 read_blockwise $((DEVSIZE-1)) $BSIZE
192         RUN "F" $1 read_blockwise $((DEVSIZE+1)) $BSIZE
193
194         RUN "P" $1 write_blockwise 0 $BSIZE
195         RUN "P" $1 write_blockwise $((BSIZE)) $BSIZE
196         RUN "P" $1 write_blockwise $((BSIZE-1)) $BSIZE
197         RUN "P" $1 write_blockwise $((BSIZE+1)) $BSIZE
198         RUN "P" $1 write_blockwise $((DEVSIZE)) $BSIZE
199         RUN "P" $1 write_blockwise $((DEVSIZE-1)) $BSIZE
200         RUN "$BD_FAIL" $1 write_blockwise $((DEVSIZE+1)) $BSIZE
201
202         # seek variant blockwise functions
203         # device/file fn_name length bsize offset
204         RUN "P" $1 read_lseek_blockwise 0 $BSIZE 0
205         RUN "P" $1 read_lseek_blockwise 0 $BSIZE 1
206         RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE))
207         # length = 0 is significant here
208         RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE+1))
209
210         # beginning of device
211         RUN "P" $1 read_lseek_blockwise 1 $BSIZE 0
212         RUN "P" $1 read_lseek_blockwise 1 $BSIZE 1
213         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE-1))
214         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE/2))
215
216         # somewhere in the 'middle'
217         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $BSIZE
218         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+1))
219         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
220         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
221
222         # cross-sector tests
223         RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((BSIZE-1))
224         RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
225         RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
226         RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
227         RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
228         RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
229
230         # including one whole sector
231         RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
232         RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
233         RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
234         RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
235         RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
236         RUN "P" $1 read_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
237
238         # hiting exactly the sector boundary
239         RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE 1
240         RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
241         RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
242         RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
243
244         # device end
245         RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
246         RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
247         RUN "P" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
248         RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
249
250         # this must fail on both device and file
251         RUN "F" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE))
252         RUN "F" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
253         RUN "F" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
254         RUN "F" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
255
256         RUN "P" $1 write_lseek_blockwise 0 $BSIZE 0
257         # TODO: this may pass but must not write a byte (write(0) is undefined).
258         #       Test it with underlying dm-error or phony read/write syscalls.
259         #       Skipping read is optimization.
260         # HINT: currently it performs useless write and read as well
261         RUN "P" $1 write_lseek_blockwise 0 $BSIZE 1
262         RUN "P" $1 write_lseek_blockwise 0 $BSIZE $BSIZE
263
264         # beginning of device
265         RUN "P" $1 write_lseek_blockwise 1 $BSIZE 0
266         RUN "P" $1 write_lseek_blockwise 1 $BSIZE 1
267         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE-1))
268         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE/2))
269
270         # somewhere in the 'middle'
271         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $BSIZE
272         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+1))
273         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
274         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
275
276         # cross-sector tests
277         RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((BSIZE-1))
278         RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
279         RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
280         RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
281         RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
282         RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
283
284         # including one whole sector
285         RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
286         RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
287         RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
288         RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
289         RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
290         RUN "P" $1 write_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
291
292         # hiting exactly the sector boundary
293         RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE 1
294         RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
295         RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
296         RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
297
298         # device end
299         RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
300         RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
301         RUN "P" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
302         RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
303
304         # this must fail on device, but pass on file (which is unfortunate and maybe design mistake)
305         RUN "$BD_FAIL" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE))
306         RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
307         RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
308         RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
309 }
310
311 command -v $STRACE >/dev/null || unset STRACE
312 test -x $BW_UNIT || skip "Run \"make `basename $BW_UNIT`\" first"
313
314 FAILS=0
315 WARNS=0
316 DEVSIZEMB=2
317 DEVSIZE=$((DEVSIZEMB*1024*1024))
318
319 PAGE_SIZE=$(getconf PAGE_SIZE)
320 echo "System PAGE_SIZE=$PAGE_SIZE"
321
322 echo "Run tests in local filesystem"
323 falloc $DEVSIZEMB $LOCAL_FILE || fail "Failed to create file in local filesystem."
324 BSIZE=$(stat -c "%o" $LOCAL_FILE)
325 if [ $BSIZE -gt $((512*1024)) ]; then
326         echo "Detected file block size: $BSIZE bytes"
327         echo "Tuning it down to system page size ($PAGE_SIZE bytes)"
328         BSIZE=$PAGE_SIZE
329 fi
330 run_all $LOCAL_FILE
331
332 [ $(id -u) -eq 0 ] || {
333         echo "WARNING: You must be root to run remaining tests."
334         test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
335         cleanup
336         exit 0
337 }
338
339 DEVBSIZE=512
340 BSIZE=$DEVBSIZE
341 EXP=0
342 DEVSIZEMBIMG=32
343
344 echo "# Create classic 512B drive"
345 echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
346 add_device dev_size_mb=$DEVSIZEMB sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
347 run_all $DEV
348 cleanup
349 add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
350 run_all_in_fs
351 cleanup
352
353 EXP=3
354 echo "# Create desktop-class 4K drive"
355 echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
356 add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
357 run_all $DEV
358 BSIZE=$((DEVBSIZE*(1<<EXP)))
359 run_all $DEV
360 cleanup
361
362 add_device dev_size_mb=$DEVSIZEMBIMG physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
363 run_all_in_fs
364 cleanup
365
366 DEVBSIZE=4096
367 BSIZE=$DEVBSIZE
368 EXP=0
369 echo "# Create enterprise-class 4K drive"
370 echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
371 add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
372 run_all $DEV
373 cleanup
374 add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
375 run_all_in_fs
376 cleanup
377
378 test $WARNS -eq 0 || echo "(WARNING: $WARNS suspicious result(s) in total)"
379 test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"