From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Learn to parse a file path for the TPM state.
Signed-off-by: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Reviewed-by: Stefan Berger <stefanb(a)linux.ibm.com>
---
docs/formatdomain.rst | 21 ++++++++++++++++
src/conf/domain_conf.c | 28 +++++++++++++++++++++
src/conf/domain_conf.h | 9 +++++++
src/conf/schemas/domaincommon.rng | 14 +++++++++++
tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 1 +
5 files changed, 73 insertions(+)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 3253a28e5a..9104c95a4a 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8181,6 +8181,27 @@ Example: usage of the TPM Emulator
The default version used depends on the combination of hypervisor, guest
architecture, TPM model and backend.
+``source``
+ The ``source`` element specifies the location of the TPM state storage . This
+ element only works with the ``emulator`` backend.
+
+ When specified, it is the user's responsability to prevent files from being
+ used by multiple VMs or emulators (swtpm will also use advisory locking). If
+ not specified, the storage configuration is left to libvirt discretion.
+
+ This element requires that swtpm v0.7 or later is installed.
+
+ The following attributes are supported:
+
+ ``type``
+ The type of storage. It's possible to provide "file" to utilize a
single
+ file or block device where the TPM state will be stored.
+
+ ``path``
+ The path to the TPM state storage.
+
+ :since:`Since v10.9.0`
+
``persistent_state``
The ``persistent_state`` attribute indicates whether 'swtpm' TPM state is
kept or not when a transient domain is powered off or undefined. This
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 284a3815b3..9dd8b6b55d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1322,6 +1322,12 @@ VIR_ENUM_IMPL(virDomainTPMVersion,
"2.0",
);
+VIR_ENUM_IMPL(virDomainTPMSourceType,
+ VIR_DOMAIN_TPM_SOURCE_TYPE_LAST,
+ "default",
+ "file",
+);
+
VIR_ENUM_IMPL(virDomainTPMPcrBank,
VIR_DOMAIN_TPM_PCR_BANK_LAST,
"sha1",
@@ -10784,6 +10790,7 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
int nbackends;
int nnodes;
size_t i;
+ xmlNodePtr source_node = NULL;
g_autofree char *path = NULL;
g_autofree char *secretuuid = NULL;
g_autofree char *persistent_state = NULL;
@@ -10857,6 +10864,22 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
def->data.emulator.hassecretuuid = true;
}
+ source_node = virXPathNode("./backend/source", ctxt);
+ if (source_node) {
+ if (virXMLPropEnum(source_node, "type",
+ virDomainTPMSourceTypeTypeFromString,
+ VIR_XML_PROP_NONZERO,
+ &def->data.emulator.source_type) < 0)
+ goto error;
+ path = virXMLPropString(source_node, "path");
+ if (!path) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing TPM source path"));
+ goto error;
+ }
+ def->data.emulator.source_path = g_steal_pointer(&path);
+ }
+
persistent_state = virXMLPropString(backends[0], "persistent_state");
if (persistent_state) {
if (virStringParseYesNo(persistent_state,
@@ -25070,6 +25093,11 @@ virDomainTPMDefFormat(virBuffer *buf,
virXMLFormatElement(&backendChildBuf, "active_pcr_banks", NULL,
&activePcrBanksBuf);
}
+ if (def->data.emulator.source_type != VIR_DOMAIN_TPM_SOURCE_TYPE_DEFAULT) {
+ virBufferAsprintf(&backendChildBuf, "<source
type='%s'",
+
virDomainTPMSourceTypeTypeToString(def->data.emulator.source_type));
+ virBufferEscapeString(&backendChildBuf, "
path='%s'/>\n", def->data.emulator.source_path);
+ }
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
if (def->data.external.source->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 6b27322e3e..7a70f68177 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1463,6 +1463,13 @@ typedef enum {
VIR_DOMAIN_TPM_PCR_BANK_LAST
} virDomainPcrBank;
+typedef enum {
+ VIR_DOMAIN_TPM_SOURCE_TYPE_DEFAULT = 0,
+ VIR_DOMAIN_TPM_SOURCE_TYPE_FILE,
+
+ VIR_DOMAIN_TPM_SOURCE_TYPE_LAST
+} virDomainTPMSourceType;
+
#define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
struct _virDomainTPMDef {
@@ -1478,6 +1485,7 @@ struct _virDomainTPMDef {
struct {
virDomainTPMVersion version;
virDomainChrSourceDef *source;
+ virDomainTPMSourceType source_type;
char *source_path;
char *logfile;
unsigned int debug;
@@ -4277,6 +4285,7 @@ VIR_ENUM_DECL(virDomainRNGBackend);
VIR_ENUM_DECL(virDomainTPMModel);
VIR_ENUM_DECL(virDomainTPMBackend);
VIR_ENUM_DECL(virDomainTPMVersion);
+VIR_ENUM_DECL(virDomainTPMSourceType);
VIR_ENUM_DECL(virDomainTPMPcrBank);
VIR_ENUM_DECL(virDomainMemoryModel);
VIR_ENUM_DECL(virDomainMemoryBackingModel);
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index efb5f00d77..8d91fb0dd6 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -5923,6 +5923,7 @@
<interleave>
<ref name="tpm-backend-emulator-encryption"/>
<ref name="tpm-backend-emulator-active-pcr-banks"/>
+ <ref name="tpm-backend-emulator-source"/>
</interleave>
<optional>
<attribute name="persistent_state">
@@ -5981,6 +5982,19 @@
</optional>
</define>
+ <define name="tpm-backend-emulator-source">
+ <optional>
+ <element name="source">
+ <attribute name="type">
+ <value>file</value>
+ </attribute>
+ <attribute name="path">
+ <ref name="absFilePath"/>
+ </attribute>
+ </element>
+ </optional>
+ </define>
+
<define name="tpm-backend-emulator-encryption">
<optional>
<element name="encryption">
diff --git a/tests/qemuxmlconfdata/tpm-emulator-tpm2.xml
b/tests/qemuxmlconfdata/tpm-emulator-tpm2.xml
index 8a613db456..3d6300f544 100644
--- a/tests/qemuxmlconfdata/tpm-emulator-tpm2.xml
+++ b/tests/qemuxmlconfdata/tpm-emulator-tpm2.xml
@@ -34,6 +34,7 @@
<sha256/>
<sha512/>
</active_pcr_banks>
+ <source type='file' path='/path/to/state'/>
</backend>
</tpm>
<audio id='1' type='none'/>
--
2.47.0