[libvirt] [PATCH] tpm: Run swtpm_setup with less parameters on incoming migration
by Stefan Berger
In case of an incoming migration we do not need to run swtpm_setup
with all the parameters but only want to get the benefit of it
creating a TPM state file for us that we can then label with an
SELinux label. The actual state will be overwritten by the in-
coming state. So we have to pass an indicator for incomingMigration
all the way to the command line parameter generation for swtpm_setup.
Signed-off-by: Stefan Berger <stefanb(a)linux.ibm.com>
---
src/qemu/qemu_extdevice.c | 5 ++--
src/qemu/qemu_extdevice.h | 3 ++-
src/qemu/qemu_process.c | 2 +-
src/qemu/qemu_tpm.c | 49 +++++++++++++++++++++++++--------------
src/qemu/qemu_tpm.h | 3 ++-
5 files changed, 40 insertions(+), 22 deletions(-)
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index e576bca165..af52466421 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -128,7 +128,8 @@ qemuExtDevicesCleanupHost(virQEMUDriverPtr driver,
int
qemuExtDevicesStart(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuDomainLogContextPtr logCtxt)
+ qemuDomainLogContextPtr logCtxt,
+ bool incomingMigration)
{
int ret = 0;
@@ -136,7 +137,7 @@ qemuExtDevicesStart(virQEMUDriverPtr driver,
return -1;
if (vm->def->tpm)
- ret = qemuExtTPMStart(driver, vm, logCtxt);
+ ret = qemuExtTPMStart(driver, vm, logCtxt, incomingMigration);
return ret;
}
diff --git a/src/qemu/qemu_extdevice.h b/src/qemu/qemu_extdevice.h
index bbdb9a1cc2..5a53c79f38 100644
--- a/src/qemu/qemu_extdevice.h
+++ b/src/qemu/qemu_extdevice.h
@@ -40,7 +40,8 @@ void qemuExtDevicesCleanupHost(virQEMUDriverPtr driver,
int qemuExtDevicesStart(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuDomainLogContextPtr logCtxt)
+ qemuDomainLogContextPtr logCtxt,
+ bool incomingMigration)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_RETURN_CHECK;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 75205bc121..fae18824ba 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6774,7 +6774,7 @@ qemuProcessLaunch(virConnectPtr conn,
if (qemuProcessGenID(vm, flags) < 0)
goto cleanup;
- if (qemuExtDevicesStart(driver, vm, logCtxt) < 0)
+ if (qemuExtDevicesStart(driver, vm, logCtxt, incoming != NULL) < 0)
goto cleanup;
VIR_DEBUG("Building emulator command line");
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 77ef601f74..4174aa4c62 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -453,6 +453,7 @@ qemuTPMSetupEncryption(const unsigned char *secretuuid,
* for the user given by userid or 'tss'
* @tpmversion: The version of the TPM, either a TPM 1.2 or TPM 2
* @encryption: pointer to virStorageEncryption holding secret
+ * @incomingMigration: whether we have an incoming migration
*
* Setup the external swtpm by creating endorsement key and
* certificates for it.
@@ -466,7 +467,8 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
gid_t swtpm_group,
const char *logfile,
const virDomainTPMVersion tpmversion,
- const unsigned char *secretuuid)
+ const unsigned char *secretuuid,
+ bool incomingMigration)
{
virCommandPtr cmd = NULL;
int exitstatus;
@@ -525,16 +527,23 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
pwdfile_fd = -1;
}
- virCommandAddArgList(cmd,
- "--tpm-state", storagepath,
- "--vmid", vmid,
- "--logfile", logfile,
- "--createek",
- "--create-ek-cert",
- "--create-platform-cert",
- "--lock-nvram",
- "--not-overwrite",
- NULL);
+ if (!incomingMigration) {
+ virCommandAddArgList(cmd,
+ "--tpm-state", storagepath,
+ "--vmid", vmid,
+ "--logfile", logfile,
+ "--createek",
+ "--create-ek-cert",
+ "--create-platform-cert",
+ "--lock-nvram",
+ "--not-overwrite",
+ NULL);
+ } else {
+ virCommandAddArgList(cmd,
+ "--tpm-state", storagepath,
+ "--overwrite",
+ NULL);
+ }
virCommandClearCaps(cmd);
@@ -568,6 +577,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
* @swtpmStateDir: the directory where swtpm writes the pid file and creates the
* Unix socket
* @shortName: the short name of the VM
+ * @incomingMigration: whether we have an incoming migration
*
* Create the virCommand use for starting the emulator
* Do some initializations on the way, such as creation of storage
@@ -581,7 +591,8 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
uid_t swtpm_user,
gid_t swtpm_group,
const char *swtpmStateDir,
- const char *shortName)
+ const char *shortName,
+ bool incomingMigration)
{
virCommandPtr cmd = NULL;
bool created = false;
@@ -605,7 +616,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
qemuTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmuuid,
privileged, swtpm_user, swtpm_group,
tpm->data.emulator.logfile, tpm->version,
- secretuuid) < 0)
+ secretuuid, incomingMigration) < 0)
goto error;
unlink(tpm->data.emulator.source.data.nix.path);
@@ -814,6 +825,7 @@ qemuExtTPMCleanupHost(virDomainDefPtr def)
* @driver: QEMU driver
* @vm: the domain object
* @logCtxt: log context
+ * @incomingMigration: whether we have an incoming migration
*
* Start the external TPM Emulator:
* - have the command line built
@@ -822,7 +834,8 @@ qemuExtTPMCleanupHost(virDomainDefPtr def)
static int
qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuDomainLogContextPtr logCtxt)
+ qemuDomainLogContextPtr logCtxt,
+ bool incomingMigration)
{
int ret = -1;
virCommandPtr cmd = NULL;
@@ -846,7 +859,8 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
driver->privileged,
cfg->swtpm_user,
cfg->swtpm_group,
- cfg->swtpmStateDir, shortName)))
+ cfg->swtpmStateDir, shortName,
+ incomingMigration)))
goto cleanup;
if (qemuExtDeviceLogCommand(logCtxt, cmd, "TPM Emulator") < 0)
@@ -903,14 +917,15 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver,
int
qemuExtTPMStart(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuDomainLogContextPtr logCtxt)
+ qemuDomainLogContextPtr logCtxt,
+ bool incomingMigration)
{
int ret = 0;
virDomainTPMDefPtr tpm = vm->def->tpm;
switch (tpm->type) {
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
- ret = qemuExtTPMStartEmulator(driver, vm, logCtxt);
+ ret = qemuExtTPMStartEmulator(driver, vm, logCtxt, incomingMigration);
break;
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
case VIR_DOMAIN_TPM_TYPE_LAST:
diff --git a/src/qemu/qemu_tpm.h b/src/qemu/qemu_tpm.h
index 74c9924d68..5f454d3580 100644
--- a/src/qemu/qemu_tpm.h
+++ b/src/qemu/qemu_tpm.h
@@ -37,7 +37,8 @@ void qemuExtTPMCleanupHost(virDomainDefPtr def)
int qemuExtTPMStart(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- qemuDomainLogContextPtr logCtxt)
+ qemuDomainLogContextPtr logCtxt,
+ bool incomingMigration)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_RETURN_CHECK;
--
2.21.0
5 years, 5 months
[libvirt] [PATCH v2 0/2] tpm2: Properly handle a removed logfile
by Stefan Berger
If the swtpm's logfile was removed by the user, we get an error
'no transaction is set' from the security manager (DAC) since the
labeling of the file failed the transaction in the commit() phase.
In the failure case we will try to remove the label then in the
error path and run into another commit() error and overwrite a more
useful error message. So in this case we just call the transaction
abort function. We also create an empty log file now since swtpm
doesn't seem to be able to create one itself.
Stefan
v1->v2:
- Added R-b's
Stefan Berger (2):
tpm: Set transationStarted to false if commit failed
tpm: Create empty log file if file was removed
src/qemu/qemu_security.c | 3 ++-
src/qemu/qemu_tpm.c | 8 ++++++--
2 files changed, 8 insertions(+), 3 deletions(-)
--
2.21.0
5 years, 5 months
[libvirt] [PATCH v2 0/4] Cleanups on vTPM encryption patches
by Stefan Berger
This series of patches cleans up the Coverity issues reported by John.
Stefan
v1->v2: fixed patch 3
Stefan Berger (4):
tpm: Fix memory leak and use existing variable instead
tests: Call virCommandFree() in cleanup section
utils: Remove ATTRIBUTE_NONNULL(1) from virCommandSetSendBuffer
conf: Remove ATTRIBUTE_NONNULL(2) from virDomainCheckDeviceChanges()
src/conf/domain_conf.h | 3 +--
src/qemu/qemu_tpm.c | 4 ++--
src/util/vircommand.c | 3 ++-
src/util/vircommand.h | 2 +-
tests/commandtest.c | 3 +--
5 files changed, 7 insertions(+), 8 deletions(-)
--
2.20.1
5 years, 5 months
[libvirt] [PATCH] backup: Fix tests/virsh-snapshot
by Eric Blake
Creating an 'exp' output file, but never comparing it against the
actual output, does no one any good. :)
Fixes: 280a2b41e
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the trivial rule.
tests/virsh-snapshot | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/virsh-snapshot b/tests/virsh-snapshot
index b23d949f62..1034140cde 100755
--- a/tests/virsh-snapshot
+++ b/tests/virsh-snapshot
@@ -207,6 +207,8 @@ Descendants: 0
Metadata: yes
EOF
+sed '1,/^virsh #/d; /virsh #/d' < out > out.cooked || fail=1
+compare exp out.cooked || fail=1
cat <<EOF > exp || fail=1
error: invalid argument: parent s3 for moment s2 not found
--
2.20.1
5 years, 5 months
[libvirt] [PATCH 0/2] tpm2: Properly handle a removed logfile
by Stefan Berger
If the swtpm's logfile was removed by the user, we get an error
'no transaction is set' from the security manager (DAC) since the
labeling of the file failed the transaction in the commit() phase.
In the failure case we will try to remove the label then in the
error path and run into another commit() error and overwrite a more
useful error message. So in this case we just call the transaction
abort function. We also create an empty log file now since swtpm
doesn't seem to be able to create one itself.
Stefan
Stefan Berger (2):
tpm: Set transationStarted to false if commit failed
tpm: Create empty log file if file was removed
src/qemu/qemu_security.c | 6 ++++--
src/qemu/qemu_tpm.c | 8 ++++++--
2 files changed, 10 insertions(+), 4 deletions(-)
--
2.21.0
5 years, 5 months
[libvirt] [PATCH 0/4] Cleanups on vTPM encrytion patches
by Stefan Berger
This series of patches cleans up the Coverity issues reported by John.
Stefan
Stefan Berger (4):
tpm: Fix memory leak and use existing variable instead
tests: Call virCommandFree() in cleanup section
utils: Remove ATTRIBUTE_NONNULL(1) from virCommandSetSendBuffer
conf: Remove ATTRIBUTE_NONNULL(2) from virDomainCheckDeviceChanges()
src/conf/domain_conf.h | 3 +--
src/qemu/qemu_tpm.c | 4 ++--
src/util/vircommand.h | 2 +-
tests/commandtest.c | 3 +--
4 files changed, 5 insertions(+), 7 deletions(-)
--
2.20.1
5 years, 5 months
[libvirt] [PATCH v7 00/19] Add support for vTPM state encryption
by Stefan Berger
This series of patches addresses the RFE in BZ 172830:
https://bugzilla.redhat.com/show_bug.cgi?id=1728030
This series of patches adds support for vTPM state encryption by passing
the read-end of a pipe's file descriptor to 'swtpm_setup' and 'swtpm'
where they can read a passphrase from and derive a key from that passphrase.
The TPM's domain XML looks to enable state encryption looks like this:
<tpm model='tpm-tis'>
<backend type='emulator' version='1.2'>
<encryption secret='2c9ceaba-c6ef-4f38-86fd-6e3adb2df5cd'/>
</backend>
</tpm>
The vTPM secret holding the passphrase looks like this:
<secret ephemeral='no' private='yes'>
<uuid>2c9ceaba-c6ef-4f38-86fd-6e3adb2df5cd</uuid>
<description>vTPM passphrase example</description>
<usage type='vtpm'>
<name>vtpm_example</name>
</usage>
</secret>
The swtpm v0.2 is needed that supports the command line option
--print-capabilities returning a JSON object that identifies features added
since v0.1. One such features is the possibility to pass a passphrase via a
file descriptor.
The patches do some refactoring of existing code on the way.
Stefan
v1->v2:
- Added Marc-André's R-bs
- Addressed comments
- Added patches to extend virCommand to be able to write contents of multiple
buffers to file descriptors for a spawned process to read from
v2->v3:
- Fixed some pointer issues following conversion to use VIR_AUTOFREE
v3->v4:
- Added test case for virCommandSetSendBuffer() to commantest.c
- Addressed other issues raised by Marc-André
v4->v5:
- Simplified encryption node in TPM's domain XML and adapted everything that
depends on this; dropped some patches and removed some R-bs for non-trivial
stuff
- Not limiting write size for fd's with O_NONBLOCK set
v5->v6:
- Addressed comments on v5
v6->v7:
- Stubbed out virCommandSetSendBuffer if F_SETFL is not defined. Also having
'the other' occurrence of F_SETFL cause an error if F_SETFL is not defined.
Stefan Berger (19):
secret: Add support for usage type vTPM, extend schema and test case
tests: Add already existing test case tpm-emulator-tpm2
conf: Extend TPM XML parser with encryption support
tests: Add test for TPM XML encryption parser and formatter
tests: Add tests for QEMU command line generation with encrypted TPM
tpm: Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c
tpm: Refactor virTPMEmulatorInit to use loop
tpm: Check whether previously found executables were updated
tpm: Parse the capabilities supported by swtpm and swtpm_setup
utils: Implement function to pass a buffer to send via a fd to
virCommand
utils: Convert pollfd array to be allocated
utils: Mark inpipe as non-blocking
utils: Extend virCommandProcessIO to include the send buffers
tests: Extend command test to transfer large data to process on
multiple fds
tpm: Use fd to pass password to swtpm_setup and swtpm
tpm: Pass migration key passphrase via fd to swtpm
tpm: Check TPM XML device configuration changes after edit
docs: Extend Secret XML documentation with vtpm usage type
docs: Extend TPM docs with new encryption element
docs/formatdomain.html.in | 12 +
docs/formatsecret.html.in | 61 +++-
docs/schemas/domaincommon.rng | 11 +
docs/schemas/secret.rng | 10 +
include/libvirt/libvirt-secret.h | 1 +
include/libvirt/virterror.h | 2 +
src/conf/domain_conf.c | 87 ++++-
src/conf/domain_conf.h | 6 +
src/conf/secret_conf.c | 13 +
src/libvirt_private.syms | 10 +
src/qemu/qemu_driver.c | 28 ++
src/qemu/qemu_extdevice.c | 2 +-
src/qemu/qemu_extdevice.h | 3 +
src/qemu/qemu_tpm.c | 211 ++++++++-----
src/util/vircommand.c | 171 +++++++++-
src/util/vircommand.h | 5 +
src/util/virerror.c | 2 +
src/util/virsecret.c | 2 +-
src/util/virtpm.c | 298 +++++++++++++++++-
src/util/virtpm.h | 23 ++
tests/commandhelper.c | 70 +++-
tests/commandtest.c | 113 +++++++
.../tpm-emulator-tpm2-enc.x86_64-latest.args | 35 ++
.../tpm-emulator-tpm2-enc.xml | 32 ++
tests/qemuxml2argvtest.c | 1 +
.../tpm-emulator-tpm2-enc.xml | 36 +++
tests/qemuxml2xmltest.c | 2 +
tests/secretxml2xmlin/usage-vtpm.xml | 7 +
tests/secretxml2xmltest.c | 1 +
29 files changed, 1168 insertions(+), 87 deletions(-)
create mode 100644 tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
create mode 100644 tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml
create mode 100644 tests/secretxml2xmlin/usage-vtpm.xml
--
2.20.1
5 years, 5 months
[libvirt] [PATCH] test_driver: implement virDomainGetCPUStats
by Ilias Stamatis
Signed-off-by: Ilias Stamatis <stamatis.iliass(a)gmail.com>
---
src/test/test_driver.c | 131 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 131 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index fcb80c9e47..2907c043cb 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -3258,6 +3258,136 @@ static int testDomainSetMetadata(virDomainPtr dom,
return ret;
}
+
+static int
+testDomainGetDomainTotalCpuStats(virTypedParameterPtr params,
+ int nparams)
+{
+ if (nparams == 0) /* return supported number of params */
+ return 3;
+
+ if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
+ VIR_TYPED_PARAM_ULLONG, 77102913900) < 0)
+ return -1;
+
+ if (nparams > 1 &&
+ virTypedParameterAssign(¶ms[1],
+ VIR_DOMAIN_CPU_STATS_USERTIME,
+ VIR_TYPED_PARAM_ULLONG, 45650000000) < 0)
+ return -1;
+
+ if (nparams > 2 &&
+ virTypedParameterAssign(¶ms[2],
+ VIR_DOMAIN_CPU_STATS_SYSTEMTIME,
+ VIR_TYPED_PARAM_ULLONG, 11390000000) < 0)
+ return -1;
+
+ if (nparams > 3)
+ nparams = 3;
+
+ return nparams;
+}
+
+
+static int
+testDomainGetPercpuStats(virTypedParameterPtr params,
+ unsigned int nparams,
+ int start_cpu,
+ unsigned int ncpus,
+ int total_cpus)
+{
+ size_t i;
+ int need_cpus;
+ int param_idx;
+ int ret = -1;
+
+ /* return the number of supported params */
+ if (nparams == 0 && ncpus != 0)
+ return 2;
+
+ /* return total number of cpus */
+ if (ncpus == 0) {
+ ret = total_cpus;
+ goto cleanup;
+ }
+
+ if (start_cpu >= total_cpus) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("start_cpu %d larger than maximum of %d"),
+ start_cpu, total_cpus - 1);
+ goto cleanup;
+ }
+
+ /* return percpu cputime in index 0 */
+ param_idx = 0;
+
+ /* number of cpus to compute */
+ need_cpus = MIN(total_cpus, start_cpu + ncpus);
+
+ for (i = 0; i < need_cpus; i++) {
+ if (i < start_cpu)
+ continue;
+ int idx = (i - start_cpu) * nparams + param_idx;
+ if (virTypedParameterAssign(¶ms[idx],
+ VIR_DOMAIN_CPU_STATS_CPUTIME,
+ VIR_TYPED_PARAM_ULLONG,
+ 202542145062 + 10 * i) < 0)
+ goto cleanup;
+ }
+
+ /* return percpu vcputime in index 1 */
+ param_idx = 1;
+
+ if (param_idx < nparams) {
+ for (i = start_cpu; i < need_cpus; i++) {
+ int idx = (i - start_cpu) * nparams + param_idx;
+ if (virTypedParameterAssign(¶ms[idx],
+ VIR_DOMAIN_CPU_STATS_VCPUTIME,
+ VIR_TYPED_PARAM_ULLONG,
+ 26254023765 + 10 * i) < 0)
+ goto cleanup;
+ }
+ param_idx++;
+ }
+
+ ret = param_idx;
+ cleanup:
+ return ret;
+}
+
+
+static int
+testDomainGetCPUStats(virDomainPtr dom,
+ virTypedParameterPtr params,
+ unsigned int nparams,
+ int start_cpu,
+ unsigned int ncpus,
+ unsigned int flags)
+{
+ virDomainObjPtr vm = NULL;
+ testDriverPtr privconn = dom->conn->privateData;
+ int ret = -1;
+
+ virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ return -1;
+
+ if (virDomainObjCheckActive(vm) < 0)
+ goto cleanup;
+
+ if (start_cpu == -1)
+ ret = testDomainGetDomainTotalCpuStats(params, nparams);
+ else
+ ret = testDomainGetPercpuStats(params, nparams, start_cpu, ncpus,
+ privconn->nodeInfo.cores);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
static int
testDomainSendProcessSignal(virDomainPtr dom,
long long pid_value,
@@ -7794,6 +7924,7 @@ static virHypervisorDriver testHypervisorDriver = {
.domainSendKey = testDomainSendKey, /* 5.5.0 */
.domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */
.domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */
+ .domainGetCPUStats = testDomainGetCPUStats, /* 5.6.0 */
.domainSendProcessSignal = testDomainSendProcessSignal, /* 5.5.0 */
.connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.3 */
.domainManagedSave = testDomainManagedSave, /* 1.1.4 */
--
2.22.0
5 years, 5 months
[libvirt] [PATCH 0/4] test_driver: implement IOThread related APIs
by Ilias Stamatis
Ilias Stamatis (4):
test_driver: implement virDomainAddIOThread
test_driver: implement virDomainDelIOThread
test_driver: implement virDomainPinIOThread
test_driver: implement virDomainGetIOThreadInfo
src/test/test_driver.c | 248 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 248 insertions(+)
--
2.22.0
5 years, 5 months