qemu_tpm: handle file/block storage source

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>.

Teach the storage to use custom directory or file source location.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Marc-André Lureau 2024-10-22 18:15:20 +04:00 committed by Martin Kletzander
parent a110042d0c
commit f1304cc566

View File

@ -340,9 +340,28 @@ qemuTPMVirCommandAddEncryption(virCommand *cmd,
} }
static char *
qemuTPMGetSwtpmSetupStateArg(const virDomainTPMSourceType source_type,
const char *source_path)
{
switch (source_type) {
case VIR_DOMAIN_TPM_SOURCE_TYPE_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", source_path);
case VIR_DOMAIN_TPM_SOURCE_TYPE_DIR:
case VIR_DOMAIN_TPM_SOURCE_TYPE_DEFAULT:
case VIR_DOMAIN_TPM_SOURCE_TYPE_LAST:
default:
return g_strdup_printf("%s", source_path);
}
}
/* /*
* qemuTPMEmulatorRunSetup * qemuTPMEmulatorRunSetup
* *
* @source_type: type of storage
* @source_path: path to the directory for TPM state * @source_path: path to the directory for TPM state
* @vmname: the name of the VM * @vmname: the name of the VM
* @vmuuid: the UUID of the VM * @vmuuid: the UUID of the VM
@ -360,7 +379,8 @@ qemuTPMVirCommandAddEncryption(virCommand *cmd,
* certificates for it. * certificates for it.
*/ */
static int static int
qemuTPMEmulatorRunSetup(const char *source_path, qemuTPMEmulatorRunSetup(const virDomainTPMSourceType source_type,
const char *source_path,
const char *vmname, const char *vmname,
const unsigned char *vmuuid, const unsigned char *vmuuid,
bool privileged, bool privileged,
@ -376,6 +396,7 @@ qemuTPMEmulatorRunSetup(const char *source_path,
char uuid[VIR_UUID_STRING_BUFLEN]; char uuid[VIR_UUID_STRING_BUFLEN];
g_autofree char *vmid = NULL; g_autofree char *vmid = NULL;
g_autofree char *swtpm_setup = virTPMGetSwtpmSetup(); g_autofree char *swtpm_setup = virTPMGetSwtpmSetup();
g_autofree char *tpm_state = qemuTPMGetSwtpmSetupStateArg(source_type, source_path);
if (!swtpm_setup) if (!swtpm_setup)
return -1; return -1;
@ -413,7 +434,7 @@ qemuTPMEmulatorRunSetup(const char *source_path,
if (!incomingMigration) { if (!incomingMigration) {
virCommandAddArgList(cmd, virCommandAddArgList(cmd,
"--tpm-state", source_path, "--tpm-state", tpm_state,
"--vmid", vmid, "--vmid", vmid,
"--logfile", logfile, "--logfile", logfile,
"--createek", "--createek",
@ -424,7 +445,7 @@ qemuTPMEmulatorRunSetup(const char *source_path,
NULL); NULL);
} else { } else {
virCommandAddArgList(cmd, virCommandAddArgList(cmd,
"--tpm-state", source_path, "--tpm-state", tpm_state,
"--logfile", logfile, "--logfile", logfile,
"--overwrite", "--overwrite",
NULL); NULL);
@ -465,6 +486,7 @@ qemuTPMPcrBankBitmapToStr(virBitmap *activePcrBanks)
* qemuTPMEmulatorReconfigure * qemuTPMEmulatorReconfigure
* *
* *
* @source_type: type of storage
* @source_path: path to the directory for TPM state * @source_path: path to the directory for TPM state
* @swtpm_user: The userid to switch to when setting up the TPM; * @swtpm_user: The userid to switch to when setting up the TPM;
* typically this should be the uid of 'tss' or 'root' * typically this should be the uid of 'tss' or 'root'
@ -478,7 +500,8 @@ qemuTPMPcrBankBitmapToStr(virBitmap *activePcrBanks)
* Reconfigure the active PCR banks of a TPM 2. * Reconfigure the active PCR banks of a TPM 2.
*/ */
static int static int
qemuTPMEmulatorReconfigure(const char *source_path, qemuTPMEmulatorReconfigure(const virDomainTPMSourceType source_type,
const char *source_path,
uid_t swtpm_user, uid_t swtpm_user,
gid_t swtpm_group, gid_t swtpm_group,
virBitmap *activePcrBanks, virBitmap *activePcrBanks,
@ -490,6 +513,7 @@ qemuTPMEmulatorReconfigure(const char *source_path,
int exitstatus; int exitstatus;
g_autofree char *activePcrBanksStr = NULL; g_autofree char *activePcrBanksStr = NULL;
g_autofree char *swtpm_setup = virTPMGetSwtpmSetup(); g_autofree char *swtpm_setup = virTPMGetSwtpmSetup();
g_autofree char *tpm_state = qemuTPMGetSwtpmSetupStateArg(source_type, source_path);
if (!swtpm_setup) if (!swtpm_setup)
return -1; return -1;
@ -510,7 +534,7 @@ qemuTPMEmulatorReconfigure(const char *source_path,
return -1; return -1;
virCommandAddArgList(cmd, virCommandAddArgList(cmd,
"--tpm-state", source_path, "--tpm-state", tpm_state,
"--logfile", logfile, "--logfile", logfile,
"--pcr-banks", activePcrBanksStr, "--pcr-banks", activePcrBanksStr,
"--reconfigure", "--reconfigure",
@ -557,6 +581,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
{ {
g_autoptr(virCommand) cmd = NULL; g_autoptr(virCommand) cmd = NULL;
bool created = false; bool created = false;
bool run_setup = false;
g_autofree char *swtpm = virTPMGetSwtpm(); g_autofree char *swtpm = virTPMGetSwtpm();
int pwdfile_fd = -1; int pwdfile_fd = -1;
int migpwdfile_fd = -1; int migpwdfile_fd = -1;
@ -567,6 +592,18 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
if (!swtpm) if (!swtpm)
return NULL; return NULL;
if (tpm->data.emulator.source_type == VIR_DOMAIN_TPM_SOURCE_TYPE_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 /* Do not create storage and run swtpm_setup on incoming migration over
* shared storage * shared storage
*/ */
@ -574,15 +611,18 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
if (incomingMigration && on_shared_storage) if (incomingMigration && on_shared_storage)
create_storage = false; create_storage = false;
if (create_storage && if (create_storage) {
qemuTPMEmulatorCreateStorage(tpm, &created, swtpm_user, swtpm_group) < 0) if (qemuTPMEmulatorCreateStorage(tpm, &created, swtpm_user, swtpm_group) < 0)
return NULL; return NULL;
run_setup = created;
}
if (tpm->data.emulator.hassecretuuid) if (tpm->data.emulator.hassecretuuid)
secretuuid = tpm->data.emulator.secretuuid; secretuuid = tpm->data.emulator.secretuuid;
if (created && if (run_setup &&
qemuTPMEmulatorRunSetup(tpm->data.emulator.source_path, vmname, vmuuid, qemuTPMEmulatorRunSetup(tpm->data.emulator.source_type,
tpm->data.emulator.source_path, vmname, vmuuid,
privileged, swtpm_user, swtpm_group, privileged, swtpm_user, swtpm_group,
tpm->data.emulator.logfile, tpm->data.emulator.logfile,
tpm->data.emulator.version, tpm->data.emulator.version,
@ -590,7 +630,8 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
goto error; goto error;
if (!incomingMigration && if (!incomingMigration &&
qemuTPMEmulatorReconfigure(tpm->data.emulator.source_path, qemuTPMEmulatorReconfigure(tpm->data.emulator.source_type,
tpm->data.emulator.source_path,
swtpm_user, swtpm_group, swtpm_user, swtpm_group,
tpm->data.emulator.activePcrBanks, tpm->data.emulator.activePcrBanks,
tpm->data.emulator.logfile, tpm->data.emulator.logfile,
@ -609,8 +650,18 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
tpm->data.emulator.source->data.nix.path); tpm->data.emulator.source->data.nix.path);
virCommandAddArg(cmd, "--tpmstate"); virCommandAddArg(cmd, "--tpmstate");
virCommandAddArgFormat(cmd, "dir=%s,mode=0600", switch (tpm->data.emulator.source_type) {
tpm->data.emulator.source_path); case VIR_DOMAIN_TPM_SOURCE_TYPE_FILE:
virCommandAddArgFormat(cmd, "backend-uri=file://%s",
tpm->data.emulator.source_path);
break;
case VIR_DOMAIN_TPM_SOURCE_TYPE_DIR:
case VIR_DOMAIN_TPM_SOURCE_TYPE_DEFAULT:
case VIR_DOMAIN_TPM_SOURCE_TYPE_LAST:
virCommandAddArgFormat(cmd, "dir=%s,mode=0600",
tpm->data.emulator.source_path);
break;
}
virCommandAddArg(cmd, "--log"); virCommandAddArg(cmd, "--log");
if (tpm->data.emulator.debug != 0) if (tpm->data.emulator.debug != 0)