From: Marc-André Lureau <marcandre.lureau@redhat.com>
Learn to parse a file path for the TPM state.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
docs/formatdomain.rst | 15 +++++++++++++++
src/conf/domain_conf.c | 21 +++++++++++++++++++++
src/conf/domain_conf.h | 6 ++++++
src/conf/schemas/domaincommon.rng | 11 +++++++++++
tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 1 +
5 files changed, 54 insertions(+)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 47d3e2125e..4818113bc2 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8170,6 +8170,21 @@ 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.
+
+ The following attributes are supported:
+
+ ``path``
+ The path to the TPM state storage file.
+
+ This attribute requires that swtpm v0.7 or later is installed.
+
+ :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 a263612ef7..18c58d16dc 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10789,6 +10789,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;
@@ -10862,6 +10863,18 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
def->data.emulator.hassecretuuid = true;
}
+ source_node = virXPathNode("./backend/source", ctxt);
+ if (source_node) {
+ path = virXMLPropString(source_node, "file");
+ if (!path) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing TPM file source"));
+ goto error;
+ }
+ def->data.emulator.storage_type = VIR_DOMAIN_TPM_STORAGE_FILE;
+ def->data.emulator.storagepath = g_steal_pointer(&path);
+ }
+
persistent_state = virXMLPropString(backends[0], "persistent_state");
if (persistent_state) {
if (virStringParseYesNo(persistent_state,
@@ -25066,6 +25079,14 @@ virDomainTPMDefFormat(virBuffer *buf,
virXMLFormatElement(&backendChildBuf, "active_pcr_banks", NULL, &activePcrBanksBuf);
}
+ switch (def->data.emulator.storage_type) {
+ case VIR_DOMAIN_TPM_STORAGE_FILE:
+ virBufferAsprintf(&backendChildBuf, "<source file='%s'/>\n",
+ def->data.emulator.storagepath);
+ break;
+ case VIR_DOMAIN_TPM_STORAGE_DEFAULT:
+ break;
+ }
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 659299bdd1..371e6ecf6c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1463,6 +1463,11 @@ typedef enum {
VIR_DOMAIN_TPM_PCR_BANK_LAST
} virDomainPcrBank;
+typedef enum {
+ VIR_DOMAIN_TPM_STORAGE_DEFAULT,
+ VIR_DOMAIN_TPM_STORAGE_FILE,
+} virDomainTPMStorage;
+
#define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
struct _virDomainTPMDef {
@@ -1478,6 +1483,7 @@ struct _virDomainTPMDef {
struct {
virDomainTPMVersion version;
virDomainChrSourceDef *source;
+ virDomainTPMStorage storage_type;
char *storagepath;
char *logfile;
unsigned int debug;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index efb5f00d77..62d3f0e6fe 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,16 @@
</optional>
</define>
+ <define name="tpm-backend-emulator-source">
+ <optional>
+ <element name="source">
+ <attribute name="file">
+ <ref name="filePath"/>
+ </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..4c61e2645b 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 file='/path/to/state'/>
</backend>
</tpm>
<audio id='1' type='none'/>
--
2.45.2.827.g557ae147e6
On Tue, Sep 10, 2024 at 11:05:58AM +0400, marcandre.lureau@redhat.com wrote: >From: Marc-André Lureau <marcandre.lureau@redhat.com> > >Learn to parse a file path for the TPM state. > >Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> >--- > docs/formatdomain.rst | 15 +++++++++++++++ > src/conf/domain_conf.c | 21 +++++++++++++++++++++ > src/conf/domain_conf.h | 6 ++++++ > src/conf/schemas/domaincommon.rng | 11 +++++++++++ > tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 1 + > 5 files changed, 54 insertions(+) > >diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst >index 47d3e2125e..4818113bc2 100644 >--- a/docs/formatdomain.rst >+++ b/docs/formatdomain.rst >@@ -8170,6 +8170,21 @@ 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. >+ >+ The following attributes are supported: >+ >+ ``path`` You name it "path" here, but everywhere below it is a "file".
On Wed, Oct 2, 2024 at 11:18 AM Martin Kletzander <mkletzan@redhat.com> wrote: > > On Tue, Sep 10, 2024 at 11:05:58AM +0400, marcandre.lureau@redhat.com wrote: > >From: Marc-André Lureau <marcandre.lureau@redhat.com> > > > >Learn to parse a file path for the TPM state. > > > >Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> > >--- > > docs/formatdomain.rst | 15 +++++++++++++++ > > src/conf/domain_conf.c | 21 +++++++++++++++++++++ > > src/conf/domain_conf.h | 6 ++++++ > > src/conf/schemas/domaincommon.rng | 11 +++++++++++ > > tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 1 + > > 5 files changed, 54 insertions(+) > > > >diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst > >index 47d3e2125e..4818113bc2 100644 > >--- a/docs/formatdomain.rst > >+++ b/docs/formatdomain.rst > >@@ -8170,6 +8170,21 @@ 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. > >+ > >+ The following attributes are supported: > >+ > >+ ``path`` > > You name it "path" here, but everywhere below it is a "file". good catch, fixed
On 9/10/24 3:05 AM, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Learn to parse a file path for the TPM state.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> ---
> docs/formatdomain.rst | 15 +++++++++++++++
> src/conf/domain_conf.c | 21 +++++++++++++++++++++
> src/conf/domain_conf.h | 6 ++++++
> src/conf/schemas/domaincommon.rng | 11 +++++++++++
> tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 1 +
> 5 files changed, 54 insertions(+)
>
> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
> index 47d3e2125e..4818113bc2 100644
> --- a/docs/formatdomain.rst
> +++ b/docs/formatdomain.rst
> @@ -8170,6 +8170,21 @@ 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.
> +
> + The following attributes are supported:
> +
> + ``path``
> + The path to the TPM state storage file.
> +
> + This attribute requires that swtpm v0.7 or later is installed.
> +
> + :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 a263612ef7..18c58d16dc 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -10789,6 +10789,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;
> @@ -10862,6 +10863,18 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
> def->data.emulator.hassecretuuid = true;
> }
>
> + source_node = virXPathNode("./backend/source", ctxt);
> + if (source_node) {
> + path = virXMLPropString(source_node, "file");
> + if (!path) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("missing TPM file source"));
> + goto error;
> + }
> + def->data.emulator.storage_type = VIR_DOMAIN_TPM_STORAGE_FILE;
> + def->data.emulator.storagepath = g_steal_pointer(&path);
> + }
> +
> persistent_state = virXMLPropString(backends[0], "persistent_state");
> if (persistent_state) {
> if (virStringParseYesNo(persistent_state,
> @@ -25066,6 +25079,14 @@ virDomainTPMDefFormat(virBuffer *buf,
>
> virXMLFormatElement(&backendChildBuf, "active_pcr_banks", NULL, &activePcrBanksBuf);
> }
> + switch (def->data.emulator.storage_type) {
> + case VIR_DOMAIN_TPM_STORAGE_FILE:
> + virBufferAsprintf(&backendChildBuf, "<source file='%s'/>\n",
> + def->data.emulator.storagepath);
> + break;
> + case VIR_DOMAIN_TPM_STORAGE_DEFAULT:
> + break;
> + }
> 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 659299bdd1..371e6ecf6c 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1463,6 +1463,11 @@ typedef enum {
> VIR_DOMAIN_TPM_PCR_BANK_LAST
> } virDomainPcrBank;
>
> +typedef enum {
> + VIR_DOMAIN_TPM_STORAGE_DEFAULT,
> + VIR_DOMAIN_TPM_STORAGE_FILE,
> +} virDomainTPMStorage;
> +
> #define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0"
>
> struct _virDomainTPMDef {
> @@ -1478,6 +1483,7 @@ struct _virDomainTPMDef {
> struct {
> virDomainTPMVersion version;
> virDomainChrSourceDef *source;
> + virDomainTPMStorage storage_type;
> char *storagepath;
> char *logfile;
> unsigned int debug;
> diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
> index efb5f00d77..62d3f0e6fe 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,16 @@
> </optional>
> </define>
>
> + <define name="tpm-backend-emulator-source">
> + <optional>
> + <element name="source">
> + <attribute name="file">
> + <ref name="filePath"/>
> + </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..4c61e2645b 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 file='/path/to/state'/>
> </backend>
> </tpm>
> <audio id='1' type='none'/>
© 2016 - 2026 Red Hat, Inc.