Introduce a new <boot-certs> element inside <os> for s390x domains, holding one or more <path> children pointing to X.509 certificates used by the firmware during Secure IPL. Example: <os> <type arch='s390x' machine='s390-ccw-virtio-11.1'>hvm</type> <boot-certs> <path>/path/to/cert.pem</path> <path>/path/to/cert2.pem</path> </boot-certs> </os> Only the xml/conf layer is added here (parsing, formatting, and schema validation). The QEMU command-line translation of these paths onto: -machine s390-ccw-virtio,...,boot-certs.<n>.path=<path> is handled by QEMU itself and is not part of this patch. The <boot-certs> element is intentionally omitted from migratable XML. Certificate paths are host-local and will not exist on the destination host. The guest XML on the destination needs to be configured with <boot-certs> referencing certificate paths that are valid on the destination host. Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com> --- src/conf/domain_conf.c | 69 +++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 2 + src/conf/schemas/domaincommon.rng | 9 ++++ 3 files changed, 80 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 94a1f8bd8e..1dfb7b251a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4112,6 +4112,9 @@ virDomainOSDefClear(virDomainOSDef *os) for (i = 0; i < os->nacpiTables; i++) virDomainOSACPITableDefFree(os->acpiTables[i]); g_free(os->acpiTables); + for (i = 0; i < os->nbootCerts; i++) + g_free(os->bootCertPaths[i]); + g_free(os->bootCertPaths); virDomainLoaderDefFree(os->loader); virDomainVarstoreDefFree(os->varstore); g_free(os->bootloader); @@ -18753,6 +18756,58 @@ virDomainDefParseBootAcpiOptions(virDomainDef *def, } +static int +virDomainDefParseBootCertPaths(virDomainDef *def, + xmlXPathContextPtr ctxt) +{ + int n; + g_autofree xmlNodePtr *nodes = NULL; + size_t ncerts = 0; + char **certs = NULL; + size_t i; + + if (!virXPathNode("./os/boot-certs", ctxt)) + return 0; + + if ((n = virXPathNodeSet("./os/boot-certs/path", ctxt, &nodes)) < 0) + return -1; + + if (n == 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing <path> element in <boot-certs>")); + return -1; + } + + certs = g_new0(char *, n); + for (i = 0; i < n; i++) { + g_autofree char *path = virXMLNodeContentString(nodes[i]); + + if (!path) + goto error; + + if (virStringIsEmpty(path)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Paths for boot certificates must be provided")); + goto error; + } + + certs[ncerts] = virFileSanitizePath(path); + ncerts++; + } + + def->os.nbootCerts = ncerts; + def->os.bootCertPaths = certs; + + return 0; + + error: + for (i = 0; i < ncerts; i++) + g_free(certs[i]); + g_free(certs); + return -1; +} + + static int virDomainDefParseBootOptions(virDomainDef *def, xmlXPathContextPtr ctxt, @@ -18781,6 +18836,9 @@ virDomainDefParseBootOptions(virDomainDef *def, if (virDomainDefParseBootAcpiOptions(def, ctxt) < 0) return -1; + if (virDomainDefParseBootCertPaths(def, ctxt) < 0) + return -1; + if (virDomainDefParseBootXML(ctxt, def) < 0) return -1; @@ -30222,6 +30280,17 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, virBufferAddLit(buf, "</acpi>\n"); } + if (def->os.nbootCerts && !migratable) { + virBufferAddLit(buf, "<boot-certs>\n"); + virBufferAdjustIndent(buf, 2); + for (i = 0; i < def->os.nbootCerts; i++) { + virBufferEscapeString(buf, "<path>%s</path>\n", + def->os.bootCertPaths[i]); + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</boot-certs>\n"); + } + if (!def->os.bootloader) { for (n = 0; n < def->os.nBootDevs; n++) { const char *boottype = diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index eadb5a49a4..c8bc5d6604 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2604,6 +2604,8 @@ struct _virDomainOSDef { char *root; size_t nacpiTables; virDomainOSACPITableDef **acpiTables; + size_t nbootCerts; + char **bootCertPaths; virDomainLoaderDef *loader; virDomainVarstoreDef *varstore; char *bootloader; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index d1b10c1c5f..db2365f592 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -315,6 +315,15 @@ </oneOrMore> </element> </optional> + <optional> + <element name="boot-certs"> + <oneOrMore> + <element name="path"> + <ref name="absFilePath"/> + </element> + </oneOrMore> + </element> + </optional> <optional> <element name="loader"> <optional> -- 2.56.0