Commit d06defd8 authored by Milan Broz's avatar Milan Broz

Add automatic recalculation to dm-integrity.

Linux kernel since version 4.18 supports automatic background
recalculation of integrity tags for dm-integrity.

This patch adds new integritysetup --integrity-recalculate options
that uses this option.
parent 0fed68dd
......@@ -977,6 +977,8 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
#define CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE (1 << 15)
/** allow activation check including unbound keyslots (keyslots without segments) */
#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (1 << 16)
/** dm-integrity: activate automatic recalculation */
#define CRYPT_ACTIVATE_RECALCULATE (1 << 17)
/**
* Active device runtime attributes
......
......@@ -209,6 +209,9 @@ static void _dm_set_integrity_compat(struct crypt_device *cd,
_dm_flags |= DM_INTEGRITY_SUPPORTED;
if (_dm_satisfies_version(1, 2, 0, integrity_maj, integrity_min, integrity_patch))
_dm_flags |= DM_INTEGRITY_RECALC_SUPPORTED;
_dm_integrity_checked = true;
}
......@@ -683,7 +686,7 @@ out:
}
static char *get_dm_integrity_params(struct crypt_dm_active_device *dmd, uint32_t flags)
static char *get_dm_integrity_params(struct crypt_dm_active_device *dmd, uint32_t flags, uint32_t dmflags)
{
int r, max_size, num_options = 0;
char *params, *hexkey, mode;
......@@ -801,6 +804,12 @@ static char *get_dm_integrity_params(struct crypt_dm_active_device *dmd, uint32_
crypt_safe_free(hexkey);
}
if ((dmflags & DM_INTEGRITY_RECALC_SUPPORTED) && (flags & CRYPT_ACTIVATE_RECALCULATE)) {
num_options++;
snprintf(feature, sizeof(feature), "recalculate ");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (flags & CRYPT_ACTIVATE_RECOVERY)
mode = 'R';
else if (flags & CRYPT_ACTIVATE_NO_JOURNAL)
......@@ -1194,14 +1203,14 @@ int dm_create_device(struct crypt_device *cd, const char *name,
return -ENOTSUP;
dmd_flags = dmd->flags;
dmt_flags = 0;
dm_flags(cd, dmd->target, &dmt_flags);
if (dmd->target == DM_CRYPT)
table_params = get_dm_crypt_params(dmd, dmd_flags);
else if (dmd->target == DM_VERITY)
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd, dmd_flags);
else if (dmd->target == DM_INTEGRITY)
table_params = get_dm_integrity_params(dmd, dmd_flags);
table_params = get_dm_integrity_params(dmd, dmd_flags, dmt_flags);
else
goto out;
......@@ -1928,6 +1937,8 @@ static int _dm_query_integrity(struct crypt_device *cd,
goto err;
}
}
} else if (!strcmp(arg, "recalculate")) {
dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
} else /* unknown option */
goto err;
}
......
......@@ -49,6 +49,7 @@ struct device;
#define DM_SECTOR_SIZE_SUPPORTED (1 << 13) /* support for sector size setting in dm-crypt/dm-integrity */
#define DM_CAPI_STRING_SUPPORTED (1 << 14) /* support for cryptoapi format cipher definition */
#define DM_DEFERRED_SUPPORTED (1 << 15) /* deferred removal of device */
#define DM_INTEGRITY_RECALC_SUPPORTED (1 << 16) /* dm-integrity automatic recalculation supported */
typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_UNKNOWN } dm_target_type;
......
......@@ -32,7 +32,7 @@ Open a mapping with <name> backed by device <device>.
\fB<options>\fR can be [\-\-batch\-mode, \-\-journal\-watermark, \-\-journal\-commit\-time,
\-\-buffer\-sectors, \-\-integrity, \-\-integrity\-key\-size, \-\-integrity\-key\-file,
\-\-integrity\-no\-journal, \-\-integrity\-recovery\-mode]
\-\-integrity\-no\-journal, \-\-integrity\-recalculate, \-\-integrity\-recovery\-mode]
.PP
\fIclose\fR <name>
......@@ -77,6 +77,12 @@ Size of the journal.
.B "\-\-interleave\-sectors SECTORS"
The number of interleaved sectors.
.TP
.B "\-\-integrity\-recalculate"
Automatically recalculate integrity tags in kernel on activation.
The device can be used during automatic integrity recalculation but becomes fully
integrity protected only after the backgroud operation is finished.
This option is available since the Linux kernel version 4.19.
.TP
.B "\-\-journal\-watermark PERCENT"
Journal watermark in percents. When the size of the journal exceeds this watermark,
the journal flush will be started.
......
......@@ -54,6 +54,8 @@ static int opt_journal_crypt_key_size = 0;
static int opt_integrity_nojournal = 0;
static int opt_integrity_recovery = 0;
static int opt_integrity_recalculate = 0;
static int opt_version_mode = 0;
static const char **action_argv;
......@@ -299,6 +301,9 @@ static int action_open(int arg)
if (opt_integrity_recovery)
activate_flags |= CRYPT_ACTIVATE_RECOVERY;
if (opt_integrity_recalculate)
activate_flags |= CRYPT_ACTIVATE_RECALCULATE;
r = _read_keys(&integrity_key, &params);
if (r)
goto out;
......@@ -530,6 +535,7 @@ int main(int argc, const char **argv)
{ "integrity-no-journal", 'D', POPT_ARG_NONE, &opt_integrity_nojournal, 0, N_("Disable journal for integrity device"), NULL },
{ "integrity-recovery-mode", 'R', POPT_ARG_NONE, &opt_integrity_recovery, 0, N_("Recovery mode (no journal, no tag checking)"), NULL },
{ "integrity-recalculate", '\0', POPT_ARG_NONE, &opt_integrity_recalculate, 0, N_("Recalculate initial tags automatically."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
......@@ -606,6 +612,11 @@ int main(int argc, const char **argv)
if (!strcmp(aname, "format") && opt_tag_size == 0)
opt_tag_size = DEFAULT_TAG_SIZE;
if (opt_integrity_recalculate && strcmp(aname, "open"))
usage(popt_context, EXIT_FAILURE,
_("Option --integrity-recalculate can be used only for open action."),
poptGetInvocationName(popt_context));
if (opt_interleave_sectors < 0 || opt_journal_watermark < 0 ||
opt_journal_commit_time < 0 || opt_tag_size < 0 ||
opt_sector_size < 0 || opt_buffer_sectors < 0 ||
......
......@@ -311,4 +311,15 @@ int_mode sha256 32 512
int_mode hmac-sha256 32 512 $KEY_FILE 32
int_mode hmac-sha256 32 4096 $KEY_FILE 32
echo -n "Recalculate tags in-kernel:"
$INTSETUP format -q $DEV --no-wipe || fail "Cannot format device."
$INTSETUP open $DEV $DEV_NAME --integrity-recalculate || fail "Cannot activate device with journal."
$INTSETUP dump $DEV | grep -q recalculating
if [ $? -eq 0 ] ; then
dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot tags recalculate in-kernel"
echo "[OK]"
else
echo "[N/A]"
fi
cleanup
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