Split low level code for creating dm devices.

The separate code for reloading device tables
will be used in later features.
This commit is contained in:
Ondrej Kozina
2018-11-13 13:33:55 +01:00
committed by Milan Broz
parent 6e1e11f6cd
commit 120ebea917
10 changed files with 175 additions and 70 deletions

View File

@@ -237,7 +237,7 @@ int INTEGRITY_activate(struct crypt_device *cd,
return r;
}
r = dm_create_device(cd, name, "INTEGRITY", &dmdi, 0);
r = dm_create_device(cd, name, "INTEGRITY", &dmdi);
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel doesn't support dm-integrity mapping."));
return -ENOTSUP;
@@ -309,7 +309,7 @@ int INTEGRITY_format(struct crypt_device *cd,
if (params && params->integrity_key_size)
dmdi.u.integrity.vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
r = dm_create_device(cd, tmp_name, "INTEGRITY", &dmdi, 0);
r = dm_create_device(cd, tmp_name, "INTEGRITY", &dmdi);
crypt_free_volume_key(dmdi.u.integrity.vk);
if (r)

View File

@@ -900,6 +900,8 @@ out:
return r;
}
static int _dm_resume_device(const char *name, uint32_t flags);
static int _error_device(const char *name, size_t size)
{
struct dm_task *dmt;
@@ -923,7 +925,7 @@ static int _error_device(const char *name, size_t size)
if (!dm_task_run(dmt))
goto error;
if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
if (_dm_resume_device(name, 0)) {
_dm_simple(DM_DEVICE_CLEAR, name, 0);
goto error;
}
@@ -1051,16 +1053,14 @@ int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char
static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
struct device *device, uint32_t flags,
const char *uuid, uint64_t size,
dm_target_type target, char *params, int reload)
dm_target_type target, char *params)
{
struct dm_task *dmt = NULL;
struct dm_info dmi;
char dev_uuid[DM_UUID_LEN] = {0};
const char *target_name;
int r = -EINVAL;
uint32_t read_ahead = 0;
uint32_t cookie = 0;
uint32_t dmt_flags;
uint32_t dmt_flags, cookie = 0, read_ahead = 0;
uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
/* Only need DM_SECURE_SUPPORTED, no target specific fail matters */
@@ -1082,74 +1082,49 @@ static int _dm_create_device(struct crypt_device *cd, const char *name, const ch
udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
/* All devices must have DM_UUID, only resize on old device is exception */
if (reload) {
if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
goto out_no_removal;
if (!dm_prepare_uuid(cd, name, type, uuid, dev_uuid, sizeof(dev_uuid)))
goto out;
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
} else {
if (!dm_prepare_uuid(cd, name, type, uuid, dev_uuid, sizeof(dev_uuid)))
goto out_no_removal;
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out;
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out_no_removal;
if (!dm_task_set_name(dmt, name))
goto out;
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
if (!dm_task_set_uuid(dmt, dev_uuid))
goto out_no_removal;
}
if (!dm_task_set_uuid(dmt, dev_uuid))
goto out;
if ((dmt_flags & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
goto out_no_removal;
goto out;
if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
goto out_no_removal;
goto out;
if (!dm_task_add_target(dmt, 0, size, target_name, params))
goto out_no_removal;
goto out;
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
if (device_read_ahead(device, &read_ahead) &&
!dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
goto out_no_removal;
goto out;
#endif
/* do not set cookie for DM_DEVICE_RELOAD task */
if (!reload && _dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out_no_removal;
if (!dm_task_run(dmt))
goto out_no_removal;
if (reload) {
dm_task_destroy(dmt);
if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
goto out;
if (!dm_task_set_name(dmt, name))
goto out;
if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
goto out;
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (!dm_task_run(dmt))
goto out;
}
if (!dm_task_get_info(dmt, &dmi))
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
r = 0;
out:
if (!dm_task_run(dmt))
goto out;
if (dm_task_get_info(dmt, &dmi))
r = 0;
if (_dm_use_udev()) {
(void)_dm_udev_wait(cookie);
cookie = 0;
}
if (r < 0 && !reload)
if (r < 0)
_dm_remove(name, 1, 0);
out_no_removal:
out:
if (cookie && _dm_use_udev())
(void)_dm_udev_wait(cookie);
@@ -1164,6 +1139,96 @@ out_no_removal:
return r;
}
static int _dm_resume_device(const char *name, uint32_t flags)
{
struct dm_task *dmt;
int r = -EINVAL;
uint32_t cookie = 0;
uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (flags & CRYPT_ACTIVATE_PRIVATE)
udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
return r;
if (!dm_task_set_name(dmt, name))
goto out;
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (dm_task_run(dmt))
r = 0;
out:
if (cookie && _dm_use_udev())
(void)_dm_udev_wait(cookie);
dm_task_destroy(dmt);
dm_task_update_nodes();
return r;
}
static int _dm_reload_device(struct crypt_device *cd,
const char *name, struct device *device,
uint32_t flags, uint64_t size,
dm_target_type target, const char *params)
{
const char *target_name;
int r = -EINVAL;
struct dm_task *dmt = NULL;
uint32_t dmt_flags = 0, read_ahead = 0;
if (target == DM_CRYPT)
target_name = DM_CRYPT_TARGET;
else if (target == DM_VERITY)
target_name = DM_VERITY_TARGET;
else if (target == DM_INTEGRITY)
target_name = DM_INTEGRITY_TARGET;
else
return -EINVAL;
/* All devices must have DM_UUID, only resize on old device is exception */
if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
goto out;
if (!dm_task_set_name(dmt, name))
goto out;
if (dm_flags(cd, target, &dmt_flags))
goto out;
if ((dmt_flags & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
goto out;
/* FIXME: resume only ?*/
if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
goto out;
if (!dm_task_add_target(dmt, 0, size, target_name, params))
goto out;
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
if (device_read_ahead(device, &read_ahead) &&
!dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
goto out;
#endif
if (dm_task_run(dmt))
r = 0;
out:
if (dmt)
dm_task_destroy(dmt);
/* If code just loaded target module, update versions */
_dm_check_versions(cd, target);
return r;
}
static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dmt_flags)
{
int ret = 0;
@@ -1197,8 +1262,7 @@ static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dm
int dm_create_device(struct crypt_device *cd, const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
int reload)
struct crypt_dm_active_device *dmd)
{
char *table_params = NULL;
uint32_t dmd_flags, dmt_flags;
@@ -1223,16 +1287,16 @@ int dm_create_device(struct crypt_device *cd, const char *name,
goto out;
r = _dm_create_device(cd, name, type, dmd->data_device, dmd_flags,
dmd->uuid, dmd->size, dmd->target, table_params, reload);
dmd->uuid, dmd->size, dmd->target, table_params);
if (r < 0 && dm_flags(cd, dmd->target, &dmt_flags))
goto out;
if (!reload && r && dmd->target == DM_CRYPT && check_retry(cd, &dmd_flags, dmt_flags)) {
if (r && dmd->target == DM_CRYPT && check_retry(cd, &dmd_flags, dmt_flags)) {
crypt_safe_free(table_params);
table_params = get_dm_crypt_params(dmd, dmd_flags);
r = _dm_create_device(cd, name, type, dmd->data_device, dmd_flags,
dmd->uuid, dmd->size, dmd->target, table_params, reload);
dmd->uuid, dmd->size, dmd->target, table_params);
}
if (r == -EINVAL &&
@@ -1263,6 +1327,46 @@ out:
return r;
}
int dm_reload_device(struct crypt_device *cd, const char *name,
struct crypt_dm_active_device *dmd, unsigned resume)
{
char *table_params = NULL;
uint32_t dmt_flags;
int r = -EINVAL;
if (dm_init_context(cd, dmd->target))
return -ENOTSUP;
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, dmt_flags);
else
return r;
r = _dm_reload_device(cd, name, dmd->data_device, dmd->flags, dmd->size,
dmd->target, table_params);
if (r == -EINVAL && dmd->target == DM_CRYPT) {
if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED))
log_err(cd, _("Discard/TRIM is not supported."));
}
if (!r && resume)
r = _dm_resume_device(name, dmd->flags);
dm_exit_context();
return r;
}
static int dm_status_dmi(const char *name, struct dm_info *dmi,
const char *target, char **status_line)
{
@@ -2138,7 +2242,7 @@ int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name)
}
if (!_dm_message(name, "key wipe", dmt_flags)) {
_dm_simple(DM_DEVICE_RESUME, name, 1);
_dm_resume_device(name, 0);
r = -EINVAL;
goto out;
}
@@ -2180,7 +2284,7 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
hex_key(&msg[8], vk->keylength, vk->key);
if (!_dm_message(name, msg, dmt_flags) ||
!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
_dm_resume_device(name, 0)) {
r = -EINVAL;
goto out;
}

View File

@@ -239,7 +239,7 @@ int LOOPAES_activate(struct crypt_device *cd,
log_dbg(cd, "Trying to activate loop-AES device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd);
if (r < 0 && !dm_flags(cd, DM_CRYPT, &dmc_flags) &&
(dmc_flags & req_flags) != req_flags) {

View File

@@ -110,7 +110,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
return -EACCES;
}
r = dm_create_device(ctx, name, "TEMP", &dmd, 0);
r = dm_create_device(ctx, name, "TEMP", &dmd);
if (r < 0) {
if (r != -EACCES && r != -ENOTSUP)
_error_hint(ctx, device_path(dmd.data_device),

View File

@@ -1189,7 +1189,7 @@ int LUKS1_activate(struct crypt_device *cd,
return -ENOMEM;
dmd.u.crypt.cipher = dm_cipher;
r = dm_create_device(cd, name, CRYPT_LUKS1, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LUKS1, &dmd);
free(dm_cipher);
return r;

View File

@@ -1934,7 +1934,7 @@ int LUKS2_activate(struct crypt_device *cd,
r = device_block_adjust(cd, dmd.data_device, device_check,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (!r)
r = dm_create_device(cd, name, CRYPT_LUKS2, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LUKS2, &dmd);
if (r < 0 && dmd.u.crypt.integrity)
dm_remove_device(cd, dm_int_name, 0);

View File

@@ -517,7 +517,7 @@ int PLAIN_activate(struct crypt_device *cd,
log_dbg(cd, "Trying to activate PLAIN device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(cd, name, CRYPT_PLAIN, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_PLAIN, &dmd);
free(dm_cipher);
return r;
@@ -2211,7 +2211,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
else if (isLUKS2(cd->type))
r = LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, 0);
if (!r)
r = dm_create_device(cd, name, cd->type, &dmd, 1);
r = dm_reload_device(cd, name, &dmd, 1);
}
out:
if (dmd.target == DM_CRYPT) {

View File

@@ -846,7 +846,7 @@ int TCRYPT_activate(struct crypt_device *cd,
log_dbg(cd, "Trying to activate TCRYPT device %s using cipher %s.",
dm_name, dmd.u.crypt.cipher);
r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd, 0);
r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd);
device_free(cd, device);
device = NULL;

View File

@@ -139,8 +139,9 @@ int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint
int dm_query_device(struct crypt_device *cd, const char *name,
uint32_t get_flags, struct crypt_dm_active_device *dmd);
int dm_create_device(struct crypt_device *cd, const char *name,
const char *type, struct crypt_dm_active_device *dmd,
int reload);
const char *type, struct crypt_dm_active_device *dmd);
int dm_reload_device(struct crypt_device *cd, const char *name,
struct crypt_dm_active_device *dmd, unsigned resume);
int dm_suspend_device(struct crypt_device *cd, const char *name);
int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name);
int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,

View File

@@ -303,7 +303,7 @@ int VERITY_activate(struct crypt_device *cd,
return r;
}
r = dm_create_device(cd, name, CRYPT_VERITY, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_VERITY, &dmd);
if (r < 0 && (dm_flags(cd, DM_VERITY, &dmv_flags) || !(dmv_flags & DM_VERITY_SUPPORTED))) {
log_err(cd, _("Kernel doesn't support dm-verity mapping."));
return -ENOTSUP;