<active_pcr_banks>
<sha256/>
</active_pcr_banks>
- <profile source='local:restricted' removeDisabled='check'/>
+ <profile source='local:restricted' removeDisabled='check' name='custom:restricted'/>
</backend>
</tpm>
</devices>
``profile``
The ``profile`` node is used to set a profile for a TPM 2.0 given in the
source attribute. This profile will be set when the TPM is initially
- created and after that cannot be changed anymore. If no profile is provided,
- then swtpm will use the latest built-in 'default' profile or the default
- profile set in swtpm_setup.conf. Otherwise swtpm_setup will search for a
- profile with the given name with appended .json suffix in a configurable
- local and then in a distro directory. If none could be found in either, it
- will fall back trying to use a built-in one.
+ created and after that cannot be changed anymore. Once a profile has been
+ set the name attribute will be updated with the name of the profile that
+ is running. If no profile is provided, then swtpm will use the latest
+ built-in 'default' profile or the default profile set in swtpm_setup.conf.
+ Otherwise swtpm_setup will search for a profile with the given name with
+ appended .json suffix in a configurable local and then in a distro
+ directory. If none could be found in either, it will fall back trying to
+ use a built-in one.
The built-in 'null' profile provides backwards compatibility with
libtpms v0.9 but also restricts the user to use only TPM features that were
g_free(def->data.emulator.logfile);
virBitmapFree(def->data.emulator.activePcrBanks);
g_free(def->data.emulator.profile.source);
+ g_free(def->data.emulator.profile.name);
break;
case VIR_DOMAIN_TPM_TYPE_EXTERNAL:
virObjectUnref(def->data.external.source);
if ((profile = virXPathNode("./backend/profile[1]", ctxt))) {
def->data.emulator.profile.source = virXMLPropString(profile, "source");
- if (!def->data.emulator.profile.source) {
- virReportError(VIR_ERR_XML_ERROR, "%s", _("missing profile source"));
- goto error;
- }
+ def->data.emulator.profile.name = virXMLPropString(profile, "name");
if (virXMLPropEnum(profile, "removeDisabled",
virDomainTPMProfileRemoveDisabledTypeFromString,
VIR_XML_PROP_NONZERO,
virDomainTPMSourceTypeTypeToString(def->data.emulator.source_type));
virBufferEscapeString(&backendChildBuf, " path='%s'/>\n", def->data.emulator.source_path);
}
- if (def->data.emulator.profile.source) {
+ if (def->data.emulator.profile.source ||
+ def->data.emulator.profile.name) {
g_auto(virBuffer) profileAttrBuf = VIR_BUFFER_INITIALIZER;
- virBufferAsprintf(&profileAttrBuf, " source='%s'",
- def->data.emulator.profile.source);
+ if (def->data.emulator.profile.source) {
+ virBufferAsprintf(&profileAttrBuf, " source='%s'",
+ def->data.emulator.profile.source);
+ }
if (def->data.emulator.profile.removeDisabled) {
virBufferAsprintf(&profileAttrBuf, " removeDisabled='%s'",
virDomainTPMProfileRemoveDisabledTypeToString(def->data.emulator.profile.removeDisabled));
}
+ if (def->data.emulator.profile.name) {
+ virBufferAsprintf(&profileAttrBuf, " name='%s'",
+ def->data.emulator.profile.name);
+ }
virXMLFormatElement(&backendChildBuf, "profile", &profileAttrBuf, NULL);
}
break;
}
}
+/* qemuTPMEmulatorUpdateProfileName:
+ *
+ * @emulator: TPM emulator definition
+ * @persistentTPMDef: TPM definition from the persistent domain definition
+ * @cfg: virQEMUDriverConfig
+ * @saveDef: whether caller should save the persistent domain def
+ */
+static int
+qemuTPMEmulatorUpdateProfileName(virDomainTPMEmulatorDef *emulator,
+ virDomainTPMDef *persistentTPMDef,
+ const virQEMUDriverConfig *cfg,
+ bool *saveDef)
+{
+ g_autoptr(virJSONValue) object = NULL;
+ g_autofree char *stderr_buf = NULL;
+ g_autofree char *stdout_buf = NULL;
+ g_autoptr(virCommand) cmd = NULL;
+ g_autofree char *swtpm = NULL;
+ virJSONValue *active_profile;
+ const char *profile_name;
+ int exitstatus;
+
+ if (emulator->version != VIR_DOMAIN_TPM_VERSION_2_0 ||
+ !virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_CMDARG_PRINT_INFO))
+ return 0;
+
+ swtpm = virTPMGetSwtpm();
+ if (!swtpm)
+ return -1;
+
+ cmd = virCommandNew(swtpm);
+
+ virCommandSetUID(cmd, cfg->swtpm_user); /* should be uid of 'tss' or 'root' */
+ virCommandSetGID(cmd, cfg->swtpm_group);
+
+ virCommandAddArgList(cmd, "socket", "--print-info", "0x20", "--tpm2", NULL);
+
+ qemuTPMVirCommandSwtpmAddTPMState(cmd, emulator);
+
+ if (qemuTPMVirCommandSwtpmAddEncryption(cmd, emulator, swtpm) < 0)
+ return -1;
+
+ virCommandClearCaps(cmd);
+
+ virCommandSetOutputBuffer(cmd, &stdout_buf);
+ virCommandSetErrorBuffer(cmd, &stderr_buf);
+
+ if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not run '%1$s --print-info'. exitstatus: %2$d; stderr: %3$s"),
+ swtpm, exitstatus, stderr_buf);
+ return -1;
+ }
+
+ if (!(object = virJSONValueFromString(stdout_buf)))
+ return -1;
+
+ if (!(active_profile = virJSONValueObjectGetObject(object, "ActiveProfile")))
+ return -1;
+
+ profile_name = virJSONValueObjectGetString(active_profile, "Name");
+
+ g_free(emulator->profile.name);
+ emulator->profile.name = g_strdup(profile_name);
+
+ *saveDef = true;
+ g_free(persistentTPMDef->data.emulator.profile.name);
+ persistentTPMDef->data.emulator.profile.name = g_strdup(profile_name);
+
+ return 0;
+}
+
/*
* qemuTPMEmulatorBuildCommand:
*
* @tpm: TPM definition
+ * @persistentTPMDef: TPM definition from the persistent domain definition
* @vmname: The name of the VM
* @vmuuid: The UUID of the VM
* @privileged: whether we are running in privileged mode
* @cfg: virQEMUDriverConfig
* @incomingMigration: whether we have an incoming migration
+ * @saveDef: whether caller should save the persistent domain def
*
* Create the virCommand use for starting the emulator
* Do some initializations on the way, such as creation of storage
*/
static virCommand *
qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
+ virDomainTPMDef *persistentTPMDef,
const char *vmname,
const unsigned char *vmuuid,
bool privileged,
const virQEMUDriverConfig *cfg,
- bool incomingMigration)
+ bool incomingMigration,
+ bool *saveDef)
{
g_autoptr(virCommand) cmd = NULL;
bool created = false;
incomingMigration) < 0)
goto error;
+ if (run_setup && !incomingMigration &&
+ qemuTPMEmulatorUpdateProfileName(&tpm->data.emulator, persistentTPMDef,
+ cfg, saveDef) < 0)
+ goto error;
+
if (!incomingMigration &&
qemuTPMEmulatorReconfigure(&tpm->data.emulator, cfg, secretuuid) < 0)
goto error;
* @driver: QEMU driver
* @vm: the domain object
* @tpm: TPM definition
+ * @persistentTPMDef: TPM definition from persistent domain definition
* @shortName: short and unique name of the domain
* @incomingMigration: whether we have an incoming migration
*
virDomainObj *vm,
const char *shortName,
virDomainTPMDef *tpm,
+ virDomainTPMDef *persistentTPMDef,
bool incomingMigration)
{
g_autoptr(virCommand) cmd = NULL;
g_autofree char *pidfile = NULL;
virTimeBackOffVar timebackoff;
const unsigned long long timeout = 1000; /* ms */
+ bool saveDef = false;
pid_t pid = -1;
bool lockMetadataException = false;
/* stop any left-over TPM emulator for this VM */
qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName);
- if (!(cmd = qemuTPMEmulatorBuildCommand(tpm, vm->def->name, vm->def->uuid,
+ if (!(cmd = qemuTPMEmulatorBuildCommand(tpm, persistentTPMDef,
+ vm->def->name, vm->def->uuid,
driver->privileged,
cfg,
- incomingMigration)))
+ incomingMigration,
+ &saveDef)))
return -1;
+ if (saveDef &&
+ virDomainDefSave(vm->newDef, driver->xmlopt, cfg->configDir) < 0)
+ goto error;
+
if (qemuExtDeviceLogCommand(driver, vm, cmd, "TPM Emulator") < 0)
return -1;
qemuExtTPMStart(virQEMUDriver *driver,
virDomainObj *vm,
virDomainTPMDef *tpm,
+ virDomainTPMDef *persistentTPMDef,
bool incomingMigration)
{
g_autofree char *shortName = virDomainDefGetShortName(vm->def);
if (!shortName)
return -1;
- return qemuTPMEmulatorStart(driver, vm, shortName, tpm, incomingMigration);
+ return qemuTPMEmulatorStart(driver, vm, shortName, tpm, persistentTPMDef,
+ incomingMigration);
}