Add a test function to exercise concurrent activations

The issue can be reproduced very easily by starting 2 veritysetup processes
at the same time:

$ sudo veritysetup open -v ./img.raw img ./img.verity  & sudo veritysetup open -v ./img.raw img ./img.verity
[1] 814021
device-mapper: create ioctl on img CRYPT-VERITY-cea03b7bc5b94e088e5754ff33be71d6-img failed: Device or resource busy
Verity device detected corruption after activation.
Command successful.
Command failed with code -1 (wrong or missing parameters).

Note how veritysetup open is reporting -EINVAL as the return code.

After the fix:

$ sudo veritysetup open -v ./img.raw img ./img.verity  & sudo veritysetup open -v ./img.raw img ./img.verity
[1] 814649
Verity device detected corruption after activation.
Command successful.
Device img already exists.
Command failed with code -5 (device already exists or device is busy).
This commit is contained in:
Luca Boccassi
2020-08-08 20:56:20 +01:00
committed by Luca Boccassi
parent 31ebf3dc2c
commit f6706ce124

View File

@@ -350,6 +350,31 @@ function checkUserSpaceRepair()
echo "[OK]"
}
function check_concurrent() # $1 hash
{
DEV_PARAMS="$LOOPDEV1 $LOOPDEV2"
# First check that with two sequential opens, we are returning the expected -EEXIST
$VERITYSETUP format $DEV_PARAMS >/dev/null 2>&1 || fail
$VERITYSETUP create $DEV_NAME $DEV_PARAMS $1 >/dev/null 2>&1 || fail
check_exists
$VERITYSETUP create $DEV_NAME $DEV_PARAMS $1 2>&1 >/dev/null | grep -q "Device $DEV_NAME already exists" || fail
$VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
# Then do two concurrent opens, and check that libdevmapper did not return -EINVAL, which is
# not gracefully recoverable. Either could fail depending on scheduling, so just check that
# the libdevmapper error does not appear in either of the outputs.
exec {out_1}< <($VERITYSETUP create -v $DEV_NAME $DEV_PARAMS $1 2>&1)
exec {out_2}< <($VERITYSETUP create -v $DEV_NAME $DEV_PARAMS $1 2>&1)
wait
cat <&${out_1} | grep -q "Command failed with code .* (wrong or missing parameters)" && fail
cat <&${out_2} | grep -q "Command failed with code .* (wrong or missing parameters)" && fail
check_exists
$VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
echo "[OK]"
}
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
[ ! -x "$VERITYSETUP" ] && skip "Cannot find $VERITYSETUP, test skipped."
@@ -440,5 +465,9 @@ checkUserSpaceRepair -1 4096 2 0 0 3 10
checkUserSpaceRepair 400 4096 2 2048000 0 2 1
#checkUserSpaceRepair 500 4096 2 2457600 4915200 1 2 # FIXME
echo "Verity concurrent opening tests."
prepare 8192 1024
check_concurrent 9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174
remove_mapping
exit 0