mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
verity: Support status info about FEC repaired events
Kernel 6.19 will support additional info on dm-verity status line that contains number of FEC successful repair events. This patch adds support to libcryptsetup and veritysetup status command. Ref. https://lore.kernel.org/dm-devel/074e1ecc-6690-1c22-0dba-454e191e1b6f@redhat.com/T/#m1af31c9c4263fe2b1fb58dee2fd7f0bdf045c463
This commit is contained in:
@@ -2117,6 +2117,18 @@ int crypt_header_is_detached(struct crypt_device *cd);
|
||||
int crypt_get_verity_info(struct crypt_device *cd,
|
||||
struct crypt_params_verity *vp);
|
||||
|
||||
/**
|
||||
* Get FEC repaired block count for VERITY device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param name verity device name
|
||||
* @param repaired FEC repaired blocks
|
||||
*
|
||||
* @return @e 0 on success or negative errno value otherwise.
|
||||
*/
|
||||
int crypt_get_verity_repaired(struct crypt_device *cd, const char *name,
|
||||
uint64_t *repaired);
|
||||
|
||||
/**
|
||||
* Get device parameters for INTEGRITY device.
|
||||
*
|
||||
|
||||
@@ -195,3 +195,8 @@ CRYPTSETUP_2.8 {
|
||||
crypt_get_old_volume_key_size;
|
||||
crypt_format_inline;
|
||||
} CRYPTSETUP_2.7;
|
||||
|
||||
CRYPTSETUP_2.9 {
|
||||
global:
|
||||
crypt_get_verity_repaired;
|
||||
} CRYPTSETUP_2.8;
|
||||
|
||||
@@ -1992,6 +1992,40 @@ int dm_status_verity_ok(struct crypt_device *cd, const char *name)
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired)
|
||||
{
|
||||
int r;
|
||||
struct dm_info dmi;
|
||||
char *status_line = NULL, *p;
|
||||
uint64_t val64;
|
||||
|
||||
if (dm_init_context(cd, DM_VERITY))
|
||||
return -ENOTSUP;
|
||||
|
||||
r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
|
||||
dm_exit_context();
|
||||
if (r < 0 || !status_line || !*status_line) {
|
||||
free(status_line);
|
||||
return r;
|
||||
}
|
||||
p = status_line + 1;
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
|
||||
if (!*p || *p == '-' || sscanf(p, "%" PRIu64, &val64) != 1) {
|
||||
free(status_line);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
|
||||
|
||||
if (repaired)
|
||||
*repaired = val64;
|
||||
|
||||
free(status_line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count)
|
||||
{
|
||||
int r;
|
||||
|
||||
10
lib/setup.c
10
lib/setup.c
@@ -6790,6 +6790,16 @@ int crypt_get_verity_info(struct crypt_device *cd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_get_verity_repaired(struct crypt_device *cd, const char *name,
|
||||
uint64_t *repaired)
|
||||
|
||||
{
|
||||
if (!cd || !isVERITY(cd->type) || !name || !repaired)
|
||||
return -EINVAL;
|
||||
|
||||
return dm_status_verity_repaired(cd, name, repaired);
|
||||
}
|
||||
|
||||
int crypt_get_integrity_info(struct crypt_device *cd,
|
||||
struct crypt_params_integrity *ip)
|
||||
{
|
||||
|
||||
@@ -205,6 +205,7 @@ int dm_status_device(struct crypt_device *cd, const char *name);
|
||||
int dm_status_suspended(struct crypt_device *cd, const char *name);
|
||||
int dm_status_verity_ok(struct crypt_device *cd, const char *name);
|
||||
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count);
|
||||
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired);
|
||||
int dm_query_device(struct crypt_device *cd, const char *name,
|
||||
uint64_t get_flags, struct crypt_dm_active_device *dmd);
|
||||
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,
|
||||
|
||||
@@ -333,6 +333,7 @@ static int action_status(void)
|
||||
size_t root_hash_size;
|
||||
unsigned path = 0;
|
||||
int r = 0;
|
||||
uint64_t repaired;
|
||||
|
||||
/* perhaps a path, not a dm device name */
|
||||
if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
|
||||
@@ -415,6 +416,8 @@ static int action_status(void)
|
||||
log_std(" FEC offset: %" PRIu64 " [512-byte units] (%" PRIu64 " [bytes])\n",
|
||||
vp.fec_area_offset * vp.hash_block_size / SECTOR_SIZE, vp.fec_area_offset * vp.hash_block_size);
|
||||
log_std(" FEC roots: %u\n", vp.fec_roots);
|
||||
if (!crypt_get_verity_repaired(cd, action_argv[0], &repaired))
|
||||
log_std(" FEC repaired: %" PRIu64 " [events]\n", repaired);
|
||||
}
|
||||
|
||||
root_hash_size = crypt_get_volume_key_size(cd);
|
||||
|
||||
@@ -241,6 +241,7 @@ corrupt_device() # $1 device, $2 device_size(in bytes), $3 #{corrupted_bytes}
|
||||
# $1 data_device, $2 hash_device, $3 fec_device, $4 data/hash_block_size(in bytes),
|
||||
# $5 data_size(in blocks), $6 device_size(in blocks), $7 hash_offset(in bytes),
|
||||
# $8 fec_offset(in bytes), $9 fec_roots, ${10} corrupted_bytes, [${11} superblock(y/n), ${12} salt]
|
||||
# NOTE: do not use fail() in this function, use RET code
|
||||
check_fec()
|
||||
{
|
||||
INDEX=25
|
||||
@@ -292,18 +293,32 @@ check_fec()
|
||||
dd if=/dev/mapper/$DEV_NAME of=$IMG_TMP > /dev/null 2>&1
|
||||
HASH_REPAIRED=$(sha256sum $IMG_TMP | cut -d' ' -f 1)
|
||||
|
||||
# If empty, status not supported
|
||||
REPAIRED=$(dmsetup status $DEV_NAME |sed -e s/.*verity\ \[VC\]\ *//)
|
||||
if [ -n "$REPAIRED" -a "$REPAIRED" != "-" ] ; then
|
||||
echo -n "[EC events: $REPAIRED]"
|
||||
else
|
||||
REPAIRED=""
|
||||
fi
|
||||
|
||||
$VERITYSETUP close $DEV_NAME
|
||||
|
||||
if [ "$HASH_ORIG" != "$HASH_REPAIRED" ]; then
|
||||
echo -n "[kernel correction failed]"
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && fail "Userspace verify should fail"
|
||||
echo -n "[userspace verify failed]"
|
||||
RET=1
|
||||
if [ -n "$REPAIRED" ]; then
|
||||
[ "$REPAIRED" -eq 0 ] || { RET=4; echo "FEC repaired events should be 0."; }
|
||||
fi
|
||||
echo -n "[kernel correction failed]"
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && { RET=5; echo "Userspace verify should fail"; }
|
||||
echo -n "[userspace verify failed]"
|
||||
else
|
||||
echo -n "[repaired in kernel]"
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || fail "Userspace verify failed"
|
||||
echo "[userspace verify][OK]"
|
||||
RET=0
|
||||
echo -n "[repaired in kernel]"
|
||||
if [ -n "$REPAIRED" ]; then
|
||||
[ "$REPAIRED" -gt 0 ] || { RET=4; echo "FEC repaired events should be greater than 0."; }
|
||||
fi
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || { RET=5; echo "Userspace verify failed"; }
|
||||
echo "[userspace verify][OK]"
|
||||
fi
|
||||
rm $1 $2 $3 $IMG_TMP > /dev/null 2>&1
|
||||
return $RET
|
||||
@@ -531,10 +546,10 @@ if check_version 1 3; then
|
||||
echo "Veritysetup [FEC tests]"
|
||||
for INDEX in {1..4}; do
|
||||
# in the first iteration check if we can use FEC (it can be compiled-out)
|
||||
(check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) )
|
||||
(check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)))
|
||||
RET=$?
|
||||
[ "$RET" -eq "3" ] && break
|
||||
[ "$RET" -eq "0" ] || fail "FEC repair failed"
|
||||
[ "$RET" -eq 3 ] && break
|
||||
[ "$RET" -eq 0 ] || fail "FEC repair failed"
|
||||
|
||||
(check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'n' $SALT) || fail "FEC repair failed"
|
||||
(check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'y' $SALT) || fail "FEC repair failed"
|
||||
@@ -546,7 +561,9 @@ if check_version 1 3; then
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 512 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 1024 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
|
||||
# this test should fail
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200))) && fail "FEC repair must fail"
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200)))
|
||||
RET=$?
|
||||
[ "$RET" -eq 1 ] || fail "FEC repair must fail"
|
||||
echo "[OK]"
|
||||
done
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user