block/qcow2: extend qemu-img amend interface with crypto options
Now that we have all the infrastructure in place, wire it in the qcow2 driver and expose this to the user. Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-Id: <20200608094030.670121-9-mlevitsk@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
bbfdae91fb
commit
90766d9db9
|
@ -176,6 +176,19 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QDict*
|
||||||
|
qcow2_extract_crypto_opts(QemuOpts *opts, const char *fmt, Error **errp)
|
||||||
|
{
|
||||||
|
QDict *cryptoopts_qdict;
|
||||||
|
QDict *opts_qdict;
|
||||||
|
|
||||||
|
/* Extract "encrypt." options into a qdict */
|
||||||
|
opts_qdict = qemu_opts_to_qdict(opts, NULL);
|
||||||
|
qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
|
||||||
|
qobject_unref(opts_qdict);
|
||||||
|
qdict_put_str(cryptoopts_qdict, "format", fmt);
|
||||||
|
return cryptoopts_qdict;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read qcow2 extension and fill bs
|
* read qcow2 extension and fill bs
|
||||||
|
@ -4860,16 +4873,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
|
||||||
|
|
||||||
if (has_luks) {
|
if (has_luks) {
|
||||||
g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
|
g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
|
||||||
QDict *opts_qdict;
|
QDict *cryptoopts = qcow2_extract_crypto_opts(opts, "luks", errp);
|
||||||
QDict *cryptoopts;
|
|
||||||
size_t headerlen;
|
size_t headerlen;
|
||||||
|
|
||||||
opts_qdict = qemu_opts_to_qdict(opts, NULL);
|
|
||||||
qdict_extract_subqdict(opts_qdict, &cryptoopts, "encrypt.");
|
|
||||||
qobject_unref(opts_qdict);
|
|
||||||
|
|
||||||
qdict_put_str(cryptoopts, "format", "luks");
|
|
||||||
|
|
||||||
create_opts = block_crypto_create_opts_init(cryptoopts, errp);
|
create_opts = block_crypto_create_opts_init(cryptoopts, errp);
|
||||||
qobject_unref(cryptoopts);
|
qobject_unref(cryptoopts);
|
||||||
if (!create_opts) {
|
if (!create_opts) {
|
||||||
|
@ -5273,6 +5279,7 @@ typedef enum Qcow2AmendOperation {
|
||||||
QCOW2_NO_OPERATION = 0,
|
QCOW2_NO_OPERATION = 0,
|
||||||
|
|
||||||
QCOW2_UPGRADING,
|
QCOW2_UPGRADING,
|
||||||
|
QCOW2_UPDATING_ENCRYPTION,
|
||||||
QCOW2_CHANGING_REFCOUNT_ORDER,
|
QCOW2_CHANGING_REFCOUNT_ORDER,
|
||||||
QCOW2_DOWNGRADING,
|
QCOW2_DOWNGRADING,
|
||||||
} Qcow2AmendOperation;
|
} Qcow2AmendOperation;
|
||||||
|
@ -5354,6 +5361,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
int ret;
|
int ret;
|
||||||
QemuOptDesc *desc = opts->list->desc;
|
QemuOptDesc *desc = opts->list->desc;
|
||||||
Qcow2AmendHelperCBInfo helper_cb_info;
|
Qcow2AmendHelperCBInfo helper_cb_info;
|
||||||
|
bool encryption_update = false;
|
||||||
|
|
||||||
while (desc && desc->name) {
|
while (desc && desc->name) {
|
||||||
if (!qemu_opt_find(opts, desc->name)) {
|
if (!qemu_opt_find(opts, desc->name)) {
|
||||||
|
@ -5380,6 +5388,18 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
|
backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) {
|
||||||
backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
|
backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
|
||||||
|
} else if (g_str_has_prefix(desc->name, "encrypt.")) {
|
||||||
|
if (!s->crypto) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Can't amend encryption options - encryption not present");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Only LUKS encryption options can be amended");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
encryption_update = true;
|
||||||
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
|
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
|
||||||
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
||||||
lazy_refcounts);
|
lazy_refcounts);
|
||||||
|
@ -5422,7 +5442,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
.original_status_cb = status_cb,
|
.original_status_cb = status_cb,
|
||||||
.original_cb_opaque = cb_opaque,
|
.original_cb_opaque = cb_opaque,
|
||||||
.total_operations = (new_version != old_version)
|
.total_operations = (new_version != old_version)
|
||||||
+ (s->refcount_bits != refcount_bits)
|
+ (s->refcount_bits != refcount_bits) +
|
||||||
|
(encryption_update == true)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Upgrade first (some features may require compat=1.1) */
|
/* Upgrade first (some features may require compat=1.1) */
|
||||||
|
@ -5435,6 +5456,33 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (encryption_update) {
|
||||||
|
QDict *amend_opts_dict;
|
||||||
|
QCryptoBlockAmendOptions *amend_opts;
|
||||||
|
|
||||||
|
helper_cb_info.current_operation = QCOW2_UPDATING_ENCRYPTION;
|
||||||
|
amend_opts_dict = qcow2_extract_crypto_opts(opts, "luks", errp);
|
||||||
|
if (!amend_opts_dict) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
amend_opts = block_crypto_amend_opts_init(amend_opts_dict, errp);
|
||||||
|
qobject_unref(amend_opts_dict);
|
||||||
|
if (!amend_opts) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ret = qcrypto_block_amend_options(s->crypto,
|
||||||
|
qcow2_crypto_hdr_read_func,
|
||||||
|
qcow2_crypto_hdr_write_func,
|
||||||
|
bs,
|
||||||
|
amend_opts,
|
||||||
|
force,
|
||||||
|
errp);
|
||||||
|
qapi_free_QCryptoBlockAmendOptions(amend_opts);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (s->refcount_bits != refcount_bits) {
|
if (s->refcount_bits != refcount_bits) {
|
||||||
int refcount_order = ctz32(refcount_bits);
|
int refcount_order = ctz32(refcount_bits);
|
||||||
|
|
||||||
|
@ -5694,6 +5742,11 @@ static QemuOptsList qcow2_amend_opts = {
|
||||||
.name = "qcow2-amend-opts",
|
.name = "qcow2-amend-opts",
|
||||||
.head = QTAILQ_HEAD_INITIALIZER(qcow2_amend_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(qcow2_amend_opts.head),
|
||||||
.desc = {
|
.desc = {
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_STATE("encrypt."),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT("encrypt."),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET("encrypt."),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET("encrypt."),
|
||||||
|
BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."),
|
||||||
QCOW_COMMON_OPTIONS,
|
QCOW_COMMON_OPTIONS,
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
}
|
}
|
||||||
|
|
|
@ -645,6 +645,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -656,6 +661,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -667,6 +677,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -678,6 +693,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -689,6 +709,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -700,6 +725,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -711,6 +741,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -722,6 +757,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
@ -750,6 +790,11 @@ Amend options for 'qcow2':
|
||||||
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
|
||||||
data_file=<str> - File name of an external data file
|
data_file=<str> - File name of an external data file
|
||||||
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
|
||||||
|
encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
|
||||||
|
encrypt.keyslot=<num> - Select a single keyslot to modify explicitly
|
||||||
|
encrypt.new-secret=<str> - New secret to set in the matching keyslots. Empty string to erase
|
||||||
|
encrypt.old-secret=<str> - Select all keyslots that match this password
|
||||||
|
encrypt.state=<str> - Select new state of affected keyslots (active/inactive)
|
||||||
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
|
||||||
refcount_bits=<num> - Width of a reference count entry in bits
|
refcount_bits=<num> - Width of a reference count entry in bits
|
||||||
size=<size> - Virtual disk size
|
size=<size> - Virtual disk size
|
||||||
|
|
Loading…
Reference in New Issue