Commit 807cedf4 authored by Milan Broz's avatar Milan Broz

Check for data device and hash device area overlap in veritysetup.

Thanks Michal Virgovic for tests.
parent ef8a7d82
......@@ -76,6 +76,7 @@ int device_read_ahead(struct device *device, uint32_t *read_ahead);
int device_size(struct device *device, uint64_t *size);
int device_open(struct device *device, int flags);
void device_disable_direct_io(struct device *device);
int device_is_identical(struct device *device1, struct device *device2);
enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 };
......
......@@ -1030,6 +1030,12 @@ static int _crypt_format_verity(struct crypt_device *cd,
} else
cd->u.verity.hdr.data_size = params->data_size;
if (device_is_identical(crypt_metadata_device(cd), crypt_data_device(cd)) &&
(cd->u.verity.hdr.data_size * params->data_block_size) > params->hash_area_offset) {
log_err(cd, _("Data area overlaps with hash area.\n"));
return -EINVAL;
}
hash_size = crypt_hash_size(params->hash_name);
if (hash_size <= 0) {
log_err(cd, _("Hash algorithm %s not supported.\n"),
......
......@@ -535,3 +535,18 @@ void device_disable_direct_io(struct device *device)
{
device->o_direct = 0;
}
int device_is_identical(struct device *device1, struct device *device2)
{
if (device1 == device2)
return 1;
if (!device1 || !device2 || !device_path(device1) || !device_path(device2))
return 0;
/* This should be better check - major/minor for block device etc */
if (!strcmp(device_path(device1), device_path(device2)))
return 1;
return 0;
}
......@@ -171,6 +171,31 @@ function valgrind_run()
INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${VERITYSETUP} "$@"
}
function checkOffsetBug() # $1 size, $2 hash-offset, $3 data-blocks
{
echo -n "Size :: $1 B | Hash-offset :: $2 blocks | Data-blocks :: $3 "
dd if=/dev/zero of=$IMG bs=1 count=0 seek=$1 >/dev/null 2>&1
$VERITYSETUP --data-blocks=$3 --hash-offset=$2 format $IMG $IMG >/dev/null 2>&1 || fail "Test [hash-offset greater than 2G] failed"
echo "[OK]"
remove_mapping
}
function checkOverlapBug() # $1 size, $2 hash-offset, $3 data-blocks
{
echo -n "Size :: $1 B | Hash-offset :: $2 blocks | "
dd if=/dev/zero of=$IMG bs=1 count=0 seek=$1 >/dev/null 2>&1
if [ -z $3 ] ; then
# veritysetup must fail
$VERITYSETUP --hash-offset=$2 format $IMG $IMG >/dev/null 2>&1 && fail "Test [overlap with option \"--data-blocks\" not entered] failed"
else
$VERITYSETUP --data-blocks=$3 --hash-offset=$2 format $IMG $IMG >/dev/null 2>&1 || fail "Test [overlap with option \"--data-blocks\" entered] failed"
RET=$?
[ "$3" -gt "$(($2 / 4096))" ] && [ "$RET" -eq "0" ] && fail "Test [overlap - hash-offset in data area] failed"
fi
echo "[OK]"
remove_mapping
}
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
[ ! -x "$VERITYSETUP" ] && skip "Cannot find $VERITYSETUP, test skipped."
......@@ -208,6 +233,7 @@ check_root_hash 4096 ef29c902d87350f1da4bfa536e16cebc162a909bf89abe448b81ec500d4
check_root_hash 1024 d0e9163ca8844aaa2e88fe5265a8c5d9ee494a99 $SALT 1 sha1 8388608
check_root_hash 1024 73509e8e868be6b8ac939817a98a3d35121413b2 dadada 1 sha1 8388608
if check_version ; then
echo "Verity data corruption options test."
SALT=e48da609055204e89ae53b655ca2216dd983cf3cb829f34f63a297d106d53e2d
......@@ -219,5 +245,13 @@ if check_version ; then
check_option 512 $HASH $SALT 1 sha256 "--ignore-corruption --ignore-zero-blocks" "ignore_corruption"
fi
echo "Veritysetup [hash-offset bigger than 2G works] "
checkOffsetBug 3000000000 2499997696 256
checkOffsetBug 10000000000 8000000000 128
echo "Veritysetup [overlap-detection] "
checkOverlapBug 2097152 1433600
checkOverlapBug 2097152 1433600 350
remove_mapping
exit 0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment