Skip to content

Commit 8da66c3

Browse files
committed
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
1 parent 11a4fc6 commit 8da66c3

File tree

7 files changed

+90
-8
lines changed

7 files changed

+90
-8
lines changed

lib/libcryptsetup.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,18 @@ int crypt_header_is_detached(struct crypt_device *cd);
21172117
int crypt_get_verity_info(struct crypt_device *cd,
21182118
struct crypt_params_verity *vp);
21192119

2120+
/**
2121+
* Get FEC repaired block count for VERITY device.
2122+
*
2123+
* @param cd crypt device handle
2124+
* @param name verity device name
2125+
* @param repaired FEC repaired blocks
2126+
*
2127+
* @return @e 0 on success or negative errno value otherwise.
2128+
*/
2129+
int crypt_get_verity_repaired(struct crypt_device *cd, const char *name,
2130+
uint64_t *repaired);
2131+
21202132
/**
21212133
* Get device parameters for INTEGRITY device.
21222134
*

lib/libcryptsetup.sym

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,8 @@ CRYPTSETUP_2.8 {
195195
crypt_get_old_volume_key_size;
196196
crypt_format_inline;
197197
} CRYPTSETUP_2.7;
198+
199+
CRYPTSETUP_2.9 {
200+
global:
201+
crypt_get_verity_repaired;
202+
} CRYPTSETUP_2.8;

lib/libdevmapper.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,40 @@ int dm_status_verity_ok(struct crypt_device *cd, const char *name)
19921992
return r;
19931993
}
19941994

1995+
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired)
1996+
{
1997+
int r;
1998+
struct dm_info dmi;
1999+
char *status_line = NULL, *p;
2000+
uint64_t val64;
2001+
2002+
if (dm_init_context(cd, DM_VERITY))
2003+
return -ENOTSUP;
2004+
2005+
r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
2006+
dm_exit_context();
2007+
if (r < 0 || !status_line || !*status_line) {
2008+
free(status_line);
2009+
return r;
2010+
}
2011+
p = status_line + 1;
2012+
while (*p == ' ')
2013+
p++;
2014+
2015+
if (!*p || *p == '-' || sscanf(p, "%" PRIu64, &val64) != 1) {
2016+
free(status_line);
2017+
return -ENOTSUP;
2018+
}
2019+
2020+
log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
2021+
2022+
if (repaired)
2023+
*repaired = val64;
2024+
2025+
free(status_line);
2026+
return 0;
2027+
}
2028+
19952029
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count)
19962030
{
19972031
int r;

lib/setup.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6790,6 +6790,16 @@ int crypt_get_verity_info(struct crypt_device *cd,
67906790
return 0;
67916791
}
67926792

6793+
int crypt_get_verity_repaired(struct crypt_device *cd, const char *name,
6794+
uint64_t *repaired)
6795+
6796+
{
6797+
if (!cd || !isVERITY(cd->type) || !name || !repaired)
6798+
return -EINVAL;
6799+
6800+
return dm_status_verity_repaired(cd, name, repaired);
6801+
}
6802+
67936803
int crypt_get_integrity_info(struct crypt_device *cd,
67946804
struct crypt_params_integrity *ip)
67956805
{

lib/utils_dm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ int dm_status_device(struct crypt_device *cd, const char *name);
205205
int dm_status_suspended(struct crypt_device *cd, const char *name);
206206
int dm_status_verity_ok(struct crypt_device *cd, const char *name);
207207
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count);
208+
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired);
208209
int dm_query_device(struct crypt_device *cd, const char *name,
209210
uint64_t get_flags, struct crypt_dm_active_device *dmd);
210211
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,

src/veritysetup.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ static int action_status(void)
333333
size_t root_hash_size;
334334
unsigned path = 0;
335335
int r = 0;
336+
uint64_t repaired;
336337

337338
/* perhaps a path, not a dm device name */
338339
if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
@@ -415,6 +416,8 @@ static int action_status(void)
415416
log_std(" FEC offset: %" PRIu64 " [512-byte units] (%" PRIu64 " [bytes])\n",
416417
vp.fec_area_offset * vp.hash_block_size / SECTOR_SIZE, vp.fec_area_offset * vp.hash_block_size);
417418
log_std(" FEC roots: %u\n", vp.fec_roots);
419+
if (!crypt_get_verity_repaired(cd, action_argv[0], &repaired))
420+
log_std(" FEC repaired: %" PRIu64 " [events]\n", repaired);
418421
}
419422

420423
root_hash_size = crypt_get_volume_key_size(cd);

tests/verity-compat-test

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ corrupt_device() # $1 device, $2 device_size(in bytes), $3 #{corrupted_bytes}
241241
# $1 data_device, $2 hash_device, $3 fec_device, $4 data/hash_block_size(in bytes),
242242
# $5 data_size(in blocks), $6 device_size(in blocks), $7 hash_offset(in bytes),
243243
# $8 fec_offset(in bytes), $9 fec_roots, ${10} corrupted_bytes, [${11} superblock(y/n), ${12} salt]
244+
# NOTE: do not use fail() in this function, use RET code
244245
check_fec()
245246
{
246247
INDEX=25
@@ -292,18 +293,32 @@ check_fec()
292293
dd if=/dev/mapper/$DEV_NAME of=$IMG_TMP > /dev/null 2>&1
293294
HASH_REPAIRED=$(sha256sum $IMG_TMP | cut -d' ' -f 1)
294295

296+
# If empty, status not supported
297+
REPAIRED=$(dmsetup status $DEV_NAME |sed -e s/.*verity\ \[VC\]\ *//)
298+
if [ -n "$REPAIRED" -a "$REPAIRED" != "-" ] ; then
299+
echo -n "[EC events: $REPAIRED]"
300+
else
301+
REPAIRED=""
302+
fi
303+
295304
$VERITYSETUP close $DEV_NAME
296305

297306
if [ "$HASH_ORIG" != "$HASH_REPAIRED" ]; then
307+
RET=1
308+
if [ -n "$REPAIRED" ]; then
309+
[ "$REPAIRED" -eq 0 ] || { RET=4; echo "FEC repaired events should be 0."; }
310+
fi
298311
echo -n "[kernel correction failed]"
299-
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && fail "Userspace verify should fail"
312+
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && { RET=5; echo "Userspace verify should fail"; }
300313
echo -n "[userspace verify failed]"
301-
RET=1
302314
else
315+
RET=0
303316
echo -n "[repaired in kernel]"
304-
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || fail "Userspace verify failed"
317+
if [ -n "$REPAIRED" ]; then
318+
[ "$REPAIRED" -gt 0 ] || { RET=4; echo "FEC repaired events should be greater than 0."; }
319+
fi
320+
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || { RET=5; echo "Userspace verify failed"; }
305321
echo "[userspace verify][OK]"
306-
RET=0
307322
fi
308323
rm $1 $2 $3 $IMG_TMP > /dev/null 2>&1
309324
return $RET
@@ -531,10 +546,10 @@ if check_version 1 3; then
531546
echo "Veritysetup [FEC tests]"
532547
for INDEX in {1..4}; do
533548
# in the first iteration check if we can use FEC (it can be compiled-out)
534-
(check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) )
549+
(check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)))
535550
RET=$?
536-
[ "$RET" -eq "3" ] && break
537-
[ "$RET" -eq "0" ] || fail "FEC repair failed"
551+
[ "$RET" -eq 3 ] && break
552+
[ "$RET" -eq 0 ] || fail "FEC repair failed"
538553

539554
(check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'n' $SALT) || fail "FEC repair failed"
540555
(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
546561
(check_fec $IMG $IMG_HASH $FEC_DEV 512 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
547562
(check_fec $IMG $IMG_HASH $FEC_DEV 1024 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
548563
# this test should fail
549-
(check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200))) && fail "FEC repair must fail"
564+
(check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200)))
565+
RET=$?
566+
[ "$RET" -eq 1 ] || fail "FEC repair must fail"
550567
echo "[OK]"
551568
done
552569
fi

0 commit comments

Comments
 (0)