Learn to parse a file path for the TPM state.
Signed-off-by: Marc-André Lureau <marcandre.lureau(a)redhat.com>
---
docs/formatdomain.rst | 19 ++++++++++++++
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, 71 insertions(+)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index e6f09a728f..d4feb4421c 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8174,6 +8174,25 @@ 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.
+
+ If not specified, the storage configuration is left to libvirt
discretion.
IMO it would be good to mention that it is up to the user to prevent
files being used by multiple VMs, especially if locking cannot be used.
+
+ 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.8.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..72c8b6c694 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="filePath"/>
Should probably be absFilePath?
With this nit:
Reviewed-by: Stefan Berger <stefanb(a)linux.ibm.com>
> + </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