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 <[email protected]>
---
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