[PATCH 0/3] Add TPM emulator <source file=''/>

From: Marc-André Lureau <marcandre.lureau@redhat.com> Hi, When swtpm capabilities reports "nvram-backend-dir", it can accepts a single file or block device where TPM state will be stored. --tpmstate must be backend-uri=file://. Let me know what you think of this approach of exposing this. Related: https://issues.redhat.com/browse/CNV-35250 Marc-André Lureau (3): util: check swtpm nvram-backend-dir capability schema: add TPM emulator <source file='..'> qemu_tpm: handle file/block storage docs/formatdomain.rst | 15 +++++ src/conf/domain_conf.c | 21 ++++++ src/conf/domain_conf.h | 6 ++ src/conf/schemas/domaincommon.rng | 11 +++ src/qemu/qemu_tpm.c | 74 +++++++++++++++++---- src/util/virtpm.c | 1 + src/util/virtpm.h | 1 + tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 1 + 8 files changed, 117 insertions(+), 13 deletions(-) -- 2.45.2.827.g557ae147e6

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/util/virtpm.c | 1 + src/util/virtpm.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/util/virtpm.c b/src/util/virtpm.c index 81fd6166cf..84ed2f0edd 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -40,6 +40,7 @@ VIR_ENUM_IMPL(virTPMSwtpmFeature, VIR_TPM_SWTPM_FEATURE_LAST, "cmdarg-pwd-fd", "cmdarg-migration", + "nvram-backend-dir", ); VIR_ENUM_IMPL(virTPMSwtpmSetupFeature, diff --git a/src/util/virtpm.h b/src/util/virtpm.h index fb330effa8..088bb2f667 100644 --- a/src/util/virtpm.h +++ b/src/util/virtpm.h @@ -31,6 +31,7 @@ bool virTPMHasSwtpm(void); typedef enum { VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD, VIR_TPM_SWTPM_FEATURE_CMDARG_MIGRATION, + VIR_TPM_SWTPM_FEATURE_NVRAM_BACKEND_DIR, VIR_TPM_SWTPM_FEATURE_LAST } virTPMSwtpmFeature; -- 2.45.2.827.g557ae147e6

On Wed, Aug 28, 2024 at 11:02:27AM +0400, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/util/virtpm.c | 1 + src/util/virtpm.h | 1 + 2 files changed, 2 insertions(+)
diff --git a/src/util/virtpm.c b/src/util/virtpm.c index 81fd6166cf..84ed2f0edd 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -40,6 +40,7 @@ VIR_ENUM_IMPL(virTPMSwtpmFeature, VIR_TPM_SWTPM_FEATURE_LAST, "cmdarg-pwd-fd", "cmdarg-migration", + "nvram-backend-dir", );
This looks a bit wierd. You're probing for 'nvram-backend-dir' but IIUC patch three is actually creating an swtpm args related to 'nvramd-backend-file'. I presume this works because both nvram-backend-file & nvram-backend-dir were introduced at the same time, but I think it'd still make more sense to probe the new one we're using
VIR_ENUM_IMPL(virTPMSwtpmSetupFeature, diff --git a/src/util/virtpm.h b/src/util/virtpm.h index fb330effa8..088bb2f667 100644 --- a/src/util/virtpm.h +++ b/src/util/virtpm.h @@ -31,6 +31,7 @@ bool virTPMHasSwtpm(void); typedef enum { VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD, VIR_TPM_SWTPM_FEATURE_CMDARG_MIGRATION, + VIR_TPM_SWTPM_FEATURE_NVRAM_BACKEND_DIR,
VIR_TPM_SWTPM_FEATURE_LAST } virTPMSwtpmFeature; -- 2.45.2.827.g557ae147e6
With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

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 5f0b35be5e..d62a0423d8 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, @@ -25065,6 +25078,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 Wed, Aug 28, 2024 at 11:02:28AM +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`` + 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 5f0b35be5e..d62a0423d8 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, @@ -25065,6 +25078,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'/>
So you're modifying an existing XML file, which is fine, but this modification looks conceptually incomplete to me. When we have two different backend options - in this case 'dir' and 'file', then we would normally have an "type" attribute on the parent element, that dictates what child elements are permitted. Picking a chunk from earlier in the patch:
+typedef enum { + VIR_DOMAIN_TPM_STORAGE_DEFAULT, + VIR_DOMAIN_TPM_STORAGE_FILE, +} virDomainTPMStorage;
I would have expected to see typedef enum { VIR_DOMAIN_TPM_STORAGE_DIR, VIR_DOMAIN_TPM_STORAGE_FILE, } virDomainTPMStorage; and have this enum be exposed as the 'type' attribute on <backend>. Also, if we're going to expose the raw file path as a user configurable optin for "file" type, then IMHO, we should also expose the dir path for our existing backend. It doesn't make sense to allow one to be configured, but not both. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On 8/28/24 11:26 AM, Daniel P. Berrangé wrote:
On Wed, Aug 28, 2024 at 11:02:28AM +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>
When we have two different backend options - in this case 'dir' and 'file', then we would normally have an "type" attribute on the parent element, that dictates what child elements are permitted.
Picking a chunk from earlier in the patch:
+typedef enum { + VIR_DOMAIN_TPM_STORAGE_DEFAULT, + VIR_DOMAIN_TPM_STORAGE_FILE, +} virDomainTPMStorage;
I would have expected to see
typedef enum { VIR_DOMAIN_TPM_STORAGE_DIR, VIR_DOMAIN_TPM_STORAGE_FILE, } virDomainTPMStorage;
and have this enum be exposed as the 'type' attribute on <backend>.
Also, if we're going to expose the raw file path as a user configurable optin for "file" type, then IMHO, we should also expose the dir path for our existing backend. It doesn't make sense to allow one to be configured, but not both.
I am not sure whether it is good to give users control over directories or file paths. Do we want to allow them to get access to the state of a a TPM of another VM?
With regards, Daniel

On Thu, Aug 29, 2024 at 12:04:27PM -0400, Stefan Berger wrote:
On 8/28/24 11:26 AM, Daniel P. Berrangé wrote:
On Wed, Aug 28, 2024 at 11:02:28AM +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>
When we have two different backend options - in this case 'dir' and 'file', then we would normally have an "type" attribute on the parent element, that dictates what child elements are permitted.
Picking a chunk from earlier in the patch:
+typedef enum { + VIR_DOMAIN_TPM_STORAGE_DEFAULT, + VIR_DOMAIN_TPM_STORAGE_FILE, +} virDomainTPMStorage;
I would have expected to see
typedef enum { VIR_DOMAIN_TPM_STORAGE_DIR, VIR_DOMAIN_TPM_STORAGE_FILE, } virDomainTPMStorage;
and have this enum be exposed as the 'type' attribute on <backend>.
Also, if we're going to expose the raw file path as a user configurable optin for "file" type, then IMHO, we should also expose the dir path for our existing backend. It doesn't make sense to allow one to be configured, but not both.
I am not sure whether it is good to give users control over directories or file paths. Do we want to allow them to get access to the state of a a TPM of another VM?
Libvirt is not responsible for enforcing such policies. A connection to libvirt which has been granted permission to the change the XML, has privileges equivalent to an unrestricted root shell. The mgmt application talking to libvirt is responsible for not making bad VM configuration decisions, such as giving the VM access to the host / filesystem or /dev/ inode for host disks. Controlling access to the TPM paths is inconsequential compared to this and thus providing the ability to configure TPM state paths has no security implications IMHO. If there is a need for a virtual TPM that is immune to host administrative mistakes, then IMHO only confidential computing can offer meaningful protection. ie a paravisor can securely isolate a vTPM from both the host OS and guest OS/firmware using the VMPL concept in SEV-SNP on AMD CPUs, or TDX partitioning on Intel CPUs. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Marc-André Lureau <marcandre.lureau@redhat.com> When swtpm reports "nvram-backend-dir", it can accepts a single file or block device where TPM state will be stored. --tpmstate must be backend-uri=file://<path>. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_tpm.c | 74 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c index 2f17918cbb..b69706ccc0 100644 --- a/src/qemu/qemu_tpm.c +++ b/src/qemu/qemu_tpm.c @@ -340,9 +340,27 @@ qemuTPMVirCommandAddEncryption(virCommand *cmd, } +static char * +qemuTPMGetSwtpmSetupStateArg(const virDomainTPMStorage storage_type, + const char *storagepath) +{ + switch (storage_type) { + case VIR_DOMAIN_TPM_STORAGE_FILE: + /* the file:// prefix is supported since swtpm_setup 0.7.0 */ + /* assume the capability check for swtpm is redundant. */ + return g_strdup_printf("file://%s", storagepath); + case VIR_DOMAIN_TPM_STORAGE_DEFAULT: + return g_strdup_printf("%s", storagepath); + } + + return NULL; +} + + /* * qemuTPMEmulatorRunSetup * + * @storage_type: type of storage * @storagepath: path to the directory for TPM state * @vmname: the name of the VM * @vmuuid: the UUID of the VM @@ -360,7 +378,8 @@ qemuTPMVirCommandAddEncryption(virCommand *cmd, * certificates for it. */ static int -qemuTPMEmulatorRunSetup(const char *storagepath, +qemuTPMEmulatorRunSetup(const virDomainTPMStorage storage_type, + const char *storagepath, const char *vmname, const unsigned char *vmuuid, bool privileged, @@ -376,6 +395,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath, char uuid[VIR_UUID_STRING_BUFLEN]; g_autofree char *vmid = NULL; g_autofree char *swtpm_setup = virTPMGetSwtpmSetup(); + g_autofree char *tpm_state = qemuTPMGetSwtpmSetupStateArg(storage_type, storagepath); if (!swtpm_setup) return -1; @@ -413,7 +433,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath, if (!incomingMigration) { virCommandAddArgList(cmd, - "--tpm-state", storagepath, + "--tpm-state", tpm_state, "--vmid", vmid, "--logfile", logfile, "--createek", @@ -424,7 +444,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath, NULL); } else { virCommandAddArgList(cmd, - "--tpm-state", storagepath, + "--tpm-state", tpm_state, "--logfile", logfile, "--overwrite", NULL); @@ -465,6 +485,7 @@ qemuTPMPcrBankBitmapToStr(virBitmap *activePcrBanks) * qemuTPMEmulatorReconfigure * * + * @storage_type: type of storage * @storagepath: path to the directory for TPM state * @swtpm_user: The userid to switch to when setting up the TPM; * typically this should be the uid of 'tss' or 'root' @@ -478,7 +499,8 @@ qemuTPMPcrBankBitmapToStr(virBitmap *activePcrBanks) * Reconfigure the active PCR banks of a TPM 2. */ static int -qemuTPMEmulatorReconfigure(const char *storagepath, +qemuTPMEmulatorReconfigure(const virDomainTPMStorage storage_type, + const char *storagepath, uid_t swtpm_user, gid_t swtpm_group, virBitmap *activePcrBanks, @@ -490,6 +512,7 @@ qemuTPMEmulatorReconfigure(const char *storagepath, int exitstatus; g_autofree char *activePcrBanksStr = NULL; g_autofree char *swtpm_setup = virTPMGetSwtpmSetup(); + g_autofree char *tpm_state = qemuTPMGetSwtpmSetupStateArg(storage_type, storagepath); if (!swtpm_setup) return -1; @@ -510,7 +533,7 @@ qemuTPMEmulatorReconfigure(const char *storagepath, return -1; virCommandAddArgList(cmd, - "--tpm-state", storagepath, + "--tpm-state", tpm_state, "--logfile", logfile, "--pcr-banks", activePcrBanksStr, "--reconfigure", @@ -555,6 +578,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, { g_autoptr(virCommand) cmd = NULL; bool created = false; + bool run_setup = false; g_autofree char *swtpm = virTPMGetSwtpm(); int pwdfile_fd = -1; int migpwdfile_fd = -1; @@ -565,6 +589,18 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, if (!swtpm) return NULL; + if (tpm->data.emulator.storage_type == VIR_DOMAIN_TPM_STORAGE_FILE) { + if (!virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_NVRAM_BACKEND_DIR)) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, + _("%1$s does not support file storage"), + swtpm); + goto error; + } + create_storage = false; + /* setup is run with --not-overwrite */ + run_setup = true; + } + /* Do not create storage and run swtpm_setup on incoming migration over * shared storage */ @@ -572,15 +608,18 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, if (incomingMigration && on_shared_storage) create_storage = false; - if (create_storage && - qemuTPMEmulatorCreateStorage(tpm, &created, swtpm_user, swtpm_group) < 0) - return NULL; + if (create_storage) { + if (qemuTPMEmulatorCreateStorage(tpm, &created, swtpm_user, swtpm_group) < 0) + return NULL; + run_setup = created; + } if (tpm->data.emulator.hassecretuuid) secretuuid = tpm->data.emulator.secretuuid; - if (created && - qemuTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmuuid, + if (run_setup && + qemuTPMEmulatorRunSetup(tpm->data.emulator.storage_type, + tpm->data.emulator.storagepath, vmname, vmuuid, privileged, swtpm_user, swtpm_group, tpm->data.emulator.logfile, tpm->data.emulator.version, @@ -588,7 +627,8 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, goto error; if (!incomingMigration && - qemuTPMEmulatorReconfigure(tpm->data.emulator.storagepath, + qemuTPMEmulatorReconfigure(tpm->data.emulator.storage_type, + tpm->data.emulator.storagepath, swtpm_user, swtpm_group, tpm->data.emulator.activePcrBanks, tpm->data.emulator.logfile, @@ -607,8 +647,16 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, tpm->data.emulator.source->data.nix.path); virCommandAddArg(cmd, "--tpmstate"); - virCommandAddArgFormat(cmd, "dir=%s,mode=0600", - tpm->data.emulator.storagepath); + switch (tpm->data.emulator.storage_type) { + case VIR_DOMAIN_TPM_STORAGE_FILE: + virCommandAddArgFormat(cmd, "backend-uri=file://%s", + tpm->data.emulator.storagepath); + break; + case VIR_DOMAIN_TPM_STORAGE_DEFAULT: + virCommandAddArgFormat(cmd, "dir=%s,mode=0600", + tpm->data.emulator.storagepath); + break; + } virCommandAddArg(cmd, "--log"); if (tpm->data.emulator.debug != 0) -- 2.45.2.827.g557ae147e6
participants (3)
-
Daniel P. Berrangé
-
marcandre.lureau@redhat.com
-
Stefan Berger