diff --git a/lib/internal.h b/lib/internal.h index 0202b40c..e5388b43 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -98,7 +98,6 @@ int device_alloc_no_check(struct device **device, const char *path); void device_close(struct crypt_device *cd, struct device *device); void device_free(struct crypt_device *cd, struct device *device); const char *device_path(const struct device *device); -const char *device_dm_name(const struct device *device); const char *device_block_path(const struct device *device); void device_topology_alignment(struct crypt_device *cd, struct device *device, @@ -178,6 +177,7 @@ int lookup_by_disk_id(const char *dm_uuid); int lookup_by_sysfs_uuid_field(const char *dm_uuid); int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid); int crypt_uuid_type_cmp(const char *dm_uuid, const char *type); +int crypt_uuid_integrity_cmp(const char *dm_uuid, const char *dmi_uuid); size_t crypt_getpagesize(void); unsigned crypt_cpusonline(void); diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index f2a9a007..203bb070 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -3189,6 +3189,54 @@ int dm_get_iname(const char *name, char **iname, bool with_path) return r < 0 ? -ENOMEM : 0; } +char *dm_get_active_iname(struct crypt_device *cd, const char *name) +{ + struct crypt_dm_active_device dmd = {}, dmdi = {}; + struct dm_target *tgt = &dmd.segment, *tgti = &dmdi.segment; + char *ipath = NULL, *iname = NULL, *ret_iname = NULL; + struct stat st; + + if (!name) + return NULL; + + if (dm_query_device(cd, name, DM_ACTIVE_UUID, &dmd) < 0) + return NULL; + + if (!single_segment(&dmd)) + goto out; + + if (tgt->type != DM_CRYPT || tgt->u.crypt.tag_size == 0) + goto out; + + if (dm_get_iname(name, &iname, false) < 0) + goto out; + + if (dm_get_iname(name, &ipath, true) < 0) + goto out; + + if (stat(ipath, &st) < 0 || !S_ISBLK(st.st_mode)) + goto out; + + if (dm_query_device(cd, iname, DM_ACTIVE_UUID, &dmdi) < 0) + goto out; + + if (single_segment(&dmdi) && + tgti->type == DM_INTEGRITY && + crypt_uuid_integrity_cmp(dmd.uuid, dmdi.uuid) == 0) { + ret_iname = iname; + iname = NULL; + } +out: + dm_targets_free(cd, &dmdi); + dm_targets_free(cd, &dmd); + free(CONST_CAST(void*)dmd.uuid); + free(CONST_CAST(void*)dmdi.uuid); + free(ipath); + free(iname); + + return ret_iname; +} + int dm_is_dm_device(int major) { return dm_is_dm_major((uint32_t)major); diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c index 20d5fd42..6d50e5be 100644 --- a/lib/luks2/luks2_json_metadata.c +++ b/lib/luks2/luks2_json_metadata.c @@ -2834,7 +2834,7 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr struct crypt_dm_active_device dmdc; uint32_t opal_segment_number; char **dep, deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = { 0 }; - const char *namei = NULL; + char *iname = NULL; struct crypt_lock_handle *reencrypt_lock = NULL, *opal_lh = NULL; if (!dmd || !dmd->uuid || strncmp(CRYPT_LUKS2, dmd->uuid, sizeof(CRYPT_LUKS2)-1)) @@ -2856,8 +2856,8 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr tgt = &dmd->segment; /* TODO: We have LUKS2 dependencies now */ - if (single_segment(dmd) && tgt->type == DM_CRYPT && tgt->u.crypt.tag_size) - namei = device_dm_name(tgt->data_device); + if (tgt->type == DM_CRYPT && tgt->u.crypt.tag_size) + iname = dm_get_active_iname(cd, name); r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps)); if (r < 0) @@ -2902,9 +2902,9 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr dm_targets_free(cd, &dmdc); /* TODO: We have LUKS2 dependencies now */ - if (r >= 0 && namei) { - log_dbg(cd, "Deactivating integrity device %s.", namei); - r = dm_remove_device(cd, namei, 0); + if (r >= 0 && iname) { + log_dbg(cd, "Deactivating integrity device %s.", iname); + r = dm_remove_device(cd, iname, 0); } if (!r) { @@ -2972,6 +2972,7 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr out: opal_exclusive_unlock(cd, opal_lh); LUKS2_reencrypt_unlock(cd, reencrypt_lock); + free(iname); dep = deps; while (*dep) free(*dep++); diff --git a/lib/setup.c b/lib/setup.c index 49d76459..bc693449 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -550,7 +550,7 @@ int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid) * compares two UUIDs returned by device-mapper (striped by cryptsetup) * used for stacked LUKS2 & INTEGRITY devices */ -static int crypt_uuid_integrity_cmp(const char *dm_uuid, const char *dmi_uuid) +int crypt_uuid_integrity_cmp(const char *dm_uuid, const char *dmi_uuid) { int i; char *str, *stri; @@ -1310,7 +1310,8 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name) bool found = false; char **dep, *cipher_spec = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN]; char deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = {}; - const char *dev, *namei; + const char *dev; + char *iname = NULL; int key_nums, r; struct crypt_dm_active_device dmd, dmdi = {}, dmdep = {}; struct dm_target *tgt = &dmd.segment, *tgti = &dmdi.segment; @@ -1358,16 +1359,13 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name) dep = deps; - if (tgt->type == DM_CRYPT && tgt->u.crypt.integrity && (namei = device_dm_name(tgt->data_device))) { - r = dm_query_device(cd, namei, DM_ACTIVE_DEVICE, &dmdi); + if (tgt->type == DM_CRYPT && tgt->u.crypt.tag_size && + (iname = dm_get_active_iname(cd, name))) { + + r = dm_query_device(cd, iname, DM_ACTIVE_DEVICE, &dmdi); + free(iname); if (r < 0) goto out; - if (!single_segment(&dmdi) || tgti->type != DM_INTEGRITY) { - log_dbg(cd, "Unsupported device table detected in %s.", namei); - r = -EINVAL; - goto out; - } - /* * Data device for crypt with integrity is not dm-integrity device, * but always the device underlying dm-integrity. @@ -4215,21 +4213,8 @@ int crypt_suspend(struct crypt_device *cd, } /* check UUID of integrity device underneath crypt device */ - if (crypt_get_integrity_tag_size(cd)) { - r = dm_get_iname(name, &iname, false); - if (r) - goto out; - - r = dm_query_device(cd, iname, DM_ACTIVE_UUID, &dmdi); - if (r < 0) - goto out; - - r = crypt_uuid_integrity_cmp(dmd.uuid, dmdi.uuid); - if (r < 0) { - log_dbg(cd, "Integrity device uuid: %s mismatches crypt device uuid %s", dmdi.uuid, dmd.uuid); - goto out; - } - } + if (crypt_get_integrity_tag_size(cd)) + iname = dm_get_active_iname(cd, name); r = dm_status_suspended(cd, name); if (r < 0) @@ -4269,7 +4254,7 @@ int crypt_suspend(struct crypt_device *cd, } /* Suspend integrity device underneath; keep crypt suspended if it fails */ - if (crypt_get_integrity_tag_size(cd)) { + if (iname) { r = dm_suspend_device(cd, iname, 0); if (r) log_err(cd, _("Error during suspending device %s."), iname); @@ -4481,14 +4466,12 @@ 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; - + if (crypt_get_integrity_tag_size(cd) && + (iname = dm_get_active_iname(cd, name))) { r = dm_resume_device(cd, iname, 0); if (r) log_err(cd, _("Error during resuming device %s."), iname); + free(iname); } if (enc_type == CRYPT_OPAL_HW_ONLY) @@ -4517,7 +4500,6 @@ out: crypt_free_volume_key(zerokey); crypt_free_volume_key(opal_key); crypt_free_volume_key(crypt_key); - free(iname); return r; } @@ -5868,7 +5850,7 @@ int crypt_get_active_device(struct crypt_device *cd, const char *name, { int r; struct crypt_dm_active_device dmd, dmdi = {}; - const char *namei = NULL; + char *iname = NULL; struct dm_target *tgt = &dmd.segment; uint64_t min_offset = UINT64_MAX; @@ -5880,10 +5862,11 @@ int crypt_get_active_device(struct crypt_device *cd, const char *name, return r; /* For LUKS2 with integrity we need flags from underlying dm-integrity */ - if (isLUKS2(cd->type) && crypt_get_integrity_tag_size(cd) && single_segment(&dmd)) { - namei = device_dm_name(tgt->data_device); - if (namei && dm_query_device(cd, namei, 0, &dmdi) >= 0) + if (isLUKS2(cd->type) && crypt_get_integrity_tag_size(cd) && + (iname = dm_get_active_iname(cd, name))) { + if (dm_query_device(cd, iname, 0, &dmdi) >= 0) dmd.flags |= dmdi.flags; + free(iname); } if (cd && isTCRYPT(cd->type)) { diff --git a/lib/utils_device.c b/lib/utils_device.c index 9bc2fcb4..90ec9de4 100644 --- a/lib/utils_device.c +++ b/lib/utils_device.c @@ -476,21 +476,6 @@ const char *device_block_path(const struct device *device) return device->path; } -/* Get device-mapper name of device (if possible) */ -const char *device_dm_name(const struct device *device) -{ - const char *dmdir = dm_get_dir(); - size_t dmdir_len = strlen(dmdir); - - if (!device) - return NULL; - - if (strncmp(device->path, dmdir, dmdir_len)) - return NULL; - - return &device->path[dmdir_len+1]; -} - /* Get path to device / file */ const char *device_path(const struct device *device) { diff --git a/lib/utils_dm.h b/lib/utils_dm.h index 60fd0273..036a62a8 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -223,6 +223,7 @@ 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); +char *dm_get_active_iname(struct crypt_device *cd, const char *name); int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type);