From f6706ce12401e228fa5e0ce80dfde56037d042af Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 8 Aug 2020 20:56:20 +0100 Subject: [PATCH] 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). --- tests/verity-compat-test | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/verity-compat-test b/tests/verity-compat-test index 4ce70f9f..d3bcdd99 100755 --- a/tests/verity-compat-test +++ b/tests/verity-compat-test @@ -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