On Mon, Mar 06, 2023 at 06:53:10 -0600, Or Ozeri wrote: > This commit changes the _qemuDomainStorageSourcePrivate struct > to support multiple secrets (instead of a single one before this commit). > This will useful for storage encryption requiring more than a single secret. > > Signed-off-by: Or Ozeri <oro@xxxxxxxxxx> > --- > src/qemu/qemu_block.c | 22 +++++++----- > src/qemu/qemu_command.c | 20 ++++++----- > src/qemu/qemu_domain.c | 75 ++++++++++++++++++++++++++++++++--------- > src/qemu/qemu_domain.h | 3 +- > tests/qemublocktest.c | 7 ++-- > 5 files changed, 91 insertions(+), 36 deletions(-) [...] > diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c > index 2e3e0f6572..f6d21d2040 100644 > --- a/src/qemu/qemu_block.c > +++ b/src/qemu/qemu_block.c > @@ -581,7 +581,7 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src, > > if (virJSONValueObjectAdd(&encrypt, > "s:format", encformat, > - "s:key-secret", srcPriv->encinfo->alias, > + "s:key-secret", srcPriv->encinfo[0]->alias, > NULL) < 0) > return NULL; > } So, will this be changed in an upcomming commit? > @@ -978,7 +978,7 @@ qemuBlockStorageSourceGetFormatLUKSProps(virStorageSource *src, > { > qemuDomainStorageSourcePrivate *srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); Add a comment here stating that the encryption engine in qemu currently accepts just one secret and that the validation ensures that. > > - if (!srcPriv || !srcPriv->encinfo || !srcPriv->encinfo->alias) { > + if (!srcPriv || !srcPriv->encinfo || !srcPriv->encinfo[0]->alias) { > virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > _("missing secret info for 'luks' driver")); > return -1; > @@ -986,7 +986,7 @@ qemuBlockStorageSourceGetFormatLUKSProps(virStorageSource *src, > > if (virJSONValueObjectAdd(&props, > "s:driver", "luks", > - "s:key-secret", srcPriv->encinfo->alias, > + "s:key-secret", srcPriv->encinfo[0]->alias, > NULL) < 0) > return -1; > > @@ -1054,7 +1054,7 @@ qemuBlockStorageSourceGetCryptoProps(virStorageSource *src, > > return virJSONValueObjectAdd(encprops, > "s:format", encformat, > - "s:key-secret", srcpriv->encinfo->alias, > + "s:key-secret", srcpriv->encinfo[0]->alias, > NULL); > } ... so that's clear why we don't bother with looking at other members of the array in these two. > diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c > index f5dcb46e42..69f0d74b92 100644 > --- a/src/qemu/qemu_command.c > +++ b/src/qemu/qemu_command.c [...] > @@ -1647,12 +1647,12 @@ qemuBuildDriveSourceStr(virDomainDiskDef *disk, > > if (encinfo) { > if (disk->src->format == VIR_STORAGE_FILE_RAW) { > - virBufferAsprintf(buf, "key-secret=%s,", encinfo->alias); > + virBufferAsprintf(buf, "key-secret=%s,", encinfo[0]->alias); > rawluks = true; > } else if (disk->src->format == VIR_STORAGE_FILE_QCOW2 && > disk->src->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) { > virBufferAddLit(buf, "encrypt.format=luks,"); > - virBufferAsprintf(buf, "encrypt.key-secret=%s,", encinfo->alias); > + virBufferAsprintf(buf, "encrypt.key-secret=%s,", encinfo[0]->alias); I'm okay that we don't bother about this case here, but you then must add a validation check which forbids multiple secrets with SD-card disks, as that frontend still uses this code path. [...] > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index 80c9852dae..a3b9b57cfa 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -872,7 +872,13 @@ qemuDomainStorageSourcePrivateDispose(void *obj) > qemuDomainStorageSourcePrivate *priv = obj; > > g_clear_pointer(&priv->secinfo, qemuDomainSecretInfoFree); > - g_clear_pointer(&priv->encinfo, qemuDomainSecretInfoFree); > + if (priv->encinfo) { > + size_t i; > + for (i = 0; i < priv->enccount; ++i) { > + g_clear_pointer(&priv->encinfo[i], qemuDomainSecretInfoFree); > + } > + priv->encinfo = NULL; This leaks the 'encinfo' pointer array. > + } > g_clear_pointer(&priv->httpcookie, qemuDomainSecretInfoFree); > g_clear_pointer(&priv->tlsKeySecret, qemuDomainSecretInfoFree); > g_clear_pointer(&priv->fdpass, qemuFDPassFree);a > @@ -1470,12 +1482,14 @@ qemuDomainSecretStorageSourcePrepare(qemuDomainObjPrivate *priv, > } > > if (hasEnc) { > - if (!(srcPriv->encinfo = qemuDomainSecretInfoSetupFromSecret(priv, aliasformat, > - "encryption", 0, > - VIR_SECRET_USAGE_TYPE_VOLUME, > - NULL, > - &src->encryption->secrets[0]->seclookupdef))) > - return -1; > + srcPriv->enccount = 1; > + srcPriv->encinfo = g_new0(qemuDomainSecretInfo *, 1); > + if (!(srcPriv->encinfo[0] = qemuDomainSecretInfoSetupFromSecret(priv, aliasformat, > + "encryption", 0, > + VIR_SECRET_USAGE_TYPE_VOLUME, > + NULL, > + &src->encryption->secrets[0]->seclookupdef))) Why don't you process multiple secrets here since struct _virStorageEncryption already has multiple secrets? [...] > @@ -1999,8 +2017,27 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr ctxt, > if (qemuStorageSourcePrivateDataAssignSecinfo(&priv->secinfo, &authalias) < 0) > return -1; > > - if (qemuStorageSourcePrivateDataAssignSecinfo(&priv->encinfo, &encalias) < 0) > - return -1; > + if (enccount > 0) { > + xmlNodePtr tmp = ctxt->node; > + > + priv->enccount = enccount; > + priv->encinfo = g_new0(qemuDomainSecretInfo *, enccount); > + for (i = 0; i < enccount; ++i) { > + g_autofree char *encalias = NULL; > + > + ctxt->node = encnodes[i]; > + if (!(encalias = virXMLPropString(encnodes[i], "alias"))) { This does not use XPath .. so you don't need to modify 'ctxt->node' at all, including the 'tmp' variable. If you'd need to do it we have an automatic cleanup method fro that .... > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("missing alias on encryption secret #%lu"), i); > + return -1; ... because e.g. this code path would not un-modify it. > + } > + > + if (qemuStorageSourcePrivateDataAssignSecinfo(&priv->encinfo[i], &encalias) < 0) > + return -1; > + } > + > + ctxt->node = tmp; > + } > > if (qemuStorageSourcePrivateDataAssignSecinfo(&priv->httpcookie, &httpcookiealias) < 0) > return -1; > @@ -2061,10 +2098,13 @@ qemuStorageSourcePrivateDataFormat(virStorageSource *src, > return -1; > > if (srcPriv) { > + size_t i; > unsigned int fdSetID; > > qemuStorageSourcePrivateDataFormatSecinfo(&objectsChildBuf, srcPriv->secinfo, "auth"); > - qemuStorageSourcePrivateDataFormatSecinfo(&objectsChildBuf, srcPriv->encinfo, "encryption"); > + for (i = 0; i < srcPriv->enccount; ++i) { > + qemuStorageSourcePrivateDataFormatSecinfo(&objectsChildBuf, srcPriv->encinfo[i], "encryption"); > + } > qemuStorageSourcePrivateDataFormatSecinfo(&objectsChildBuf, srcPriv->httpcookie, "httpcookie"); > qemuStorageSourcePrivateDataFormatSecinfo(&objectsChildBuf, srcPriv->tlsKeySecret, "tlskey"); For the private data XML formatting and parsing I'd like to see a test scenario being added e.g. to tests/qemustatusxml2xmldata/modern-in.xml