Adding virDomainSecDef for general launch security data and moving virDomainSEVDef as an element for SEV data. Signed-off-by: Boris Fiuczynski <fiuczy@xxxxxxxxxxxxx> Reviewed-by: Daniel Henrique Barboza <danielhb413@xxxxxxxxx> --- src/conf/domain_conf.c | 133 +++++++++++++++++++++--------------- src/conf/domain_conf.h | 16 +++-- src/conf/virconftypes.h | 2 + src/qemu/qemu_cgroup.c | 4 +- src/qemu/qemu_command.c | 47 ++++++++++--- src/qemu/qemu_driver.c | 3 +- src/qemu/qemu_firmware.c | 32 +++++---- src/qemu/qemu_namespace.c | 20 ++++-- src/qemu/qemu_process.c | 34 +++++++-- src/qemu/qemu_validate.c | 22 ++++-- src/security/security_dac.c | 6 +- 11 files changed, 217 insertions(+), 102 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 74254d505b..af7b4f8ef8 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3491,17 +3491,25 @@ virDomainResctrlDefFree(virDomainResctrlDef *resctrl) void -virDomainSEVDefFree(virDomainSEVDef *def) +virDomainSecDefFree(virDomainSecDef *def) { if (!def) return; - g_free(def->dh_cert); - g_free(def->session); + switch ((virDomainLaunchSecurity) def->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + g_free(def->data.sev.dh_cert); + g_free(def->data.sev.session); + break; + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + break; + } g_free(def); } + static void virDomainOSDefClear(virDomainOSDef *os) { @@ -3703,7 +3711,7 @@ void virDomainDefFree(virDomainDef *def) if (def->namespaceData && def->ns.free) (def->ns.free)(def->namespaceData); - virDomainSEVDefFree(def->sev); + virDomainSecDefFree(def->sec); xmlFreeNode(def->metadata); @@ -14714,68 +14722,82 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, } -static virDomainSEVDef * -virDomainSEVDefParseXML(xmlNodePtr sevNode, +static int +virDomainSEVDefParseXML(virDomainSEVDef *def, + xmlNodePtr sevNode, xmlXPathContextPtr ctxt) { VIR_XPATH_NODE_AUTORESTORE(ctxt) - g_autoptr(virDomainSEVDef) def = NULL; unsigned long policy; int rc; - def = g_new0(virDomainSEVDef, 1); - ctxt->node = sevNode; - if (virXMLPropEnum(sevNode, "type", virDomainLaunchSecurityTypeFromString, - VIR_XML_PROP_NONZERO | VIR_XML_PROP_REQUIRED, - &def->sectype) < 0) - return NULL; + if (virXPathULongHex("string(./policy)", ctxt, &policy) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("failed to get launch security policy")); + return -1; + } - switch ((virDomainLaunchSecurity) def->sectype) { - case VIR_DOMAIN_LAUNCH_SECURITY_SEV: - if (virXPathULongHex("string(./policy)", ctxt, &policy) < 0) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("failed to get launch security policy")); - return NULL; - } + /* the following attributes are platform dependent and if missing, we can + * autofill them from domain capabilities later + */ + rc = virXPathUInt("string(./cbitpos)", ctxt, &def->cbitpos); + if (rc == 0) { + def->haveCbitpos = true; + } else if (rc == -2) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid format for launch security cbitpos")); + return -1; + } - /* the following attributes are platform dependent and if missing, we can - * autofill them from domain capabilities later - */ - rc = virXPathUInt("string(./cbitpos)", ctxt, &def->cbitpos); - if (rc == 0) { - def->haveCbitpos = true; - } else if (rc == -2) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Invalid format for launch security cbitpos")); - return NULL; - } + rc = virXPathUInt("string(./reducedPhysBits)", ctxt, + &def->reduced_phys_bits); + if (rc == 0) { + def->haveReducedPhysBits = true; + } else if (rc == -2) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid format for launch security " + "reduced-phys-bits")); + return -1; + } + + def->policy = policy; + def->dh_cert = virXPathString("string(./dhCert)", ctxt); + def->session = virXPathString("string(./session)", ctxt); + + return 0; +} - rc = virXPathUInt("string(./reducedPhysBits)", ctxt, - &def->reduced_phys_bits); - if (rc == 0) { - def->haveReducedPhysBits = true; - } else if (rc == -2) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Invalid format for launch security " - "reduced-phys-bits")); - return NULL; - } - def->policy = policy; - def->dh_cert = virXPathString("string(./dhCert)", ctxt); - def->session = virXPathString("string(./session)", ctxt); +static virDomainSecDef * +virDomainSecDefParseXML(xmlNodePtr lsecNode, + xmlXPathContextPtr ctxt) +{ + g_autoptr(virDomainSecDef) sec = g_new0(virDomainSecDef, 1); + + ctxt->node = lsecNode; + + if (virXMLPropEnum(lsecNode, "type", virDomainLaunchSecurityTypeFromString, + VIR_XML_PROP_NONZERO | VIR_XML_PROP_REQUIRED, + &sec->sectype) < 0) + return NULL; - return g_steal_pointer(&def); + switch ((virDomainLaunchSecurity) sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + if (virDomainSEVDefParseXML(&sec->data.sev, lsecNode, ctxt) < 0) + return NULL; + break; case VIR_DOMAIN_LAUNCH_SECURITY_NONE: case VIR_DOMAIN_LAUNCH_SECURITY_LAST: default: virReportError(VIR_ERR_XML_ERROR, _("unsupported launch security type '%s'"), - virDomainLaunchSecurityTypeToString(def->sectype)); + virDomainLaunchSecurityTypeToString(sec->sectype)); return NULL; } + + return g_steal_pointer(&sec); } @@ -20130,10 +20152,10 @@ virDomainDefParseXML(xmlDocPtr xml, ctxt->node = node; VIR_FREE(nodes); - /* Check for SEV feature */ + /* Check for launch security e.g. SEV feature */ if ((node = virXPathNode("./launchSecurity", ctxt)) != NULL) { - def->sev = virDomainSEVDefParseXML(node, ctxt); - if (!def->sev) + def->sec = virDomainSecDefParseXML(node, ctxt); + if (!def->sec) goto error; } @@ -26864,19 +26886,21 @@ virDomainKeyWrapDefFormat(virBuffer *buf, virDomainKeyWrapDef *keywrap) static void -virDomainSEVDefFormat(virBuffer *buf, virDomainSEVDef *sev) +virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec) { g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - if (!sev) + if (!sec) return; virBufferAsprintf(&attrBuf, " type='%s'", - virDomainLaunchSecurityTypeToString(sev->sectype)); + virDomainLaunchSecurityTypeToString(sec->sectype)); - switch ((virDomainLaunchSecurity) sev->sectype) { + switch ((virDomainLaunchSecurity) sec->sectype) { case VIR_DOMAIN_LAUNCH_SECURITY_SEV: { + virDomainSEVDef *sev = &sec->data.sev; + if (sev->haveCbitpos) virBufferAsprintf(&childBuf, "<cbitpos>%d</cbitpos>\n", sev->cbitpos); @@ -26892,6 +26916,7 @@ virDomainSEVDefFormat(virBuffer *buf, virDomainSEVDef *sev) break; } + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: case VIR_DOMAIN_LAUNCH_SECURITY_LAST: return; @@ -28306,7 +28331,7 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, if (def->keywrap) virDomainKeyWrapDefFormat(buf, def->keywrap); - virDomainSEVDefFormat(buf, def->sev); + virDomainSecDefFormat(buf, def->sec); if (def->namespaceData && def->ns.format) { if ((def->ns.format)(buf, def->namespaceData) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f3a4d0fa93..4e6426ee78 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2651,7 +2651,6 @@ typedef enum { struct _virDomainSEVDef { - virDomainLaunchSecurity sectype; char *dh_cert; char *session; unsigned int policy; @@ -2661,8 +2660,15 @@ struct _virDomainSEVDef { unsigned int reduced_phys_bits; }; -void virDomainSEVDefFree(virDomainSEVDef *def); -G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSEVDef, virDomainSEVDefFree); +struct _virDomainSecDef { + virDomainLaunchSecurity sectype; + union { + virDomainSEVDef sev; + } data; +}; + +void virDomainSecDefFree(virDomainSecDef *def); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSecDef, virDomainSecDefFree); typedef enum { VIR_DOMAIN_IOMMU_MODEL_INTEL, @@ -2873,8 +2879,8 @@ struct _virDomainDef { virDomainKeyWrapDef *keywrap; - /* SEV-specific domain */ - virDomainSEVDef *sev; + /* launch security e.g. SEV */ + virDomainSecDef *sec; /* Application-specific custom metadata */ xmlNodePtr metadata; diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index b21068486e..21420ba8ea 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -202,6 +202,8 @@ typedef struct _virDomainResourceDef virDomainResourceDef; typedef struct _virDomainSEVDef virDomainSEVDef; +typedef struct _virDomainSecDef virDomainSecDef; + typedef struct _virDomainShmemDef virDomainShmemDef; typedef struct _virDomainSmartcardDef virDomainSmartcardDef; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 038d6478b2..f2d99abcfa 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -856,7 +856,9 @@ qemuSetupDevicesCgroup(virDomainObj *vm) return -1; } - if (vm->def->sev && qemuSetupSEVCgroup(vm) < 0) + if (vm->def->sec && + vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV && + qemuSetupSEVCgroup(vm) < 0) return -1; return 0; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6af1faa3cd..61fecc607b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6967,11 +6967,20 @@ qemuBuildMachineCommandLine(virCommand *cmd, if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM)) qemuAppendLoadparmMachineParm(&buf, def); - if (def->sev) { - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT)) { - virBufferAddLit(&buf, ",confidential-guest-support=sev0"); - } else { - virBufferAddLit(&buf, ",memory-encryption=sev0"); + if (def->sec) { + switch ((virDomainLaunchSecurity) def->sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT)) { + virBufferAddLit(&buf, ",confidential-guest-support=sev0"); + } else { + virBufferAddLit(&buf, ",memory-encryption=sev0"); + } + break; + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + break; + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + virReportEnumRangeError(virDomainLaunchSecurity, def->sec->sectype); + return -1; } } @@ -9838,9 +9847,6 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, g_autofree char *dhpath = NULL; g_autofree char *sessionpath = NULL; - if (!sev) - return 0; - VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d", sev->policy, sev->cbitpos, sev->reduced_phys_bits); @@ -9867,6 +9873,29 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd, return 0; } + +static int +qemuBuildSecCommandLine(virDomainObj *vm, virCommand *cmd, + virDomainSecDef *sec) +{ + if (!sec) + return 0; + + switch ((virDomainLaunchSecurity) sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + return qemuBuildSEVCommandLine(vm, cmd, &sec->data.sev); + break; + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + break; + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype); + return -1; + } + + return 0; +} + + static int qemuBuildVMCoreInfoCommandLine(virCommand *cmd, const virDomainDef *def) @@ -10566,7 +10595,7 @@ qemuBuildCommandLine(virQEMUDriver *driver, if (qemuBuildVMCoreInfoCommandLine(cmd, def) < 0) return NULL; - if (qemuBuildSEVCommandLine(vm, cmd, def->sev) < 0) + if (qemuBuildSecCommandLine(vm, cmd, def->sec) < 0) return NULL; if (snapshot) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index df44c3fbd0..85cc87586c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19853,7 +19853,8 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain, if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0) goto cleanup; - if (vm->def->sev) { + if (vm->def->sec && + vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) { if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 0) goto cleanup; } diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index e17b024b06..6f83ebafe9 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1053,19 +1053,27 @@ qemuFirmwareMatchDomain(const virDomainDef *def, return false; } - if (def->sev && - def->sev->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) { - if (!supportsSEV) { - VIR_DEBUG("Domain requires SEV, firmware '%s' doesn't support it", - path); - return false; - } + if (def->sec) { + switch ((virDomainLaunchSecurity) def->sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + if (!supportsSEV) { + VIR_DEBUG("Domain requires SEV, firmware '%s' doesn't support it", + path); + return false; + } - if (def->sev->policy & VIR_QEMU_FIRMWARE_AMD_SEV_ES_POLICY && - !supportsSEVES) { - VIR_DEBUG("Domain requires SEV-ES, firmware '%s' doesn't support it", - path); - return false; + if (def->sec->data.sev.policy & VIR_QEMU_FIRMWARE_AMD_SEV_ES_POLICY && + !supportsSEVES) { + VIR_DEBUG("Domain requires SEV-ES, firmware '%s' doesn't support it", + path); + return false; + } + break; + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + break; + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + virReportEnumRangeError(virDomainLaunchSecurity, def->sec->sectype); + return -1; } } diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c index 4a06e5ceb7..aa8b3c579b 100644 --- a/src/qemu/qemu_namespace.c +++ b/src/qemu/qemu_namespace.c @@ -594,16 +594,26 @@ static int qemuDomainSetupLaunchSecurity(virDomainObj *vm, GSList **paths) { - virDomainSEVDef *sev = vm->def->sev; + virDomainSecDef *sec = vm->def->sec; - if (!sev || sev->sectype != VIR_DOMAIN_LAUNCH_SECURITY_SEV) + if (!sec) return 0; - VIR_DEBUG("Setting up launch security"); + switch ((virDomainLaunchSecurity) sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + VIR_DEBUG("Setting up launch security for SEV"); - *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SEV)); + *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_SEV)); + + VIR_DEBUG("Set up launch security for SEV"); + break; + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + break; + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype); + return -1; + } - VIR_DEBUG("Set up launch security"); return 0; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index c972c90801..07e695f311 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6481,7 +6481,7 @@ qemuProcessUpdateSEVInfo(virDomainObj *vm) { qemuDomainObjPrivate *priv = vm->privateData; virQEMUCaps *qemuCaps = priv->qemuCaps; - virDomainSEVDef *sev = vm->def->sev; + virDomainSEVDef *sev = &vm->def->sec->data.sev; virSEVCapability *sevCaps = NULL; /* if platform specific info like 'cbitpos' and 'reducedPhysBits' have @@ -6637,7 +6637,8 @@ qemuProcessPrepareDomain(virQEMUDriver *driver, for (i = 0; i < vm->def->nshmems; i++) qemuDomainPrepareShmemChardev(vm->def->shmems[i]); - if (vm->def->sev) { + if (vm->def->sec && + vm->def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) { VIR_DEBUG("Updating SEV platform info"); if (qemuProcessUpdateSEVInfo(vm) < 0) return -1; @@ -6675,10 +6676,7 @@ qemuProcessSEVCreateFile(virDomainObj *vm, static int qemuProcessPrepareSEVGuestInput(virDomainObj *vm) { - virDomainSEVDef *sev = vm->def->sev; - - if (!sev) - return 0; + virDomainSEVDef *sev = &vm->def->sec->data.sev; VIR_DEBUG("Preparing SEV guest"); @@ -6696,6 +6694,28 @@ qemuProcessPrepareSEVGuestInput(virDomainObj *vm) } +static int +qemuProcessPrepareLaunchSecurityGuestInput(virDomainObj *vm) +{ + virDomainSecDef *sec = vm->def->sec; + + if (!sec) + return 0; + + switch ((virDomainLaunchSecurity) sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + return qemuProcessPrepareSEVGuestInput(vm); + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + break; + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + virReportEnumRangeError(virDomainLaunchSecurity, sec->sectype); + return -1; + } + + return 0; +} + + static int qemuProcessPrepareHostStorage(virQEMUDriver *driver, virDomainObj *vm, @@ -6875,7 +6895,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver, if (qemuExtDevicesPrepareHost(driver, vm) < 0) return -1; - if (qemuProcessPrepareSEVGuestInput(vm) < 0) + if (qemuProcessPrepareLaunchSecurityGuestInput(vm) < 0) return -1; return 0; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index b133ce3cd6..c54c18160e 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -1214,12 +1214,22 @@ qemuValidateDomainDef(const virDomainDef *def, if (qemuValidateDomainDefPanic(def, qemuCaps) < 0) return -1; - if (def->sev && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("SEV launch security is not supported with " - "this QEMU binary")); - return -1; + if (def->sec) { + switch ((virDomainLaunchSecurity) def->sec->sectype) { + case VIR_DOMAIN_LAUNCH_SECURITY_SEV: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("SEV launch security is not supported with " + "this QEMU binary")); + return -1; + } + break; + case VIR_DOMAIN_LAUNCH_SECURITY_NONE: + break; + case VIR_DOMAIN_LAUNCH_SECURITY_LAST: + virReportEnumRangeError(virDomainLaunchSecurity, def->sec->sectype); + return -1; + } } if (def->naudios > 1 && diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 4909107fcc..b874dd4ab6 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1958,7 +1958,8 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr, rc = -1; } - if (def->sev) { + if (def->sec && + def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) { if (virSecurityDACRestoreSEVLabel(mgr, def) < 0) rc = -1; } @@ -2165,7 +2166,8 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr, return -1; } - if (def->sev) { + if (def->sec && + def->sec->sectype == VIR_DOMAIN_LAUNCH_SECURITY_SEV) { if (virSecurityDACSetSEVLabel(mgr, def) < 0) return -1; } -- 2.31.1