From 630703bf389b87200a6276bc68f53e23c0069f0f Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 15 Nov 2023 16:06:02 +0100 Subject: [PATCH] Suspend and resume also dm-integrity device with AEAD. Currently we suspend top-level device only. With OPAL, the underlying device will start to return errors once OPAL LR is locked. If the dm-integrity device is not suspended, regular journal flush corrupts the device (journal write failure), corrupting data above it. Suspending the whole stack should fix the issue. --- lib/libdevmapper.c | 12 ++++++++++++ lib/setup.c | 39 +++++++++++++++++++++++++++++++++------ lib/utils_dm.h | 1 + 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index a6cf27bbb..a98f199c5 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -3041,6 +3041,18 @@ const char *dm_get_dir(void) return dm_dir(); } +int dm_get_iname(const char *name, char **iname, bool with_path) +{ + int r; + + if (with_path) + r = asprintf(iname, "%s/%s_dif", dm_get_dir(), name); + else + r = asprintf(iname, "%s_dif", name); + + return r < 0 ? -ENOMEM : 0; +} + int dm_is_dm_device(int major) { return dm_is_dm_major((uint32_t)major); diff --git a/lib/setup.c b/lib/setup.c index 889c4d1fc..111c7edf4 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -3894,7 +3894,7 @@ int crypt_suspend(struct crypt_device *cd, struct crypt_dm_active_device dmd; uint32_t opal_segment_number = 1, dmflags = DM_SUSPEND_WIPE_KEY; struct dm_target *tgt = &dmd.segment; - char *key_desc = NULL; + char *key_desc = NULL, *iname = NULL; if (!cd || !name) return -EINVAL; @@ -3989,12 +3989,23 @@ int crypt_suspend(struct crypt_device *cd, goto out; } + if (crypt_get_integrity_tag_size(cd)) { + r = dm_get_iname(name, &iname, false); + if (r) + goto out; + + r = dm_suspend_device(cd, iname, 0); + if (r) + log_err(cd, _("Error during suspending device %s."), iname); + } + crypt_drop_keyring_key_by_description(cd, key_desc, cd->keyring_key_type); if (dm_opal_uuid && (!crypt_data_device(cd) || opal_lock(cd, crypt_data_device(cd), opal_segment_number))) log_err(cd, _("Device %s was suspended but hardware OPAL device cannot be locked."), name); out: free(key_desc); + free(iname); dm_targets_free(cd, &dmd); free(CONST_CAST(void*)dmd.uuid); return r; @@ -4077,6 +4088,7 @@ static int resume_luks2_by_volume_key(struct crypt_device *cd, uint32_t opal_segment_number; key_serial_t user_vk_kid = 0; struct volume_key *p_crypt = vk, *p_opal = NULL, *zerokey = NULL, *crypt_key = NULL, *opal_key = NULL; + char *iname = NULL; assert(digest >= 0); assert(vk && crypt_volume_key_get_id(vk) == digest); @@ -4140,6 +4152,16 @@ static int resume_luks2_by_volume_key(struct crypt_device *cd, } } + if (crypt_get_integrity_tag_size(cd)) { + r = dm_get_iname(name, &iname, false); + if (r) + goto out; + + r = dm_resume_device(cd, iname, 0); + if (r) + log_err(cd, _("Error during resuming device %s."), iname); + } + if (enc_type == CRYPT_OPAL_HW_ONLY) r = dm_resume_device(cd, name, 0); else @@ -4163,6 +4185,7 @@ static int resume_luks2_by_volume_key(struct crypt_device *cd, crypt_free_volume_key(zerokey); crypt_free_volume_key(opal_key); crypt_free_volume_key(crypt_key); + free(iname); return r; } @@ -4743,15 +4766,18 @@ int create_or_reload_device_with_integrity(struct crypt_device *cd, const char * struct crypt_dm_active_device *dmdi) { int r; - const char *iname = NULL; - char *ipath = NULL; + char *iname = NULL, *ipath = NULL; if (!type || !name || !dmd || !dmdi) return -EINVAL; - if (asprintf(&ipath, "%s/%s_dif", dm_get_dir(), name) < 0) - return -ENOMEM; - iname = ipath + strlen(dm_get_dir()) + 1; + r = dm_get_iname(name, &iname, false); + if (r) + goto out; + + r = dm_get_iname(name, &ipath, true); + if (r) + goto out; /* drop CRYPT_ACTIVATE_REFRESH flag if any device is inactive */ r = check_devices(cd, name, iname, &dmd->flags); @@ -4764,6 +4790,7 @@ int create_or_reload_device_with_integrity(struct crypt_device *cd, const char * r = _create_device_with_integrity(cd, type, name, iname, ipath, dmd, dmdi); out: free(ipath); + free(iname); return r; } diff --git a/lib/utils_dm.h b/lib/utils_dm.h index 79212a253..d5eadbdd0 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -234,6 +234,7 @@ int dm_clear_device(struct crypt_device *cd, const char *name); int dm_cancel_deferred_removal(const char *name); const char *dm_get_dir(void); +int dm_get_iname(const char *name, char **iname, bool with_path); int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type);