diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index 3574f508..a2108922 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -1122,6 +1122,8 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); #define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (1 << 24) /** dm-crypt: bypass internal workqueue and process write requests synchronously. */ #define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (1 << 25) +/** dm-integrity: reset automatic recalculation */ +#define CRYPT_ACTIVATE_RECALCULATE_RESET (1 << 26) /** * Active device runtime attributes diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index d8fcd61d..f3581d3a 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -235,6 +235,9 @@ static void _dm_set_integrity_compat(struct crypt_device *cd, if (_dm_satisfies_version(1, 7, 0, integrity_maj, integrity_min, integrity_patch)) _dm_flags |= DM_INTEGRITY_FIX_HMAC_SUPPORTED; + if (_dm_satisfies_version(1, 8, 0, integrity_maj, integrity_min, integrity_patch)) + _dm_flags |= DM_INTEGRITY_RESET_RECALC_SUPPORTED; + _dm_integrity_checked = true; } @@ -927,6 +930,12 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags strncat(features, feature, sizeof(features) - strlen(features) - 1); } + if (flags & CRYPT_ACTIVATE_RECALCULATE_RESET) { + num_options++; + snprintf(feature, sizeof(feature), "reset_recalculate "); + strncat(features, feature, sizeof(features) - strlen(features) - 1); + } + if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) { num_options++; snprintf(feature, sizeof(feature), "allow_discards "); @@ -1700,6 +1709,10 @@ int dm_create_device(struct crypt_device *cd, const char *name, !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED)) log_err(cd, _("Requested automatic recalculation of integrity tags is not supported.")); + if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE_RESET) && + !(dmt_flags & DM_INTEGRITY_RESET_RECALC_SUPPORTED)) + log_err(cd, _("Requested automatic recalculation of integrity tags is not supported.")); + if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED)) log_err(cd, _("Discard/TRIM is not supported.")); @@ -2481,6 +2494,8 @@ static int _dm_target_query_integrity(struct crypt_device *cd, } } else if (!strcmp(arg, "recalculate")) { *act_flags |= CRYPT_ACTIVATE_RECALCULATE; + } else if (!strcmp(arg, "reset_recalculate")) { + *act_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET; } else if (!strcmp(arg, "fix_padding")) { tgt->u.integrity.fix_padding = true; } else if (!strcmp(arg, "fix_hmac")) { diff --git a/lib/utils_dm.h b/lib/utils_dm.h index c47219d0..57e5eca0 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -73,6 +73,7 @@ static inline uint32_t act2dmflags(uint32_t act_flags) #define DM_VERITY_PANIC_CORRUPTION_SUPPORTED (1 << 24) /* dm-verity panic on corruption */ #define DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt suppot for bypassing workqueues */ #define DM_INTEGRITY_FIX_HMAC_SUPPORTED (1 << 26) /* hmac covers also superblock */ +#define DM_INTEGRITY_RESET_RECALC_SUPPORTED (1 << 27) /* dm-integrity automatic recalculation supported */ typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_ZERO, DM_UNKNOWN } dm_target_type; enum tdirection { TARGET_SET = 1, TARGET_QUERY }; diff --git a/man/integritysetup.8 b/man/integritysetup.8 index 9372cc7b..9ed2e915 100644 --- a/man/integritysetup.8 +++ b/man/integritysetup.8 @@ -33,7 +33,7 @@ Open a mapping with backed by device . \fB\fR can be [\-\-data\-device, \-\-batch\-mode, \-\-journal\-watermark, \-\-journal\-commit\-time, \-\-buffer\-sectors, \-\-integrity, \-\-integrity\-key\-size, \-\-integrity\-key\-file, \-\-integrity\-no\-journal, \-\-integrity\-recalculate, -\-\-integrity\-recovery\-mode, \-\-allow\-discards] +\-\-integrity\-recalculate-reset,\-\-integrity\-recovery\-mode, \-\-allow\-discards] .PP \fIclose\fR @@ -87,6 +87,12 @@ The device can be used during automatic integrity recalculation but becomes full integrity protected only after the background operation is finished. This option is available since the Linux kernel version 4.19. .TP +.B "\-\-integrity\-recalculate\-reset" +Restart recalculation from the beginning of the device. +It can be used to change the integrity checksum function. +Note it does not change the tag length. +This option is available since the Linux kernel version 5.13. +.TP .B "\-\-journal\-watermark PERCENT" Journal watermark in percents. When the size of the journal exceeds this watermark, the journal flush will be started. diff --git a/src/integritysetup.c b/src/integritysetup.c index 0911ce18..26781ae9 100644 --- a/src/integritysetup.c +++ b/src/integritysetup.c @@ -263,6 +263,9 @@ static int action_open(void) if (ARG_SET(OPT_INTEGRITY_RECALCULATE_ID) || ARG_SET(OPT_INTEGRITY_LEGACY_RECALC_ID)) activate_flags |= CRYPT_ACTIVATE_RECALCULATE; + if (ARG_SET(OPT_INTEGRITY_RECALCULATE_RESET_ID)) + activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET; + if (ARG_SET(OPT_ALLOW_DISCARDS_ID)) activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; diff --git a/src/integritysetup_arg_list.h b/src/integritysetup_arg_list.h index dbf8f37d..2baab74a 100644 --- a/src/integritysetup_arg_list.h +++ b/src/integritysetup_arg_list.h @@ -81,6 +81,8 @@ ARG(OPT_INTEGRITY_BITMAP_MODE, 'B', POPT_ARG_NONE, N_("Use bitmap to track chang ARG(OPT_INTEGRITY_RECALCULATE, '\0', POPT_ARG_NONE, N_("Recalculate initial tags automatically."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) +ARG(OPT_INTEGRITY_RECALCULATE_RESET, '\0', POPT_ARG_NONE, N_("Reset automatic recalculate position."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) + ARG(OPT_INTEGRITY_RECOVERY_MODE, 'R', POPT_ARG_NONE, N_("Recovery mode (no journal, no tag checking)"), NULL, CRYPT_ARG_BOOL, {}, {}) ARG(OPT_SECTOR_SIZE, 's', POPT_ARG_STRING, N_("Sector size"), N_("bytes"), CRYPT_ARG_UINT32, { .u32_value = 512 }, OPT_SECTOR_SIZE_ACTIONS) diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h index f3efa8c8..6f142eae 100644 --- a/src/utils_arg_names.h +++ b/src/utils_arg_names.h @@ -70,6 +70,7 @@ #define OPT_INTEGRITY_NO_JOURNAL "integrity-no-journal" #define OPT_INTEGRITY_NO_WIPE "integrity-no-wipe" #define OPT_INTEGRITY_RECALCULATE "integrity-recalculate" +#define OPT_INTEGRITY_RECALCULATE_RESET "integrity-recalculate-reset" #define OPT_INTEGRITY_RECOVERY_MODE "integrity-recovery-mode" #define OPT_INTERLEAVE_SECTORS "interleave-sectors" #define OPT_ITER_TIME "iter-time" diff --git a/tests/integrity-compat-test b/tests/integrity-compat-test index c2c74ac6..882684d1 100755 --- a/tests/integrity-compat-test +++ b/tests/integrity-compat-test @@ -64,6 +64,9 @@ function dm_integrity_features() [ $VER_MIN -gt 6 ] && { DM_INTEGRITY_HMAC_FIX=1 } + [ $VER_MIN -gt 7 ] && { + DM_INTEGRITY_RESET=1 + } } add_device() { @@ -383,7 +386,16 @@ if [ -n "$DM_INTEGRITY_RECALC" ] ; then dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot recalculate tags in-kernel" int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7 $INTSETUP close $DEV_NAME || fail "Cannot deactivate device." - echo "[OK]" + echo -n "[OK]" + if [ -n "$DM_INTEGRITY_RESET" ] ; then + $INTSETUP open $DEV $DEV_NAME -I sha256 --integrity-recalculate-reset || fail "Cannot activate device." + dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot reset recalculate tags in-kernel" + int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7 + $INTSETUP close $DEV_NAME || fail "Cannot deactivate device." + echo "[RESET OK]" + else + echo "[RESET N/A]" + fi else echo "[N/A]" fi