Re: [libvirt] [PATCH 6/8] backup: Add support for filtering based on current moment

2019-07-10 Thread Eric Blake
On 7/8/19 3:27 AM, Peter Krempa wrote:
> On Fri, Jul 05, 2019 at 23:37:33 -0500, Eric Blake wrote:
>> Right now, the snapshot API permits at most one current snapshot, and
>> includes specific API for getting at that snapshot
>> (virDomainHasCurrentSnapshot, virDomainSnapshotCurrent,
>> virDomainSnapshotIsCurrent).  However, with upcoming checkpoints, it
>> is conceivable that a hypervisor could mark multiple checkpoints as
> 
> The same happens to snapshots too. Since you can create an "incomplete"
> snapshot by unselecting some disks and then do a complement snapshot of
> all the remaining disks then you get to the same situation.
> 
> For more fun you can create a snapshot which partially overlaps and then
> neither of the "current" snapshots makes sense any more.

For now, I'm deferring this patch to later (or maybe even dropping it),
based on the v9 review comments about using the one-and-only leaf node
snapshot as the default parent at least for the short term where we
interlock against having snapshots. If we find that changing a
checkpoint current node makes sense with snapshots, we can always add
additional filtering at that time, but right now is premature.  While it
is more churn for me, I agree with the goal of stripping down the
initial implementation to the bare minimum needed, and this does not
qualify in that regards.

>> @@ -78,8 +78,10 @@ typedef enum {
>>  VIR_DOMAIN_MOMENT_LIST_TOPOLOGICAL = (1 << 1),
>>  VIR_DOMAIN_MOMENT_LIST_LEAVES  = (1 << 2),
>>  VIR_DOMAIN_MOMENT_LIST_NO_LEAVES   = (1 << 3),
>> -VIR_DOMAIN_MOMENT_LIST_METADATA= (1 << 4),
>> -VIR_DOMAIN_MOMENT_LIST_NO_METADATA = (1 << 5),
>> +VIR_DOMAIN_MOMENT_LIST_CURRENT = (1 << 4),
>> +VIR_DOMAIN_MOMENT_LIST_NO_CURRENT  = (1 << 5),
>> +VIR_DOMAIN_MOMENT_LIST_METADATA= (1 << 6),
>> +VIR_DOMAIN_MOMENT_LIST_NO_METADATA = (1 << 7),
> 
> Why the reorder?

Because if we like the idea of filtering on a current node better than
the idea of no_metadata, then patches that add current filtering in v9
use bit 6 right away, while bits for metadata filtering of checkpoints
sit unused, and it looks odd to have a gap in the numbering. The
snapshot code already has to do mapping between internal bits from the
public API flags, but my initial goal was to have the internal bits
match the checkpoint public bits.  That said, since I'm now working on
stripping the notion of current filtering out of checkpoints before the
initial implementation, the question is moot until (or if) this patch
ever gets revived.

> 
> 
>>  } virDomainMomentFilters;
>>
>>  #define VIR_DOMAIN_MOMENT_FILTERS_METADATA \
> 
> ACK

Thanks for the review, even if later patches changed our minds.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 05/21] schema: Extend the TPM XML schema with support for encryption

2019-07-10 Thread Stefan Berger
Extend the TPM XML schema with support for an encryption node.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/schemas/domaincommon.rng | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 31db599ab9..4a4f4f8a4d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4316,6 +4316,7 @@
   
  emulator
   
+  
 
   
   
@@ -4345,6 +4346,35 @@
 
   
 
+  
+
+  
+
+  vtpm
+
+
+  
+
+  
+
+  
+
+  
+
+  passphrase
+
+  
+  
+
+  
+
+
+  
+
+  
+
+  
+
   
 
   
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 06/21] tests: Add test for TPM XML encryption parser and formatter

2019-07-10 Thread Stefan Berger
Add a test case for the TPM XML encryption parser and formatter.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 .../tpm-emulator-tpm2-enc.xml | 34 +
 .../tpm-emulator-tpm2-enc.xml | 38 +++
 tests/qemuxml2xmltest.c   |  1 +
 3 files changed, 73 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
 create mode 100644 tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml

diff --git a/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml 
b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
new file mode 100644
index 00..3838518e65
--- /dev/null
+++ b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
@@ -0,0 +1,34 @@
+
+  TPM-VM
+  11d7cd22-da89-3094-6212-079a48a309a1
+  2097152
+  512288
+  1
+  
+hvm
+
+
+  
+  
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+
+
+
+
+  
+
+  
+
+  
+
+
+  
+
diff --git a/tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml 
b/tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml
new file mode 100644
index 00..7083fc9c13
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml
@@ -0,0 +1,38 @@
+
+  TPM-VM
+  11d7cd22-da89-3094-6212-079a48a309a1
+  2097152
+  512288
+  1
+  
+hvm
+
+
+  
+  
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+
+
+
+
+
+  
+
+  
+
+  
+
+
+  
+
+  
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index a29958ae29..f6cd56cc8f 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -654,6 +654,7 @@ mymain(void)
 DO_TEST("tpm-passthrough-crb", NONE);
 DO_TEST("tpm-emulator", NONE);
 DO_TEST("tpm-emulator-tpm2", NONE);
+DO_TEST("tpm-emulator-tpm2-enc", NONE);
 
 DO_TEST("metadata", NONE);
 DO_TEST("metadata-duplicate", NONE);
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 14/21] utils: Convert pollfd array to be allocated

2019-07-10 Thread Stefan Berger
Convert the struct pollfd *fds to be allocated rather than residing
on the stack. This prepares it for the next patch where the size of
the array of fds becomes dynamic.

Signed-off-by: Stefan Berger 
---
 src/util/vircommand.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index e32377497b..898ee0df45 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -2123,6 +2123,7 @@ virCommandProcessIO(virCommandPtr cmd)
 size_t inlen = 0, outlen = 0, errlen = 0;
 size_t inoff = 0;
 int ret = 0;
+VIR_AUTOFREE(struct pollfd *) fds = NULL;
 
 if (dryRunBuffer || dryRunCallback) {
 VIR_DEBUG("Dry run requested, skipping I/O processing");
@@ -2154,9 +2155,11 @@ virCommandProcessIO(virCommandPtr cmd)
 goto cleanup;
 ret = -1;
 
+if (VIR_ALLOC_N(fds, 3) < 0)
+goto cleanup;
+
 for (;;) {
 size_t i;
-struct pollfd fds[3];
 int nfds = 0;
 
 if (cmd->inpipe != -1) {
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 04/21] conf: Extend TPM XML parser with encryption support

2019-07-10 Thread Stefan Berger
Extend the TPM device XML parser and XML generator with emulator
state encryption support.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/conf/domain_conf.c | 40 +++-
 src/conf/domain_conf.h |  1 +
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3323c9a5b1..df6238c299 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2950,6 +2950,7 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def)
 virDomainChrSourceDefClear(>data.emulator.source);
 VIR_FREE(def->data.emulator.storagepath);
 VIR_FREE(def->data.emulator.logfile);
+virStorageEncryptionFree(def->data.emulator.encryption);
 break;
 case VIR_DOMAIN_TPM_TYPE_LAST:
 break;
@@ -13048,6 +13049,16 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr 
xmlopt,
  * 
  *   
  * 
+ *
+ * Emulator state encryption is supported with the following:
+ *
+ * 
+ *   
+ * 
+ *
+ * 
+ *   
+ * 
  */
 static virDomainTPMDefPtr
 virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
@@ -13063,6 +13074,7 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
 VIR_AUTOFREE(char *) backend = NULL;
 VIR_AUTOFREE(char *) version = NULL;
 VIR_AUTOFREE(xmlNodePtr *) backends = NULL;
+xmlNodePtr encnode = NULL;
 
 if (VIR_ALLOC(def) < 0)
 return NULL;
@@ -13126,6 +13138,21 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
 def->data.passthrough.source.type = VIR_DOMAIN_CHR_TYPE_DEV;
 break;
 case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+encnode = virXPathNode("./backend/encryption", ctxt);
+if (encnode) {
+def->data.emulator.encryption =
+   virStorageEncryptionParseNode(encnode, ctxt);
+if (!def->data.emulator.encryption)
+goto error;
+if (def->data.emulator.encryption->format !=
+VIR_STORAGE_ENCRYPTION_FORMAT_VTPM) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("Unsupported vTPM encryption type '%s'"),
+   virStorageEncryptionFormatTypeToString(
+   def->data.emulator.encryption->format));
+goto error;
+}
+}
 break;
 case VIR_DOMAIN_TPM_TYPE_LAST:
 goto error;
@@ -25949,8 +25976,19 @@ virDomainTPMDefFormat(virBufferPtr buf,
 virBufferAddLit(buf, "\n");
 break;
 case VIR_DOMAIN_TPM_TYPE_EMULATOR:
-virBufferAsprintf(buf, " version='%s'/>\n",
+virBufferAsprintf(buf, " version='%s'",
   virDomainTPMVersionTypeToString(def->version));
+if (def->data.emulator.encryption) {
+virBufferAddLit(buf, ">\n");
+virBufferAdjustIndent(buf, 2);
+if (virStorageEncryptionFormat(buf,
+   def->data.emulator.encryption) < 0)
+return -1;
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+} else {
+virBufferAddLit(buf, "/>\n");
+}
 break;
 case VIR_DOMAIN_TPM_TYPE_LAST:
 break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c1b5fc1337..a03986623a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1270,6 +1270,7 @@ struct _virDomainTPMDef {
 virDomainChrSourceDef source;
 char *storagepath;
 char *logfile;
+virStorageEncryptionPtr encryption;
 } emulator;
 } data;
 };
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 11/21] tpm: Check whether previously found executables were updated

2019-07-10 Thread Stefan Berger
Check whether previously found executables were updated and if
so look for them again. This helps to use updated features of
swtpm and its tools upon updating them.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/qemu/qemu_tpm.c |  1 +
 src/tpm/virtpm.c| 34 ++
 2 files changed, 35 insertions(+)

diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 61b4f72320..2afa8db448 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c
index 0179b1e8be..e4735f9c4d 100644
--- a/src/tpm/virtpm.c
+++ b/src/tpm/virtpm.c
@@ -77,8 +77,13 @@ virTPMCreateCancelPath(const char *devpath)
  * executables for the swtpm; to be found on the host
  */
 static char *swtpm_path;
+static struct stat swtpm_stat;
+
 static char *swtpm_setup;
+static struct stat swtpm_setup_stat;
+
 static char *swtpm_ioctl;
+static struct stat swtpm_ioctl_stat;
 
 const char *
 virTPMGetSwtpm(void)
@@ -116,18 +121,22 @@ virTPMEmulatorInit(void)
 static const struct {
 const char *name;
 char **path;
+struct stat *stat;
 } prgs[] = {
 {
 .name = "swtpm",
 .path = _path,
+.stat = _stat,
 },
 {
 .name = "swtpm_setup",
 .path = _setup,
+.stat = _setup_stat,
 },
 {
 .name = "swtpm_ioctl",
 .path = _ioctl,
+.stat = _ioctl_stat,
 }
 };
 size_t i;
@@ -135,6 +144,23 @@ virTPMEmulatorInit(void)
 for (i = 0; i < ARRAY_CARDINALITY(prgs); i++) {
 char *path;
 bool findit = *prgs[i].path == NULL;
+struct stat statbuf;
+char *tmp;
+
+if (!findit) {
+/* has executables changed? */
+if (stat(*prgs[i].path, ) < 0) {
+virReportSystemError(errno,
+ _("Could not stat %s"), path);
+findit = true;
+}
+if (!findit &&
+memcmp(_mtim,
+   [i].stat->st_mtime,
+   sizeof(statbuf.st_mtim))) {
+findit = true;
+}
+}
 
 if (findit) {
 path = virFindFileInPath(prgs[i].name);
@@ -151,7 +177,15 @@ virTPMEmulatorInit(void)
 VIR_FREE(path);
 return -1;
 }
+if (stat(path, prgs[i].stat) < 0) {
+virReportSystemError(errno,
+ _("Could not stat %s"), path);
+VIR_FREE(path);
+return -1;
+}
+tmp = *prgs[i].path;
 *prgs[i].path = path;
+VIR_FREE(tmp);
 }
 }
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 09/21] tpm: Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c

2019-07-10 Thread Stefan Berger
Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c and introduce
a few functions to query the executables needed for virCommands.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/libvirt_private.syms |  4 ++
 src/qemu/qemu_tpm.c  | 83 
 src/tpm/virtpm.c | 91 
 src/tpm/virtpm.h |  5 +++
 4 files changed, 108 insertions(+), 75 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e29007cab1..e33d7d9f14 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1447,6 +1447,10 @@ virSecurityManagerVerify;
 
 # tpm/virtpm.h
 virTPMCreateCancelPath;
+virTPMEmulatorInit;
+virTPMGetSwtpm;
+virTPMGetSwtpmIoctl;
+virTPMGetSwtpmSetup;
 
 
 # util/viralloc.h
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index cc8c69433b..61b4f72320 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -41,79 +41,12 @@
 #include "configmake.h"
 #include "dirname.h"
 #include "qemu_tpm.h"
+#include "virtpm.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 VIR_LOG_INIT("qemu.tpm");
 
-/*
- * executables for the swtpm; to be found on the host
- */
-static char *swtpm_path;
-static char *swtpm_setup;
-static char *swtpm_ioctl;
-
-/*
- * qemuTPMEmulatorInit
- *
- * Initialize the Emulator functions by searching for necessary
- * executables that we will use to start and setup the swtpm
- */
-static int
-qemuTPMEmulatorInit(void)
-{
-if (!swtpm_path) {
-swtpm_path = virFindFileInPath("swtpm");
-if (!swtpm_path) {
-virReportSystemError(ENOENT, "%s",
- _("Unable to find 'swtpm' binary in $PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_path)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("TPM emulator %s is not an executable"),
-   swtpm_path);
-VIR_FREE(swtpm_path);
-return -1;
-}
-}
-
-if (!swtpm_setup) {
-swtpm_setup = virFindFileInPath("swtpm_setup");
-if (!swtpm_setup) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find 'swtpm_setup' in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_setup)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("'%s' is not an executable"),
-   swtpm_setup);
-VIR_FREE(swtpm_setup);
-return -1;
-}
-}
-
-if (!swtpm_ioctl) {
-swtpm_ioctl = virFindFileInPath("swtpm_ioctl");
-if (!swtpm_ioctl) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find swtpm_ioctl in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_ioctl)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("swtpm_ioctl program %s is not an executable"),
-   swtpm_ioctl);
-VIR_FREE(swtpm_ioctl);
-return -1;
-}
-}
-
-return 0;
-}
-
-
 /*
  * qemuTPMCreateEmulatorStoragePath
  *
@@ -350,7 +283,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
 if (!pidfile)
 return -ENOMEM;
 
-ret = virPidFileReadPathIfAlive(pidfile, pid, swtpm_path);
+ret = virPidFileReadPathIfAlive(pidfile, pid, virTPMGetSwtpm());
 
 VIR_FREE(pidfile);
 
@@ -386,7 +319,7 @@ qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
 {
 int ret = -1;
 
-if (qemuTPMEmulatorInit() < 0)
+if (virTPMEmulatorInit() < 0)
 return -1;
 
 /* create log dir ... allow 'tss' user to cd into it */
@@ -478,7 +411,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
  "this requires privileged mode for a "
  "TPM 1.2\n"), 0600);
 
-cmd = virCommandNew(swtpm_setup);
+cmd = virCommandNew(virTPMGetSwtpmSetup());
 if (!cmd)
 goto cleanup;
 
@@ -518,7 +451,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not run '%s'. exitstatus: %d; "
  "Check error log '%s' for details."),
-  swtpm_setup, exitstatus, logfile);
+  virTPMGetSwtpmSetup(), exitstatus, logfile);
 goto cleanup;
 }
 
@@ -575,7 +508,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 
 unlink(tpm->data.emulator.source.data.nix.path);
 
-cmd = virCommandNew(swtpm_path);
+cmd = virCommandNew(virTPMGetSwtpm());
 if (!cmd)
 goto error;
 
@@ -640,7 +573,7 @@ qemuTPMEmulatorStop(const char *swtpmStateDir,
 char *pathname;
 char *errbuf = NULL;
 
-if (qemuTPMEmulatorInit() < 0)
+if (virTPMEmulatorInit() < 0)
 return;
 
 if 

[libvirt] [PATCH v3 18/21] tpm: Pass migration key passphrase via fd to swtpm

2019-07-10 Thread Stefan Berger
This patch now passes the passphrase as a migration key to swtpm.
This now encrypts the state of the TPM while a VM is migrated between
hosts or when suspended into a file. Since the migration key secret
is the same as the state encryption secret, this now requires that
the migration destination host has the same secret value.

Signed-off-by: Stefan Berger 
---
 src/qemu/qemu_tpm.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 880b0642c6..a51e3afee2 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -575,6 +575,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 bool created = false;
 char *pidfile;
 VIR_AUTOCLOSE pwdfile_fd = -1;
+VIR_AUTOCLOSE migpwdfile_fd = -1;
 
 if (qemuTPMCreateEmulatorStorage(tpm->data.emulator.storagepath,
  , swtpm_user, swtpm_group) < 0)
@@ -636,7 +637,9 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 }
 
 pwdfile_fd = qemuTPMSetupEncryption(tpm->data.emulator.encryption, 
cmd);
-if (pwdfile_fd < 0)
+migpwdfile_fd = qemuTPMSetupEncryption(tpm->data.emulator.encryption,
+   cmd);
+if (pwdfile_fd < 0 || migpwdfile_fd < 0)
 goto error;
 
 virCommandAddArg(cmd, "--key");
@@ -644,6 +647,12 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
pwdfile_fd);
 virCommandPassFD(cmd, pwdfile_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
 pwdfile_fd = -1;
+
+virCommandAddArg(cmd, "--migration-key");
+virCommandAddArgFormat(cmd, "pwdfd=%d,mode=aes-256-cbc,kdf=pbkdf2",
+   migpwdfile_fd);
+virCommandPassFD(cmd, migpwdfile_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+migpwdfile_fd = -1;
 }
 
 return cmd;
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 10/21] tpm: Refactor virTPMEmulatorInit to use loop

2019-07-10 Thread Stefan Berger
Refactor virTPMEmulatorInit to use a loop with parameters. This allows
for easier extension later on.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/tpm/virtpm.c | 80 ++--
 1 file changed, 37 insertions(+), 43 deletions(-)

diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c
index 4635d8add0..0179b1e8be 100644
--- a/src/tpm/virtpm.c
+++ b/src/tpm/virtpm.c
@@ -113,51 +113,45 @@ virTPMGetSwtpmIoctl(void)
 int
 virTPMEmulatorInit(void)
 {
-if (!swtpm_path) {
-swtpm_path = virFindFileInPath("swtpm");
-if (!swtpm_path) {
-virReportSystemError(ENOENT, "%s",
- _("Unable to find 'swtpm' binary in $PATH"));
-return -1;
+static const struct {
+const char *name;
+char **path;
+} prgs[] = {
+{
+.name = "swtpm",
+.path = _path,
+},
+{
+.name = "swtpm_setup",
+.path = _setup,
+},
+{
+.name = "swtpm_ioctl",
+.path = _ioctl,
 }
-if (!virFileIsExecutable(swtpm_path)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("TPM emulator %s is not an executable"),
-   swtpm_path);
-VIR_FREE(swtpm_path);
-return -1;
-}
-}
-
-if (!swtpm_setup) {
-swtpm_setup = virFindFileInPath("swtpm_setup");
-if (!swtpm_setup) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find 'swtpm_setup' in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_setup)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("'%s' is not an executable"),
-   swtpm_setup);
-VIR_FREE(swtpm_setup);
-return -1;
-}
-}
+};
+size_t i;
 
-if (!swtpm_ioctl) {
-swtpm_ioctl = virFindFileInPath("swtpm_ioctl");
-if (!swtpm_ioctl) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find swtpm_ioctl in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_ioctl)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("swtpm_ioctl program %s is not an executable"),
-   swtpm_ioctl);
-VIR_FREE(swtpm_ioctl);
-return -1;
+for (i = 0; i < ARRAY_CARDINALITY(prgs); i++) {
+char *path;
+bool findit = *prgs[i].path == NULL;
+
+if (findit) {
+path = virFindFileInPath(prgs[i].name);
+if (!path) {
+virReportSystemError(ENOENT,
+_("Unable to find '%s' binary in $PATH"),
+prgs[i].name);
+return -1;
+}
+if (!virFileIsExecutable(path)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("%s is not an executable"),
+   path);
+VIR_FREE(path);
+return -1;
+}
+*prgs[i].path = path;
 }
 }
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 12/21] tpm: Parse the capabilities supported by swtpm and swtpm_setup

2019-07-10 Thread Stefan Berger
Run 'swtpm socket --print-capabilities' and
'swtpm_setup --print-capabilities' to get the JSON object of the
features the programs are supporting and parse them into a bitmap.

Signed-off-by: Stefan Berger 
---
 src/conf/Makefile.inc.am |   6 ++
 src/conf/virtpm_conf.c   |  36 +++
 src/conf/virtpm_conf.h   |  36 +++
 src/libvirt_private.syms |   5 ++
 src/tpm/Makefile.inc.am  |   5 +-
 src/tpm/virtpm.c | 125 +--
 6 files changed, 208 insertions(+), 5 deletions(-)
 create mode 100644 src/conf/virtpm_conf.c
 create mode 100644 src/conf/virtpm_conf.h

diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index 08c7c9da7f..e42425fcc5 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -153,6 +153,11 @@ DEVICE_CONF_SOURCES = \
conf/device_conf.h \
$(NULL)
 
+TPM_CONF_SOURCES = \
+   conf/virtpm_conf.c \
+   conf/virtpm_conf.h \
+   $(NULL)
+
 CONF_SOURCES = \
$(NETDEV_CONF_SOURCES) \
$(DOMAIN_CONF_SOURCES) \
@@ -171,6 +176,7 @@ CONF_SOURCES = \
$(CPU_CONF_SOURCES) \
$(CHRDEV_CONF_SOURCES) \
$(DEVICE_CONF_SOURCES) \
+   $(TPM_CONF_SOURCES) \
$(NULL)
 
 noinst_LTLIBRARIES += libvirt_conf.la
diff --git a/src/conf/virtpm_conf.c b/src/conf/virtpm_conf.c
new file mode 100644
index 00..12e69e67b3
--- /dev/null
+++ b/src/conf/virtpm_conf.c
@@ -0,0 +1,36 @@
+/*
+ * virtpm_conf.c: vTPM XML processing
+ *
+ * Copyright (C) 2019 IBM Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * .
+ */
+
+#include 
+
+#include "virenum.h"
+#include "virtpm_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_ENUM_IMPL(virTPMSwtpmFeature,
+  VIR_TPM_SWTPM_FEATURE_LAST,
+  "cmdarg-pwd-fd",
+);
+
+VIR_ENUM_IMPL(virTPMSwtpmSetupFeature,
+  VIR_TPM_SWTPM_SETUP_FEATURE_LAST,
+  "cmdarg-pwdfile-fd",
+);
diff --git a/src/conf/virtpm_conf.h b/src/conf/virtpm_conf.h
new file mode 100644
index 00..73c6c67271
--- /dev/null
+++ b/src/conf/virtpm_conf.h
@@ -0,0 +1,36 @@
+/*
+ * virtpm_conf.h: vTPM XML processing
+ *
+ * Copyright (C) 2019 IBM Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * .
+ */
+
+#pragma once
+
+typedef enum {
+VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD,
+
+VIR_TPM_SWTPM_FEATURE_LAST
+} virTPMSwtpmFeature;
+
+typedef enum {
+VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD,
+
+VIR_TPM_SWTPM_SETUP_FEATURE_LAST
+} virTPMSwtpmSetupFeature;
+
+VIR_ENUM_DECL(virTPMSwtpmFeature);
+VIR_ENUM_DECL(virTPMSwtpmSetupFeature);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e33d7d9f14..d2045895a1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1236,6 +1236,11 @@ virStoragePoolObjVolumeGetNames;
 virStoragePoolObjVolumeListExport;
 
 
+# conf/virtpm_conf.h
+virTPMSwtpmFeatureTypeFromString;
+virTPMSwtpmSetupFeatureTypeFromString;
+
+
 # cpu/cpu.h
 cpuDecode;
 cpuEncode;
diff --git a/src/tpm/Makefile.inc.am b/src/tpm/Makefile.inc.am
index 1f5131bf34..d8a15c406c 100644
--- a/src/tpm/Makefile.inc.am
+++ b/src/tpm/Makefile.inc.am
@@ -12,6 +12,9 @@ EXTRA_DIST += \
 
 noinst_LTLIBRARIES += libvirt_tpm.la
 libvirt_la_BUILT_LIBADD += libvirt_tpm.la
-libvirt_tpm_la_CFLAGS = $(AM_CFLAGS)
+libvirt_tpm_la_CFLAGS = \
+   -I$(srcdir)/conf \
+   $(AM_CFLAGS) \
+   $(NULL)
 libvirt_tpm_la_LDFLAGS = $(AM_LDFLAGS)
 libvirt_tpm_la_SOURCES = $(TPM_UTIL_SOURCES)
diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c
index e4735f9c4d..5aec663025 100644
--- a/src/tpm/virtpm.c
+++ b/src/tpm/virtpm.c
@@ -27,6 +27,10 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virtpm.h"
+#include 

[libvirt] [PATCH v3 00/21] Add support for vTPM state encryption

2019-07-10 Thread 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:


  

  

  
  


The vTPM secret holding the passphrase looks like this:


  2c9ceaba-c6ef-4f38-86fd-6e3adb2df5cd
  vTPM passphrase example
  
vtpm_example
  



The swtpm v0.2 (upcoming) 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

Stefan Berger (21):
  secret: Add support for usage type vTPM, extend schema and test case
  tests: Add already existing test case tpm-emulator-tpm2
  util: Add VIR_STORAGE_ENCRYPTION_FORMAT_VTPM
  conf: Extend TPM XML parser with encryption support
  schema: Extend the TPM XML schema with support for encryption
  tests: Add test for TPM XML encryption parser and formatter
  tests: Add tests for QEMU command line generation with encrypted TPM
  tpm: Move virtpm.c from utils dir to own tpm dir
  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: Write a maximum of MAX_PIPE_FEED_BYTES into a pipe
  utils: Extend virCommandProcessIO to include the send buffers
  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 |  16 +
 docs/formatsecret.html.in |  61 +++-
 docs/schemas/domaincommon.rng |  30 ++
 docs/schemas/secret.rng   |  10 +
 include/libvirt/libvirt-secret.h  |   1 +
 po/POTFILES   |   2 +-
 src/Makefile.am   |   1 +
 src/conf/Makefile.inc.am  |   7 +
 src/conf/domain_conf.c|  96 +-
 src/conf/domain_conf.h|   5 +
 src/conf/secret_conf.c|  13 +
 src/conf/virtpm_conf.c|  36 ++
 src/conf/virtpm_conf.h|  36 ++
 src/libvirt_private.syms  |  21 +-
 src/qemu/Makefile.inc.am  |   1 +
 src/qemu/qemu_block.c |   1 +
 src/qemu/qemu_driver.c|  28 ++
 src/qemu/qemu_extdevice.c |   2 +-
 src/qemu/qemu_extdevice.h |   3 +
 src/qemu/qemu_tpm.c   | 196 ++-
 src/security/Makefile.inc.am  |   1 +
 src/tpm/Makefile.inc.am   |  20 ++
 src/tpm/virtpm.c  | 326 ++
 src/{util => tpm}/virtpm.h|   8 +
 src/util/Makefile.inc.am  |   2 -
 src/util/vircommand.c | 139 +++-
 src/util/vircommand.h |   5 +
 src/util/virsecret.c  |   2 +-
 src/util/virstorageencryption.c   |   2 +-
 src/util/virstorageencryption.h   |   1 +
 src/util/virtpm.c |  74 
 tests/Makefile.am |   1 +
 .../tpm-emulator-tpm2-enc.x86_64-latest.args  |  35 ++
 .../tpm-emulator-tpm2-enc.xml |  34 ++
 tests/qemuxml2argvtest.c  |   1 +
 .../tpm-emulator-tpm2-enc.xml |  38 ++
 tests/qemuxml2xmltest.c   |   2 +
 tests/secretxml2xmlin/usage-vtpm.xml  |   7 +
 tests/secretxml2xmltest.c |   1 +
 39 files changed, 1099 insertions(+), 166 deletions(-)
 create mode 100644 src/conf/virtpm_conf.c
 create mode 100644 src/conf/virtpm_conf.h
 create mode 100644 src/tpm/Makefile.inc.am
 create mode 100644 src/tpm/virtpm.c
 rename src/{util => tpm}/virtpm.h (77%)
 delete mode 100644 src/util/virtpm.c
 create 

[libvirt] [PATCH v3 17/21] tpm: Use fd to pass password to swtpm_setup and swtpm

2019-07-10 Thread Stefan Berger
Allow vTPM state encryption when swtpm_setup and swtpm support
passing a passphrase using a file descriptor.

This patch enables the encryption of the vTPM state only. It does
not encrypt the state during migration, so the destination secret
does not need to have the same password at this point.

Signed-off-by: Stefan Berger 
---
 src/libvirt_private.syms |   2 +
 src/qemu/qemu_tpm.c  | 103 ++-
 src/tpm/virtpm.c |  16 ++
 src/tpm/virtpm.h |   3 ++
 4 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3feb862fb4..804d244313 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1456,6 +1456,8 @@ virTPMEmulatorInit;
 virTPMGetSwtpm;
 virTPMGetSwtpmIoctl;
 virTPMGetSwtpmSetup;
+virTPMSwtpmCapsGet;
+virTPMSwtpmSetupCapsGet;
 
 
 # util/viralloc.h
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 2afa8db448..880b0642c6 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -43,6 +43,8 @@
 #include "dirname.h"
 #include "qemu_tpm.h"
 #include "virtpm.h"
+#include "secret_util.h"
+#include "virtpm_conf.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -372,6 +374,62 @@ qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
 return ret;
 }
 
+/*
+ * qemuTPMSetupEncryption
+ *
+ * @encryption: pointer to virStorageEncryption holding secret
+ * @cmd: the virCommand to transfer the secret to
+ *
+ * Returns file descriptor representing the read-end of a pipe.
+ * The passphrase can be read from this pipe. Returns < 0 in case
+ * of error.
+ *
+ * This function reads the passphrase and writes it into the
+ * write-end of a pipe so that the read-end of the pipe can be
+ * passed to the emulator for reading the passphrase from.
+ */
+static int
+qemuTPMSetupEncryption(virStorageEncryptionPtr encryption,
+   virCommandPtr cmd)
+{
+int ret = -1;
+int pipefd[2] = { -1, -1 };
+virConnectPtr conn;
+VIR_AUTOFREE(uint8_t *) secret = NULL;
+size_t secret_len;
+
+conn = virGetConnectSecret();
+if (!conn)
+return -1;
+
+if (virSecretGetSecretString(conn, >secrets[0]->seclookupdef,
+ VIR_SECRET_USAGE_TYPE_VTPM,
+ , _len) < 0)
+goto error;
+
+if (pipe(pipefd) == -1) {
+virReportSystemError(errno, "%s",
+ _("Unable to create pipe"));
+goto error;
+}
+
+if (virCommandSetSendBuffer(cmd, pipefd[1], secret, secret_len) < 0)
+goto error;
+
+secret = NULL;
+ret = pipefd[0];
+
+ cleanup:
+virObjectUnref(conn);
+
+return ret;
+
+ error:
+VIR_FORCE_CLOSE(pipefd[1]);
+VIR_FORCE_CLOSE(pipefd[0]);
+
+goto cleanup;
+}
 
 /*
  * qemuTPMEmulatorRunSetup
@@ -386,6 +444,7 @@ qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
  * @logfile: The file to write the log into; it must be writable
  *   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
  *
  * Setup the external swtpm by creating endorsement key and
  * certificates for it.
@@ -398,13 +457,15 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
 uid_t swtpm_user,
 gid_t swtpm_group,
 const char *logfile,
-const virDomainTPMVersion tpmversion)
+const virDomainTPMVersion tpmversion,
+virStorageEncryptionPtr encryption)
 {
 virCommandPtr cmd = NULL;
 int exitstatus;
 int ret = -1;
 char uuid[VIR_UUID_STRING_BUFLEN];
 char *vmid = NULL;
+VIR_AUTOCLOSE pwdfile_fd = -1;
 
 if (!privileged && tpmversion == VIR_DOMAIN_TPM_VERSION_1_2)
 return virFileWriteStr(logfile,
@@ -434,6 +495,23 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
 break;
 }
 
+if (encryption) {
+if (!virTPMSwtpmSetupCapsGet(
+VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD)) {
+virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+_("%s does not support passing a passphrase using a file "
+  "descriptor"), virTPMGetSwtpmSetup());
+goto cleanup;
+}
+if ((pwdfile_fd = qemuTPMSetupEncryption(encryption, cmd)) < 0)
+goto cleanup;
+
+virCommandAddArg(cmd, "--pwdfile-fd");
+virCommandAddArgFormat(cmd, "%d", pwdfile_fd);
+virCommandAddArgList(cmd, "--cipher", "aes-256-cbc", NULL);
+virCommandPassFD(cmd, pwdfile_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+pwdfile_fd = -1;
+}
 
 virCommandAddArgList(cmd,
  "--tpm-state", storagepath,
@@ -496,6 +574,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 virCommandPtr cmd = NULL;
 bool created = false;
 char 

[libvirt] [PATCH v3 02/21] tests: Add already existing test case tpm-emulator-tpm2

2019-07-10 Thread Stefan Berger
Add an already existing test case tpm-emulator-tpm2 to qemuxml2xmltest.c

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 tests/qemuxml2xmltest.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index a64b17ac28..a29958ae29 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -653,6 +653,7 @@ mymain(void)
 DO_TEST("tpm-passthrough", NONE);
 DO_TEST("tpm-passthrough-crb", NONE);
 DO_TEST("tpm-emulator", NONE);
+DO_TEST("tpm-emulator-tpm2", NONE);
 
 DO_TEST("metadata", NONE);
 DO_TEST("metadata-duplicate", NONE);
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 01/21] secret: Add support for usage type vTPM, extend schema and test case

2019-07-10 Thread Stefan Berger
Add support for usage type vTPM to secret.
Extend the schema for the Secret to support the vTPM usage type
and add a test case for parsing the Secret with usage type vTPM.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/schemas/secret.rng  | 10 ++
 include/libvirt/libvirt-secret.h |  1 +
 src/conf/secret_conf.c   | 13 +
 src/util/virsecret.c |  2 +-
 tests/secretxml2xmlin/usage-vtpm.xml |  7 +++
 tests/secretxml2xmltest.c|  1 +
 6 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 tests/secretxml2xmlin/usage-vtpm.xml

diff --git a/docs/schemas/secret.rng b/docs/schemas/secret.rng
index 1e94d66e48..e0add8a5e9 100644
--- a/docs/schemas/secret.rng
+++ b/docs/schemas/secret.rng
@@ -37,6 +37,7 @@
   
   
   
+  
   
 
   
@@ -81,4 +82,13 @@
 
   
 
+  
+
+  vtpm
+
+
+  
+
+  
+
 
diff --git a/include/libvirt/libvirt-secret.h b/include/libvirt/libvirt-secret.h
index 9a1065f0f3..e5aaac9450 100644
--- a/include/libvirt/libvirt-secret.h
+++ b/include/libvirt/libvirt-secret.h
@@ -43,6 +43,7 @@ typedef enum {
 VIR_SECRET_USAGE_TYPE_CEPH = 2,
 VIR_SECRET_USAGE_TYPE_ISCSI = 3,
 VIR_SECRET_USAGE_TYPE_TLS = 4,
+VIR_SECRET_USAGE_TYPE_VTPM = 5,
 
 # ifdef VIR_ENUM_SENTINELS
 VIR_SECRET_USAGE_TYPE_LAST
diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c
index 5b85a7c0be..b291339e77 100644
--- a/src/conf/secret_conf.c
+++ b/src/conf/secret_conf.c
@@ -110,6 +110,15 @@ virSecretDefParseUsage(xmlXPathContextPtr ctxt,
 }
 break;
 
+case VIR_SECRET_USAGE_TYPE_VTPM:
+def->usage_id = virXPathString("string(./usage/name)", ctxt);
+if (!def->usage_id) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("vTPM usage specified, but name is missing"));
+return -1;
+}
+break;
+
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected secret usage type %d"),
@@ -257,6 +266,10 @@ virSecretDefFormatUsage(virBufferPtr buf,
 virBufferEscapeString(buf, "%s\n", def->usage_id);
 break;
 
+case VIR_SECRET_USAGE_TYPE_VTPM:
+virBufferEscapeString(buf, "%s\n", def->usage_id);
+break;
+
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected secret usage type %d"),
diff --git a/src/util/virsecret.c b/src/util/virsecret.c
index 854dc72b06..7844a76a56 100644
--- a/src/util/virsecret.c
+++ b/src/util/virsecret.c
@@ -34,7 +34,7 @@ VIR_LOG_INIT("util.secret");
 
 VIR_ENUM_IMPL(virSecretUsage,
   VIR_SECRET_USAGE_TYPE_LAST,
-  "none", "volume", "ceph", "iscsi", "tls",
+  "none", "volume", "ceph", "iscsi", "tls", "vtpm",
 );
 
 void
diff --git a/tests/secretxml2xmlin/usage-vtpm.xml 
b/tests/secretxml2xmlin/usage-vtpm.xml
new file mode 100644
index 00..5baff3034d
--- /dev/null
+++ b/tests/secretxml2xmlin/usage-vtpm.xml
@@ -0,0 +1,7 @@
+
+  aa6c7af2-45a7-477c-85a2-fe86d9f2514e
+  vTPM secret
+  
+vTPMvTPMvTPM
+  
+
diff --git a/tests/secretxml2xmltest.c b/tests/secretxml2xmltest.c
index fd93703424..595583346a 100644
--- a/tests/secretxml2xmltest.c
+++ b/tests/secretxml2xmltest.c
@@ -80,6 +80,7 @@ mymain(void)
 DO_TEST("usage-ceph");
 DO_TEST("usage-iscsi");
 DO_TEST("usage-tls");
+DO_TEST("usage-vtpm");
 
 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 07/21] tests: Add tests for QEMU command line generation with encrypted TPM

2019-07-10 Thread Stefan Berger
The QEMU command line does not change when TPM state is encrypted
compared to when it is plain.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 .../tpm-emulator-tpm2-enc.x86_64-latest.args  | 35 +++
 tests/qemuxml2argvtest.c  |  1 +
 2 files changed, 36 insertions(+)
 create mode 100644 
tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args

diff --git a/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args 
b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args
new file mode 100644
index 00..3c8dc8e483
--- /dev/null
+++ b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args
@@ -0,0 +1,35 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-TPM-VM \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-TPM-VM/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-TPM-VM/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-TPM-VM/.config \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=TPM-VM,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-TPM-VM/master-key.aes \
+-machine pc-i440fx-2.12,accel=tcg,usb=off,dump-guest-core=off \
+-m 2048 \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid 11d7cd22-da89-3094-6212-079a48a309a1 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot menu=on,strict=on \
+-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
+-tpmdev emulator,id=tpm-tpm0,chardev=chrtpm \
+-chardev socket,id=chrtpm,path=/dev/test \
+-device tpm-tis,tpmdev=tpm-tpm0,id=tpm0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 91ca35d469..9c02cac8fc 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2082,6 +2082,7 @@ mymain(void)
 QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, 
QEMU_CAPS_DEVICE_TPM_TIS);
 DO_TEST_CAPS_LATEST("tpm-emulator");
 DO_TEST_CAPS_LATEST("tpm-emulator-tpm2");
+DO_TEST_CAPS_LATEST("tpm-emulator-tpm2-enc");
 
 DO_TEST_PARSE_ERROR("pci-domain-invalid", NONE);
 DO_TEST_PARSE_ERROR("pci-bus-invalid", NONE);
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 13/21] utils: Implement function to pass a buffer to send via a fd to virCommand

2019-07-10 Thread Stefan Berger
Implement virCommandSetSendBuffer() that allows the caller to pass a
file descriptor and buffer to virCommand. virCommand will write the
buffer into the file descriptor. That file descriptor could be the
write end of a pipe or one of the file descriptors of a socketpair.
The other file descriptor should be passed to the launched process to
read the data from.

Only implement the function to allocate memory for send buffers
and to free them later on.

Signed-off-by: Stefan Berger 
---
 src/libvirt_private.syms |  1 +
 src/util/vircommand.c| 62 
 src/util/vircommand.h|  5 
 3 files changed, 68 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d2045895a1..3feb862fb4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1734,6 +1734,7 @@ virCommandSetOutputBuffer;
 virCommandSetOutputFD;
 virCommandSetPidFile;
 virCommandSetPreExecHook;
+virCommandSetSendBuffer;
 virCommandSetSELinuxLabel;
 virCommandSetUID;
 virCommandSetUmask;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 8695c98d1b..e32377497b 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -77,6 +77,16 @@ struct _virCommandFD {
 unsigned int flags;
 };
 
+typedef struct _virCommandSendBuffer virCommandSendBuffer;
+typedef virCommandSendBuffer *virCommandSendBufferPtr;
+
+struct _virCommandSendBuffer {
+int fd;
+unsigned char *buffer;
+size_t buflen;
+off_t offset;
+};
+
 struct _virCommand {
 int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
 
@@ -136,6 +146,9 @@ struct _virCommand {
 char *appArmorProfile;
 #endif
 int mask;
+
+virCommandSendBufferPtr sendBuffers;
+size_t numSendBuffers;
 };
 
 /* See virCommandSetDryRun for description for this variable */
@@ -1741,6 +1754,53 @@ virCommandSetWorkingDirectory(virCommandPtr cmd, const 
char *pwd)
 }
 
 
+static void
+virCommandFreeSendBuffers(virCommandPtr cmd)
+{
+size_t i;
+
+for (i = 0; i < cmd->numSendBuffers; i++) {
+VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+VIR_FREE(cmd->sendBuffers[i].buffer);
+}
+VIR_FREE(cmd->sendBuffers);
+}
+
+
+/**
+ * virCommandSetSendBuffer
+ * @cmd: the command to modify
+ *
+ * Pass a buffer to virCommand that will be written into the
+ * given file descriptor. The buffer will be freed automatically
+ * and the file descriptor closed.
+ */
+int
+virCommandSetSendBuffer(virCommandPtr cmd,
+int fd,
+unsigned char *buffer, size_t buflen)
+{
+size_t i = cmd->numSendBuffers;
+
+if (!cmd || cmd->has_error)
+return -1;
+
+if (VIR_REALLOC_N(cmd->sendBuffers, i + 1) < 0) {
+cmd->has_error = ENOMEM;
+return -1;
+}
+
+cmd->sendBuffers[i].fd = fd;
+cmd->sendBuffers[i].buffer = buffer;
+cmd->sendBuffers[i].buflen = buflen;
+cmd->sendBuffers[i].offset = 0;
+
+cmd->numSendBuffers++;
+
+return 0;
+}
+
+
 /**
  * virCommandSetInputBuffer:
  * @cmd: the command to modify
@@ -2880,6 +2940,8 @@ virCommandFree(virCommandPtr cmd)
 VIR_FREE(cmd->appArmorProfile);
 #endif
 
+virCommandFreeSendBuffers(cmd);
+
 VIR_FREE(cmd);
 }
 
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index c9a8d3c41c..716e84af3d 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -148,6 +148,11 @@ void virCommandAddArgList(virCommandPtr cmd,
 void virCommandSetWorkingDirectory(virCommandPtr cmd,
const char *pwd) ATTRIBUTE_NONNULL(2);
 
+int virCommandSetSendBuffer(virCommandPtr cmd,
+int fd,
+unsigned char *buffer, size_t buflen)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
+
 void virCommandSetInputBuffer(virCommandPtr cmd,
   const char *inbuf) ATTRIBUTE_NONNULL(2);
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 08/21] tpm: Move virtpm.c from utils dir to own tpm dir

2019-07-10 Thread Stefan Berger
Move virtpm.c from utils dir to its own tpm dir. This change
is mostly driven by the later introduction of virtpm_conf.c where
the define function like XYZTypeFromString() that we cannot
include from utils dir.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 po/POTFILES  |  2 +-
 src/Makefile.am  |  1 +
 src/conf/Makefile.inc.am |  1 +
 src/libvirt_private.syms |  8 
 src/qemu/Makefile.inc.am |  1 +
 src/security/Makefile.inc.am |  1 +
 src/tpm/Makefile.inc.am  | 17 +
 src/{util => tpm}/virtpm.c   |  0
 src/{util => tpm}/virtpm.h   |  0
 src/util/Makefile.inc.am |  2 --
 tests/Makefile.am|  1 +
 11 files changed, 27 insertions(+), 7 deletions(-)
 create mode 100644 src/tpm/Makefile.inc.am
 rename src/{util => tpm}/virtpm.c (100%)
 rename src/{util => tpm}/virtpm.h (100%)

diff --git a/po/POTFILES b/po/POTFILES
index 8017712ff4..e3c1a8edae 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -188,6 +188,7 @@ src/storage/storage_backend_zfs.c
 src/storage/storage_driver.c
 src/storage/storage_util.c
 src/test/test_driver.c
+src/tpm/virtpm.c
 src/util/iohelper.c
 src/util/viralloc.c
 src/util/virarptable.c
@@ -266,7 +267,6 @@ src/util/virsysinfo.c
 src/util/virthreadjob.c
 src/util/virthreadpool.c
 src/util/virtime.c
-src/util/virtpm.c
 src/util/virtypedparam.c
 src/util/viruri.c
 src/util/virusb.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b562dc250..5f7c9001fe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -122,6 +122,7 @@ include node_device/Makefile.inc.am
 include secret/Makefile.inc.am
 include storage/Makefile.inc.am
 include remote/Makefile.inc.am
+include tpm/Makefile.inc.am
 
 
 THREAD_LIBS = $(LIB_PTHREAD) $(LTLIBMULTITHREAD)
diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index 6b52ba674b..08c7c9da7f 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -178,6 +178,7 @@ libvirt_la_BUILT_LIBADD += libvirt_conf.la
 libvirt_conf_la_SOURCES = $(CONF_SOURCES)
 libvirt_conf_la_CFLAGS = \
-I$(srcdir)/conf \
+   -I$(srcdir)/tpm \
$(AM_CFLAGS) \
$(NULL)
 libvirt_conf_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 34937adc5d..e29007cab1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1445,6 +1445,10 @@ virSecurityManagerTransactionStart;
 virSecurityManagerVerify;
 
 
+# tpm/virtpm.h
+virTPMCreateCancelPath;
+
+
 # util/viralloc.h
 virAlloc;
 virAllocN;
@@ -3175,10 +3179,6 @@ virTimeStringThen;
 virTimeStringThenRaw;
 
 
-# util/virtpm.h
-virTPMCreateCancelPath;
-
-
 # util/virtypedparam.h
 virTypedParameterAssign;
 virTypedParameterAssignFromStr;
diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am
index 254ba07dc0..72b28e731d 100644
--- a/src/qemu/Makefile.inc.am
+++ b/src/qemu/Makefile.inc.am
@@ -84,6 +84,7 @@ libvirt_driver_qemu_impl_la_CFLAGS = \
-I$(srcdir)/access \
-I$(srcdir)/conf \
-I$(srcdir)/secret \
+   -I$(srcdir)/tpm \
$(AM_CFLAGS) \
$(NULL)
 libvirt_driver_qemu_impl_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/security/Makefile.inc.am b/src/security/Makefile.inc.am
index 64e0f46857..3e110596dc 100644
--- a/src/security/Makefile.inc.am
+++ b/src/security/Makefile.inc.am
@@ -47,6 +47,7 @@ noinst_LTLIBRARIES += libvirt_security_manager.la
 libvirt_la_BUILT_LIBADD += libvirt_security_manager.la
 libvirt_security_manager_la_CFLAGS = \
-I$(srcdir)/conf \
+   -I$(srcdir)/tpm \
$(AM_CFLAGS) \
$(NULL)
 libvirt_security_manager_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/tpm/Makefile.inc.am b/src/tpm/Makefile.inc.am
new file mode 100644
index 00..1f5131bf34
--- /dev/null
+++ b/src/tpm/Makefile.inc.am
@@ -0,0 +1,17 @@
+# vim: filetype=automake
+
+TPM_UTIL_SOURCES = \
+   tpm/virtpm.h \
+   tpm/virtpm.c \
+   $(NULL)
+
+
+EXTRA_DIST += \
+   $(TPM_UTIL_SOURCES) \
+   $(NULL)
+
+noinst_LTLIBRARIES += libvirt_tpm.la
+libvirt_la_BUILT_LIBADD += libvirt_tpm.la
+libvirt_tpm_la_CFLAGS = $(AM_CFLAGS)
+libvirt_tpm_la_LDFLAGS = $(AM_LDFLAGS)
+libvirt_tpm_la_SOURCES = $(TPM_UTIL_SOURCES)
diff --git a/src/util/virtpm.c b/src/tpm/virtpm.c
similarity index 100%
rename from src/util/virtpm.c
rename to src/tpm/virtpm.c
diff --git a/src/util/virtpm.h b/src/tpm/virtpm.h
similarity index 100%
rename from src/util/virtpm.h
rename to src/tpm/virtpm.h
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
index c757f5a6ae..8b2ff6be6b 100644
--- a/src/util/Makefile.inc.am
+++ b/src/util/Makefile.inc.am
@@ -205,8 +205,6 @@ UTIL_SOURCES = \
util/virthreadpool.h \
util/virtime.c \
util/virtime.h \
-   util/virtpm.c \
-   util/virtpm.h \
util/virtypedparam.c \
util/virtypedparam.h \
util/virusb.c \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 115afa1c1a..ffc9f7f92e 100644
--- 

[libvirt] [PATCH v3 19/21] tpm: Check TPM XML device configuration changes after edit

2019-07-10 Thread Stefan Berger
Since swtpm does not support getting started once it was created
with encrypted enabled, we don't allow encryption to be removed.
Similarly, we do not allow encrypted to be added once swtpm has
run.

Signed-off-by: Stefan Berger 
---
 src/conf/domain_conf.c| 56 +++
 src/conf/domain_conf.h|  4 +++
 src/libvirt_private.syms  |  1 +
 src/qemu/qemu_driver.c| 28 
 src/qemu/qemu_extdevice.c |  2 +-
 src/qemu/qemu_extdevice.h |  3 +++
 6 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index df6238c299..dba8da0e5d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31435,3 +31435,59 @@ virDomainGraphicsNeedsAutoRenderNode(const 
virDomainGraphicsDef *graphics)
 
 return true;
 }
+
+
+static int
+virDomainCheckTPMChanges(virDomainDefPtr def,
+ virDomainDefPtr newDef)
+{
+bool oldEnc, newEnc;
+
+if (!def->tpm)
+return 0;
+
+switch (def->tpm->type) {
+case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+if (virFileExists(def->tpm->data.emulator.storagepath)) {
+/* VM has been started */
+/* Once a VM was started with an encrypted state we allow
+ * less configuration changes.
+ */
+oldEnc = def->tpm->data.emulator.encryption;
+if (oldEnc && def->tpm->type != newDef->tpm->type) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Changing the type of TPM is not allowed"));
+return -1;
+}
+if (oldEnc && !newDef->tpm) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Removing an encrypted TPM is not allowed"));
+return -1;
+}
+newEnc = newDef->tpm->data.emulator.encryption;
+if (oldEnc != newEnc) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("TPM state encryption cannot be changed "
+ "once VM was started"));
+return -1;
+}
+}
+break;
+case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+case VIR_DOMAIN_TPM_TYPE_LAST:
+break;
+}
+
+return 0;
+}
+
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def,
+virDomainDefPtr newDef)
+{
+if (!def || !newDef)
+return 0;
+
+return virDomainCheckTPMChanges(def, newDef);
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a03986623a..a61faa7d57 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3623,3 +3623,7 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef 
*graphics);
 
 bool
 virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics);
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def, virDomainDefPtr newDef)
+ATTRIBUTE_NONNULL(2);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 804d244313..d8e99ad566 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -205,6 +205,7 @@ virDomainBootTypeFromString;
 virDomainBootTypeToString;
 virDomainCapabilitiesPolicyTypeToString;
 virDomainCapsFeatureTypeToString;
+virDomainCheckDeviceChanges;
 virDomainChrConsoleTargetTypeFromString;
 virDomainChrConsoleTargetTypeToString;
 virDomainChrDefForeach;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ef2e980216..8f224582b6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -52,6 +52,7 @@
 #include "qemu_migration_params.h"
 #include "qemu_blockjob.h"
 #include "qemu_security.h"
+#include "qemu_extdevice.h"
 
 #include "virerror.h"
 #include "virlog.h"
@@ -7568,6 +7569,30 @@ qemuDomainCreate(virDomainPtr dom)
 return qemuDomainCreateWithFlags(dom, 0);
 }
 
+static int
+qemuDomainCheckDeviceChanges(virQEMUDriverPtr driver,
+ virDomainDefPtr def)
+{
+virDomainObjPtr vm;
+int ret;
+
+vm = virDomainObjListFindByUUID(driver->domains, def->uuid);
+if (!vm)
+return 0;
+
+if (qemuExtDevicesInitPaths(driver, vm->def) < 0) {
+ret = -1;
+goto cleanup;
+}
+
+ret = virDomainCheckDeviceChanges(vm->def, def);
+
+ cleanup:
+virDomainObjEndAPI();
+
+return ret;
+}
+
 static virDomainPtr
 qemuDomainDefineXMLFlags(virConnectPtr conn,
  const char *xml,
@@ -7604,6 +7629,9 @@ qemuDomainDefineXMLFlags(virConnectPtr conn,
 if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
 goto cleanup;
 
+if (qemuDomainCheckDeviceChanges(driver, def) < 0)
+goto cleanup;
+
 if (!(vm = virDomainObjListAdd(driver->domains, def,
driver->xmlopt,
0, )))
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index a21caefaba..e576bca165 100644
--- 

[libvirt] [PATCH v3 21/21] docs: Extend TPM docs with new encryption element

2019-07-10 Thread Stefan Berger
Describe the encryption element in the TPM's domain XML.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/formatdomain.html.in | 16 
 1 file changed, 16 insertions(+)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a7a6ec32a5..9fa391748e 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8212,6 +8212,9 @@ qemu-kvm -net nic,model=? /dev/null
   TPM functionality for each VM. QEMU talks to it over a Unix socket. With
   the emulator device type each guest gets its own private TPM.
   'emulator' since 4.5.0
+  The state of the TPM emulator can be encrypted by providing an
+  encryption element.
+  'encryption' since 5.6.0
 
 
  Example: usage of the TPM Emulator
@@ -8221,6 +8224,9 @@ qemu-kvm -net nic,model=? /dev/null
   devices
 tpm model='tpm-tis'
   backend type='emulator' version='2.0'
+encryption format='vtpm'
+  secret type='passphrase' usage='VTPM_example'/
+/encryption
   /backend
 /tpm
   /devices
@@ -8283,6 +8289,16 @@ qemu-kvm -net nic,model=? /dev/null
   '2.0' : creates a TPM 2.0
 
   
+  encryption
+  
+
+  The encryption element allows the state of a TPM 
emulator
+  to be encrypted. The format attribute must be 
vtpm.
+  The secret element must reference a secret object using
+  either its usage or uuid. The 
type
+  attribute must be set to passphrase.
+
+  
 
 
 NVRAM device
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 16/21] utils: Extend virCommandProcessIO to include the send buffers

2019-07-10 Thread Stefan Berger
Extend virCommandProcessIO to include the send buffers in the poll
loop.

Signed-off-by: Stefan Berger 
---
 src/util/vircommand.c | 70 ++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 0e367eeeab..bb11a76118 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -1803,6 +1803,69 @@ virCommandSetSendBuffer(virCommandPtr cmd,
 }
 
 
+static int
+virCommandGetNumSendBuffers(virCommandPtr cmd)
+{
+return cmd->numSendBuffers;
+}
+
+
+static int
+virCommandSendBuffersFillPollfd(virCommandPtr cmd,
+struct pollfd *fds,
+int startidx)
+{
+size_t i, j;
+
+for (i = 0, j = 0; i < cmd->numSendBuffers; i++) {
+if (cmd->sendBuffers[i].fd >= 0) {
+fds[startidx + j].fd = cmd->sendBuffers[i].fd;
+fds[startidx + j].events = POLLOUT;
+fds[startidx + j].revents = 0;
+j++;
+}
+}
+
+return j;
+}
+
+
+static int
+virCommandSendBuffersHandlePoll(virCommandPtr cmd,
+struct pollfd *fds)
+{
+size_t i;
+int done;
+
+for (i = 0; i < cmd->numSendBuffers; i++) {
+if (fds->fd == cmd->sendBuffers[i].fd)
+break;
+}
+if (i == cmd->numSendBuffers)
+return 0;
+
+done = write(fds->fd,
+ cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset,
+ MIN(cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset,
+ MAX_PIPE_FEED_BYTES));
+if (done < 0) {
+if (errno == EPIPE) {
+VIR_DEBUG("child closed PIPE early, ignoring EPIPE "
+  "on fd %d", cmd->sendBuffers[i].fd);
+VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+} else if (errno != EINTR && errno != EAGAIN) {
+virReportSystemError(errno, "%s",
+ _("unable to write to child input"));
+return -1;
+}
+} else {
+cmd->sendBuffers[i].offset += done;
+if (cmd->sendBuffers[i].offset == cmd->sendBuffers[i].buflen)
+VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+}
+return 0;
+}
+
 /**
  * virCommandSetInputBuffer:
  * @cmd: the command to modify
@@ -2157,7 +2220,7 @@ virCommandProcessIO(virCommandPtr cmd)
 goto cleanup;
 ret = -1;
 
-if (VIR_ALLOC_N(fds, 3) < 0)
+if (VIR_ALLOC_N(fds, 3 + virCommandGetNumSendBuffers(cmd)) < 0)
 goto cleanup;
 
 for (;;) {
@@ -2183,6 +2246,8 @@ virCommandProcessIO(virCommandPtr cmd)
 nfds++;
 }
 
+nfds += virCommandSendBuffersFillPollfd(cmd, fds, nfds);
+
 if (nfds == 0)
 break;
 
@@ -2255,6 +2320,9 @@ virCommandProcessIO(virCommandPtr cmd)
 if (inoff == inlen)
 VIR_FORCE_CLOSE(cmd->inpipe);
 }
+} else if (fds[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
+if (virCommandSendBuffersHandlePoll(cmd, [i]) < 0)
+goto cleanup;
 }
 }
 }
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 03/21] util: Add VIR_STORAGE_ENCRYPTION_FORMAT_VTPM

2019-07-10 Thread Stefan Berger
Add VIR_STORAGE_ENCRYPTION_FORMAT_VTPM with string 'vtpm' for
support of encrypting vTPM storage.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/qemu/qemu_block.c   | 1 +
 src/util/virstorageencryption.c | 2 +-
 src/util/virstorageencryption.h | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 0a6522577d..c3296c36f5 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1184,6 +1184,7 @@ qemuBlockStorageSourceGetCryptoProps(virStorageSourcePtr 
src,
 encformat = "luks";
 break;
 
+case VIR_STORAGE_ENCRYPTION_FORMAT_VTPM:
 case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT:
 case VIR_STORAGE_ENCRYPTION_FORMAT_LAST:
 default:
diff --git a/src/util/virstorageencryption.c b/src/util/virstorageencryption.c
index 49df7fddd8..4c7356d47a 100644
--- a/src/util/virstorageencryption.c
+++ b/src/util/virstorageencryption.c
@@ -44,7 +44,7 @@ VIR_ENUM_IMPL(virStorageEncryptionSecret,
 
 VIR_ENUM_IMPL(virStorageEncryptionFormat,
   VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
-  "default", "qcow", "luks",
+  "default", "qcow", "luks", "vtpm",
 );
 
 static void
diff --git a/src/util/virstorageencryption.h b/src/util/virstorageencryption.h
index 3e5485d88b..29bd00056c 100644
--- a/src/util/virstorageencryption.h
+++ b/src/util/virstorageencryption.h
@@ -59,6 +59,7 @@ typedef enum {
 VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0,
 VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */
 VIR_STORAGE_ENCRYPTION_FORMAT_LUKS,
+VIR_STORAGE_ENCRYPTION_FORMAT_VTPM,
 
 VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
 } virStorageEncryptionFormatType;
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 20/21] docs: Extend Secret XML documentation with vtpm usage type

2019-07-10 Thread Stefan Berger
Extend the Secret XML documentation with vtpm usage type.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/formatsecret.html.in | 61 +--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/docs/formatsecret.html.in b/docs/formatsecret.html.in
index defbe71731..8d0630a7c3 100644
--- a/docs/formatsecret.html.in
+++ b/docs/formatsecret.html.in
@@ -42,8 +42,8 @@
 Specifies what this secret is used for.  A mandatory
 type attribute specifies the usage category, currently
 only volume, ceph, iscsi,
-and tls are defined. Specific usage categories
-are described below.
+tls, and vtpm are defined. Specific usage
+categories are described below.
   
 
 
@@ -322,6 +322,63 @@ Secret 718c71bd-67b5-4a2b-87ec-a24e8ca200dc created
 
 # MYSECRET=`printf %s "letmein" | base64`
 # virsh secret-set-value 718c71bd-67b5-4a2b-87ec-a24e8ca200dc $MYSECRET
+Secret value set
+
+
+
+Usage type "vtpm"
+
+
+  This secret is associated with a virtualized TPM (vTPM) and serves
+  as a passphrase for deriving a key from for encrypting the state
+  of the vTPM.
+  The usage type='vtpm' element must contain
+  a single name element that specifies a usage name
+  for the secret.  The vTPM secret can then be used by UUID or by
+  this usage name via the encryption element of
+  a tpm when using an
+  emulator.
+  Since 5.6.0. The following is an example
+  of the steps to be taken.  First create a vtpm-secret.xml file:
+
+
+# cat vtpm-secret.xml
+secret ephemeral='no' private='yes'
+   descriptionsample vTPM secret/description
+   usage type='vtpm'
+  nameVTPM_example/name
+   /usage
+/secret
+
+# virsh secret-define vtpm-secret.xml
+Secret 6dd3e4a5-1d76-44ce-961f-f119f5aad935 created
+
+# virsh secret-list
+ UUID   Usage
+
+ 6dd3e4a5-1d76-44ce-961f-f119f5aad935   vtpm VTPM_example
+
+#
+
+
+
+
+  A secret may also be defined via the
+  
+   virSecretDefineXML API.
+
+  Once the secret is defined, a secret value will need to be set. The
+  secret would be the passphrase used to decrypt the vTPM state.
+  The following is a simple example of using
+  virsh secret-set-value to set the secret value. The
+  
+  virSecretSetValue API may also be used to set
+  a more secure secret without using printable/readable characters.
+
+
+
+# MYSECRET=`printf %s "open sesame" | base64`
+# virsh secret-set-value 6dd3e4a5-1d76-44ce-961f-f119f5aad935 $MYSECRET
 Secret value set
 
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 15/21] utils: Write a maximum of MAX_PIPE_FEED_BYTES into a pipe

2019-07-10 Thread Stefan Berger
To avoid blocking on a write on a pipe that the receiving process
does not read from, write only MAX_PIPE_FEED_BYTES into the pipe
so that we can serve other pipes as well.

Signed-off-by: Stefan Berger 
---
 src/util/vircommand.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 898ee0df45..0e367eeeab 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -86,6 +86,8 @@ struct _virCommandSendBuffer {
 size_t buflen;
 off_t offset;
 };
+/* max. number of bytes we write to pipe to avoid blocking on it */
+#define MAX_PIPE_FEED_BYTES 1024
 
 struct _virCommand {
 int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
@@ -2237,7 +2239,7 @@ virCommandProcessIO(virCommandPtr cmd)
 int done;
 
 done = write(cmd->inpipe, cmd->inbuf + inoff,
- inlen - inoff);
+ MIN(inlen - inoff, MAX_PIPE_FEED_BYTES));
 if (done < 0) {
 if (errno == EPIPE) {
 VIR_DEBUG("child closed stdin early, ignoring EPIPE "
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2 13/21] utils: Implement function to pass a buffer to send via a fd to virCommand

2019-07-10 Thread Marc-André Lureau
On Wed, Jul 10, 2019 at 10:12 PM Stefan Berger
 wrote:
>
> Implement virCommandSetSendBuffer() that allows the caller to pass a
> file descriptor and buffer to virCommand. virCommand will write the
> buffer into the file descriptor. That file descriptor could be the
> write end of a pipe or one of the file descriptors of a socketpair.
> The other file descriptor should be passed to the launched process to
> read the data from.
>
> Only implement the function to allocate memory for send buffers
> and to free them later on.
>
> Signed-off-by: Stefan Berger 

that looks fine,
Reviewed-by: Marc-André Lureau 

> ---
>  src/libvirt_private.syms |  1 +
>  src/util/vircommand.c| 62 
>  src/util/vircommand.h|  5 
>  3 files changed, 68 insertions(+)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index d2045895a1..3feb862fb4 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1734,6 +1734,7 @@ virCommandSetOutputBuffer;
>  virCommandSetOutputFD;
>  virCommandSetPidFile;
>  virCommandSetPreExecHook;
> +virCommandSetSendBuffer;
>  virCommandSetSELinuxLabel;
>  virCommandSetUID;
>  virCommandSetUmask;
> diff --git a/src/util/vircommand.c b/src/util/vircommand.c
> index 8695c98d1b..e32377497b 100644
> --- a/src/util/vircommand.c
> +++ b/src/util/vircommand.c
> @@ -77,6 +77,16 @@ struct _virCommandFD {
>  unsigned int flags;
>  };
>
> +typedef struct _virCommandSendBuffer virCommandSendBuffer;
> +typedef virCommandSendBuffer *virCommandSendBufferPtr;
> +
> +struct _virCommandSendBuffer {
> +int fd;
> +unsigned char *buffer;
> +size_t buflen;
> +off_t offset;
> +};
> +
>  struct _virCommand {
>  int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
>
> @@ -136,6 +146,9 @@ struct _virCommand {
>  char *appArmorProfile;
>  #endif
>  int mask;
> +
> +virCommandSendBufferPtr sendBuffers;
> +size_t numSendBuffers;
>  };
>
>  /* See virCommandSetDryRun for description for this variable */
> @@ -1741,6 +1754,53 @@ virCommandSetWorkingDirectory(virCommandPtr cmd, const 
> char *pwd)
>  }
>
>
> +static void
> +virCommandFreeSendBuffers(virCommandPtr cmd)
> +{
> +size_t i;
> +
> +for (i = 0; i < cmd->numSendBuffers; i++) {
> +VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
> +VIR_FREE(cmd->sendBuffers[i].buffer);
> +}
> +VIR_FREE(cmd->sendBuffers);
> +}
> +
> +
> +/**
> + * virCommandSetSendBuffer
> + * @cmd: the command to modify
> + *
> + * Pass a buffer to virCommand that will be written into the
> + * given file descriptor. The buffer will be freed automatically
> + * and the file descriptor closed.
> + */
> +int
> +virCommandSetSendBuffer(virCommandPtr cmd,
> +int fd,
> +unsigned char *buffer, size_t buflen)
> +{
> +size_t i = cmd->numSendBuffers;
> +
> +if (!cmd || cmd->has_error)
> +return -1;
> +
> +if (VIR_REALLOC_N(cmd->sendBuffers, i + 1) < 0) {
> +cmd->has_error = ENOMEM;
> +return -1;
> +}
> +
> +cmd->sendBuffers[i].fd = fd;
> +cmd->sendBuffers[i].buffer = buffer;
> +cmd->sendBuffers[i].buflen = buflen;
> +cmd->sendBuffers[i].offset = 0;
> +
> +cmd->numSendBuffers++;
> +
> +return 0;
> +}
> +
> +
>  /**
>   * virCommandSetInputBuffer:
>   * @cmd: the command to modify
> @@ -2880,6 +2940,8 @@ virCommandFree(virCommandPtr cmd)
>  VIR_FREE(cmd->appArmorProfile);
>  #endif
>
> +virCommandFreeSendBuffers(cmd);
> +
>  VIR_FREE(cmd);
>  }
>
> diff --git a/src/util/vircommand.h b/src/util/vircommand.h
> index c9a8d3c41c..716e84af3d 100644
> --- a/src/util/vircommand.h
> +++ b/src/util/vircommand.h
> @@ -148,6 +148,11 @@ void virCommandAddArgList(virCommandPtr cmd,
>  void virCommandSetWorkingDirectory(virCommandPtr cmd,
> const char *pwd) ATTRIBUTE_NONNULL(2);
>
> +int virCommandSetSendBuffer(virCommandPtr cmd,
> +int fd,
> +unsigned char *buffer, size_t buflen)
> +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
> +
>  void virCommandSetInputBuffer(virCommandPtr cmd,
>const char *inbuf) ATTRIBUTE_NONNULL(2);
>
> --
> 2.20.1
>

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 5/5] qemu: implement virDomainGetGuestUsers

2019-07-10 Thread Jonathon Jongsma
Signed-off-by: Jonathon Jongsma 
---
 src/qemu/qemu_driver.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5a75f23981..27fcdd393d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -22201,6 +22201,43 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
 return ret;
 }
 
+static int
+qemuDomainGetGuestUsers(virDomainPtr dom,
+virDomainUserInfoPtr **info,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = dom->conn->privateData;
+virDomainObjPtr vm = NULL;
+qemuAgentPtr agent;
+int ret = -1;
+
+virCheckFlags(0, ret);
+
+if (!(vm = qemuDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetGuestUsersEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_QUERY) < 0)
+goto cleanup;
+
+if (!qemuDomainAgentAvailable(vm, true))
+goto endjob;
+
+agent = qemuDomainObjEnterAgent(vm);
+ret = qemuAgentGetUsers(agent, info);
+qemuDomainObjExitAgent(vm, agent);
+
+ endjob:
+qemuDomainObjEndAgentJob(vm);
+
+ cleanup:
+virDomainObjEndAPI();
+return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -22428,6 +22465,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 
*/
 .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
 .domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
+.domainGetGuestUsers = qemuDomainGetGuestUsers, /* 5.6.0 */
 };
 
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/5] remote: implement remote protocol for virDomainGetGuestUsers

2019-07-10 Thread Jonathon Jongsma
Add daemon and client code to serialize/deserialize virDomainUserInfo

Signed-off-by: Jonathon Jongsma 
---
 src/remote/remote_daemon_dispatch.c | 89 +
 src/remote/remote_driver.c  | 82 +-
 src/remote/remote_protocol.x| 26 -
 src/remote_protocol-structs | 17 ++
 4 files changed, 212 insertions(+), 2 deletions(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 856c5e48e7..05c4b11b11 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -7465,3 +7465,92 @@ remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr 
errors,
 }
 return -1;
 }
+
+static int
+remoteDispatchDomainGetGuestUsers(virNetServerPtr server ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client,
+  virNetMessagePtr msg ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  remote_domain_get_guest_users_args *args,
+  remote_domain_get_guest_users_ret *ret)
+{
+int rv = -1;
+size_t i;
+struct daemonClientPrivate *priv = 
virNetServerClientGetPrivateData(client);
+virDomainUserInfoPtr *info = NULL;
+virDomainPtr dom = NULL;
+remote_domain_userinfo *dst;
+int ninfo = 0;
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if ((ninfo = virDomainGetGuestUsers(dom, , args->flags)) < 0)
+goto cleanup;
+
+if (ninfo > REMOTE_DOMAIN_GUEST_USERS_MAX) {
+virReportError(VIR_ERR_RPC,
+   _("Too many users in userinfo: %d for limit %d"),
+   ninfo, REMOTE_DOMAIN_GUEST_USERS_MAX);
+goto cleanup;
+}
+
+if (ninfo) {
+if (VIR_ALLOC_N(ret->info.info_val, ninfo) < 0)
+goto cleanup;
+
+ret->info.info_len = ninfo;
+
+for (i = 0; i < ninfo; i++) {
+dst = >info.info_val[i];
+if (VIR_STRDUP(dst->user, info[i]->user) < 0)
+goto cleanup;
+
+if (info[i]->domain) {
+if (VIR_ALLOC(*dst->domain) < 0)
+goto cleanup;
+if (VIR_STRDUP(*dst->domain, info[i]->domain) < 0)
+goto cleanup;
+}
+
+dst->login_time = info[i]->loginTime;
+
+}
+
+} else {
+ret->info.info_len = 0;
+ret->info.info_val = NULL;
+}
+
+ret->ret = ninfo;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0) {
+virNetMessageSaveError(rerr);
+
+if (ret->info.info_val && ninfo > 0) {
+for (i = 0; i < ninfo; i++) {
+dst = >info.info_val[i];
+VIR_FREE(dst->user);
+if(dst->domain)
+VIR_FREE(*dst->domain);
+VIR_FREE(dst->domain);
+}
+VIR_FREE(ret->info.info_val);
+}
+}
+virObjectUnref(dom);
+if (ninfo >= 0)
+for (i = 0; i < ninfo; i++)
+virDomainUserInfoFree(info[i]);
+VIR_FREE(info);
+
+return rv;
+}
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 925ada1cac..86e2071d3b 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8167,6 +8167,85 @@ remoteNetworkPortGetParameters(virNetworkPortPtr port,
 return rv;
 }
 
+static int
+remoteDomainGetGuestUsers(virDomainPtr dom,
+  virDomainUserInfoPtr **info,
+  unsigned int flags)
+{
+int rv = -1;
+size_t i;
+struct private_data *priv = dom->conn->privateData;
+remote_domain_get_guest_users_args args;
+remote_domain_get_guest_users_ret ret;
+remote_domain_userinfo *src;
+virDomainUserInfoPtr *info_ret = NULL;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(, dom);
+
+args.flags = flags;
+
+memset(, 0, sizeof(ret));
+
+if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_GUEST_USERS,
+ (xdrproc_t)xdr_remote_domain_get_guest_users_args, (char *),
+ (xdrproc_t)xdr_remote_domain_get_guest_users_ret, (char *)) 
== -1)
+goto done;
+
+if (ret.info.info_len > REMOTE_DOMAIN_GUEST_USERS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Too many users in userinfo: %d for limit %d"),
+   ret.info.info_len, REMOTE_DOMAIN_GUEST_USERS_MAX);
+goto cleanup;
+}
+
+if (info) {
+if (!ret.info.info_len) {
+*info = NULL;
+rv = ret.ret;
+goto cleanup;
+}
+
+if (VIR_ALLOC_N(info_ret, ret.info.info_len) < 0)
+goto cleanup;
+
+for (i = 0; i < ret.info.info_len; i++) {
+

[libvirt] [PATCH 0/5] Implement qemu-ga 'guest-get-users'

2019-07-10 Thread Jonathon Jongsma
This set of patches adds new API and an implementation for getting the active
users for a domain via the guest agent. There is only an implementation for the
qemu driver. I've implemented the remote protocol and added support in virsh
(new command 'guestusers').

A lot of the implementation was modelled on the implementation of
guest-get-fsinfo, which also returns an array of info structures. Since this is
my first time adding API or dealing with libvirt RPC stuff, I anticipate
several rounds of the series.

This series addresses https://bugzilla.redhat.com/show_bug.cgi?id=1704761

Jonathon Jongsma (5):
  lib: add API to query info about logged-in users
  remote: implement remote protocol for virDomainGetGuestUsers
  virsh: add command 'guestusers' implementing VirDomainGetGuestUsers
  qemu_agent: add helper for getting guest users
  qemu: implement virDomainGetGuestUsers

 include/libvirt/libvirt-domain.h|  18 
 src/driver-hypervisor.h |   6 ++
 src/libvirt-domain.c|  62 ++
 src/libvirt_public.syms |   5 ++
 src/qemu/qemu_agent.c   |  92 
 src/qemu/qemu_agent.h   |   2 +
 src/qemu/qemu_driver.c  |  38 +
 src/remote/remote_daemon_dispatch.c |  89 
 src/remote/remote_driver.c  |  82 +-
 src/remote/remote_protocol.x|  26 +-
 src/remote_protocol-structs |  17 
 tests/qemuagenttest.c   | 125 
 tools/virsh-domain.c|  76 +
 tools/virsh.pod |   4 +
 14 files changed, 640 insertions(+), 2 deletions(-)

-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2 15/21] utils: Write a maximum of MAX_PIPE_FEED_BYTES into a pipe

2019-07-10 Thread Marc-André Lureau
On Wed, Jul 10, 2019 at 10:12 PM Stefan Berger
 wrote:
>
> To avoid blocking on a write on a pipe that the receiving process
> does not read from, write only MAX_PIPE_FEED_BYTES into the pipe
> so that we can serve other pipes as well.

why not simply use non-blocking write?

>
> Signed-off-by: Stefan Berger 
> ---
>  src/util/vircommand.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/src/util/vircommand.c b/src/util/vircommand.c
> index 898ee0df45..0e367eeeab 100644
> --- a/src/util/vircommand.c
> +++ b/src/util/vircommand.c
> @@ -86,6 +86,8 @@ struct _virCommandSendBuffer {
>  size_t buflen;
>  off_t offset;
>  };
> +/* max. number of bytes we write to pipe to avoid blocking on it */
> +#define MAX_PIPE_FEED_BYTES 1024
>
>  struct _virCommand {
>  int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
> @@ -2237,7 +2239,7 @@ virCommandProcessIO(virCommandPtr cmd)
>  int done;
>
>  done = write(cmd->inpipe, cmd->inbuf + inoff,
> - inlen - inoff);
> + MIN(inlen - inoff, MAX_PIPE_FEED_BYTES));
>  if (done < 0) {
>  if (errno == EPIPE) {
>  VIR_DEBUG("child closed stdin early, ignoring EPIPE "
> --
> 2.20.1
>

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 3/5] virsh: add command 'guestusers' implementing VirDomainGetGuestUsers

2019-07-10 Thread Jonathon Jongsma
Signed-off-by: Jonathon Jongsma 
---
 tools/virsh-domain.c | 76 
 tools/virsh.pod  |  4 +++
 2 files changed, 80 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 828ae30789..b964608987 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -14030,6 +14030,76 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
 return ret;
 }
 
+/*
+ * "guestusers" command
+ */
+static const vshCmdInfo info_guestusers[] = {
+{.name = "help",
+ .data = N_("query the users logged on in the guest (via agent)")
+},
+{.name = "desc",
+ .data = N_("Use the guest agent to query the list of logged in users from 
guest's "
+"point of view")
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_guestusers[] = {
+VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE),
+{.name = NULL}
+};
+
+static bool
+cmdGuestusers(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom;
+virDomainUserInfoPtr *userinfo = NULL;
+int ninfo = 0;
+size_t i;
+bool ret = false;
+vshTablePtr table = NULL;
+
+if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if ((ninfo = virDomainGetGuestUsers(dom, , 0)) < 0)
+goto cleanup;
+
+if (userinfo != NULL) {
+table = vshTableNew(_("User"), _("Domain"), _("Login Time"),  NULL);
+if (!table)
+goto cleanup;
+
+for (i = 0; i < ninfo; i++) {
+VIR_AUTOFREE(char *) loginstr = 
virTimeStringThen(userinfo[i]->loginTime);
+if (loginstr == NULL)
+goto cleanup;
+
+if (vshTableRowAppend(table,
+  userinfo[i]->user,
+  userinfo[i]->domain ? userinfo[i]->domain : 
"",
+  loginstr,
+  NULL) < 0)
+goto cleanup;
+}
+
+vshTablePrintToStdout(table, ctl);
+} else {
+vshPrintExtra(ctl, _("No active users in the domain"));
+}
+
+ret = true;
+
+cleanup:
+if (ninfo >= 0) {
+for (i = 0; i < ninfo; i++)
+virDomainUserInfoFree(userinfo[i]);
+}
+VIR_FREE(userinfo);
+virshDomainFree(dom);
+return ret;
+}
+
 const vshCmdDef domManagementCmds[] = {
 {.name = "attach-device",
  .handler = cmdAttachDevice,
@@ -14645,5 +14715,11 @@ const vshCmdDef domManagementCmds[] = {
  .info = info_domblkthreshold,
  .flags = 0
 },
+{.name = "guestusers",
+ .handler = cmdGuestusers,
+ .opts = opts_guestusers,
+ .info = info_guestusers,
+ .flags = 0
+},
 {.name = NULL}
 };
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 5168fa96b6..59cf3d5857 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -3072,6 +3072,10 @@ provided too. The desired operation is then executed on 
the domain.
 
 See B for information on I.
 
+=item B I
+
+Query the list of logged in users from guest's point of view using the guest 
agent.
+
 =item B I
 
 Output the IP address and port number for the VNC display. If the information
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 4/5] qemu_agent: add helper for getting guest users

2019-07-10 Thread Jonathon Jongsma
This function fetches the list of logged-in users from the qemu agent
and converts them into a form that can be used internally in libvirt.

Also add some basic tests for the function.

Signed-off-by: Jonathon Jongsma 
---
 src/qemu/qemu_agent.c |  92 +++
 src/qemu/qemu_agent.h |   2 +
 tests/qemuagenttest.c | 125 ++
 3 files changed, 219 insertions(+)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 361db299a5..b70d6806cd 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2240,3 +2240,95 @@ qemuAgentSetUserPassword(qemuAgentPtr mon,
 VIR_FREE(password64);
 return ret;
 }
+
+int
+qemuAgentGetUsers(qemuAgentPtr mon,
+  virDomainUserInfoPtr **info)
+{
+int ret = -1;
+size_t i;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data = NULL;
+size_t ndata;
+const char *result;
+virDomainUserInfoPtr *users = NULL;
+
+if (!(cmd = qemuAgentMakeCommand("guest-get-users", NULL)))
+return -1;
+
+if (qemuAgentCommand(mon, cmd, , true,
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+goto cleanup;
+
+if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("guest-get-users reply was missing return data"));
+goto cleanup;
+}
+
+if (!virJSONValueIsArray(data)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Malformed guest-get-users data array"));
+goto cleanup;
+}
+
+ndata = virJSONValueArraySize(data);
+
+if (VIR_ALLOC_N(users, ndata) < 0)
+goto cleanup;
+
+for (i = 0; i < ndata; i++) {
+virJSONValuePtr entry = virJSONValueArrayGet(data, i);
+if (VIR_ALLOC(users[i]) < 0)
+goto cleanup;
+
+if (!entry) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("array element missing in guest-get-users return "
+ "value"));
+goto cleanup;
+}
+
+if (!(result = virJSONValueObjectGetString(entry, "user"))) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("'user' missing in reply of guest-get-users"));
+goto cleanup;
+}
+
+if (VIR_STRDUP(users[i]->user, result) < 0) {
+goto cleanup;
+}
+
+/* 'domain' is only present for windows guests */
+if ((result = virJSONValueObjectGetString(entry, "domain"))) {
+if (VIR_STRDUP(users[i]->domain, result) < 0) {
+goto cleanup;
+}
+}
+
+double loginseconds;
+if (virJSONValueObjectGetNumberDouble(entry, "login-time", 
) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("'login-time' missing in reply of 
guest-get-users"));
+goto cleanup;
+}
+/* convert to milliseconds */
+users[i]->loginTime = loginseconds * 1000;
+}
+
+*info = users;
+users = NULL;
+ret = ndata;
+
+ cleanup:
+if (users) {
+for (i = 0; i < ndata; i++) {
+virDomainUserInfoFree(users[i]);
+}
+VIR_FREE(users);
+}
+virJSONValueFree(cmd);
+virJSONValueFree(reply);
+return ret;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 6ae9fe54da..70797dc894 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -120,3 +120,5 @@ int qemuAgentSetUserPassword(qemuAgentPtr mon,
  const char *user,
  const char *password,
  bool crypted);
+
+int qemuAgentGetUsers(qemuAgentPtr mon, virDomainUserInfoPtr **info);
diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
index 2f79986207..d97f05102e 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -902,6 +902,130 @@ testQemuAgentGetInterfaces(const void *data)
 return ret;
 }
 
+static const char testQemuAgentUsersResponse[] =
+"{\"return\": "
+"   ["
+"   {\"user\": \"test\","
+"\"login-time\": 1561739203.584038"
+"   },"
+"   {\"user\": \"test2\","
+"\"login-time\": 1561739229.190697"
+"   }"
+"   ]"
+"}";
+
+static const char testQemuAgentUsersResponse2[] =
+"{\"return\": "
+"   ["
+"   {\"user\": \"test\","
+"\"domain\": \"DOMAIN\","
+"\"login-time\": 1561739203.584038"
+"   }"
+"   ]"
+"}";
+
+static int
+testQemuAgentUsers(const void *data)
+{
+virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
+qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
+virDomainUserInfoPtr *userinfo = NULL;
+int nusers;
+int ret = -1;
+int i;
+
+if (!test)
+return -1;
+
+if 

[libvirt] [PATCH 1/5] lib: add API to query info about logged-in users

2019-07-10 Thread Jonathon Jongsma
Add API for querying logged-in users from a domain implemented via
guest agent.

Signed-off-by: Jonathon Jongsma 
---
 include/libvirt/libvirt-domain.h | 18 ++
 src/driver-hypervisor.h  |  6 
 src/libvirt-domain.c | 62 
 src/libvirt_public.syms  |  5 +++
 4 files changed, 91 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 2dbd74d4f3..82dbbd3fc5 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4896,4 +4896,22 @@ int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
int *nparams,
unsigned int flags);
 
+/**
+ * virDomainUserInfo:
+ *
+ * The data structure containing informationa bout logged-in users within a
+ * guest
+ */
+typedef struct _virDomainUserInfo virDomainUserInfo;
+typedef virDomainUserInfo *virDomainUserInfoPtr;
+struct _virDomainUserInfo {
+char *user; /* username */
+char *domain; /* login domain (windows only) */
+unsigned long long loginTime; /* timestamp of login for this user in ms 
since epoch */
+};
+int virDomainGetGuestUsers(virDomainPtr domain,
+   virDomainUserInfoPtr **info,
+   unsigned int flags);
+void virDomainUserInfoFree(virDomainUserInfoPtr info);
+
 #endif /* LIBVIRT_DOMAIN_H */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index b15aaa36bc..0ef7257ace 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1327,6 +1327,11 @@ typedef int
 int *nparams,
 unsigned int flags);
 
+typedef int
+(*virDrvDomainGetGuestUsers)(virDomainPtr domain,
+ virDomainUserInfoPtr **info,
+ unsigned int flags);
+
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1579,4 +1584,5 @@ struct _virHypervisorDriver {
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
 virDrvNodeGetSEVInfo nodeGetSEVInfo;
 virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
+virDrvDomainGetGuestUsers domainGetGuestUsers;
 };
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 3d12e7c125..80faa08758 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12199,6 +12199,68 @@ virDomainSetVcpu(virDomainPtr domain,
 return -1;
 }
 
+/**
+ * virDomainGetGuestUsers:
+ * @domain: pointer to domain object
+ * @info: a pointer to a variable to store an array of user info
+ * @flags: currently unused, callers shall pass 0
+ *
+ * Queries the guest agent for the list of currently active users on the
+ * guest. The reported data depends on the guest agent implementation.
+ *
+ * This API requires the VM to run. The caller is responsible for calling
+ * virTypedParamsFree to free memory returned in @params.
+ *
+ * Returns the number of returned users, or -1 in case of error.
+ * On success, the array of the information is stored into @info. The caller is
+ * responsible for calling virDomainUserInfoFree() on each array element, then
+ * calling free() on @info. On error, @info is set to NULL.
+ */
+int
+virDomainGetGuestUsers(virDomainPtr domain,
+   virDomainUserInfoPtr **info,
+   unsigned int flags)
+{
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckReadOnlyGoto(domain->conn->flags, error);
+
+virCheckNonNullArgGoto(info, error);
+
+if (domain->conn->driver->domainGetGuestUsers) {
+int ret;
+ret = domain->conn->driver->domainGetGuestUsers(domain, info,
+flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
+
+/**
+ * virDomainUserInfoFree:
+ * @info: pointer to a UserInfo object
+ *
+ * Frees all the memory occupied by @info.
+ */
+void
+virDomainUserInfoFree(virDomainUserInfoPtr info)
+{
+if (!info)
+return;
+
+VIR_FREE(info->user);
+VIR_FREE(info->domain);
+
+VIR_FREE(info);
+}
 
 /**
  * virDomainSetBlockThreshold:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 18500ec8b2..7d0e3c7849 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -836,4 +836,9 @@ LIBVIRT_5.5.0 {
 virNetworkPortSetParameters;
 } LIBVIRT_5.2.0;
 
+LIBVIRT_5.6.0 {
+global:
+virDomainGetGuestUsers;
+virDomainUserInfoFree;
+} LIBVIRT_5.5.0;
 #  define new API here using predicted next version number 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2 16/21] utils: Extend virCommandProcessIO to including the send buffers

2019-07-10 Thread Marc-André Lureau
On Wed, Jul 10, 2019 at 10:12 PM Stefan Berger
 wrote:
>
> Signed-off-by: Stefan Berger 

Could you include a test?

> ---
>  src/util/vircommand.c | 70 ++-
>  1 file changed, 69 insertions(+), 1 deletion(-)
>
> diff --git a/src/util/vircommand.c b/src/util/vircommand.c
> index 0e367eeeab..357a9888a1 100644
> --- a/src/util/vircommand.c
> +++ b/src/util/vircommand.c
> @@ -1803,6 +1803,69 @@ virCommandSetSendBuffer(virCommandPtr cmd,
>  }
>
>
> +static int
> +virCommandGetNumSendBuffers(virCommandPtr cmd)
> +{
> +return cmd->numSendBuffers;
> +}
> +

That getter doesn't seem very useful, or at least you don't use it consistently.

looks good otherwise

> +
> +static int
> +virCommandAddSendBuffersFillPollfd(virCommandPtr cmd,
> +   struct pollfd *fds,
> +   int startidx)
> +{
> +size_t i, j;
> +
> +for (i = 0, j = 0; i < cmd->numSendBuffers; i++) {
> +if (cmd->sendBuffers[i].fd >= 0) {
> +fds[startidx + j].fd = cmd->sendBuffers[i].fd;
> +fds[startidx + j].events = POLLOUT;
> +fds[startidx + j].revents = 0;
> +j++;
> +}
> +}
> +
> +return j;
> +}
> +
> +
> +static int
> +virCommandSendBuffersHandlePoll(virCommandPtr cmd,
> +struct pollfd *fds)
> +{
> +size_t i;
> +int done;
> +
> +for (i = 0; i < cmd->numSendBuffers; i++) {
> +if (fds->fd == cmd->sendBuffers[i].fd)
> +break;
> +}
> +if (i == cmd->numSendBuffers)
> +return 0;
> +
> +done = write(fds->fd,
> + cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset,
> + MIN(cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset,
> + MAX_PIPE_FEED_BYTES));
> +if (done < 0) {
> +if (errno == EPIPE) {
> +VIR_DEBUG("child closed PIPE early, ignoring EPIPE "
> +  "on fd %d", cmd->sendBuffers[i].fd);
> +VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
> +} else if (errno != EINTR && errno != EAGAIN) {
> +virReportSystemError(errno, "%s",
> + _("unable to write to child input"));
> +return -1;
> +}
> +} else {
> +cmd->sendBuffers[i].offset += done;
> +if (cmd->sendBuffers[i].offset == cmd->sendBuffers[i].buflen)
> +VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
> +}
> +return 0;
> +}
> +
>  /**
>   * virCommandSetInputBuffer:
>   * @cmd: the command to modify
> @@ -2157,7 +2220,7 @@ virCommandProcessIO(virCommandPtr cmd)
>  goto cleanup;
>  ret = -1;
>
> -if (VIR_ALLOC_N(fds, 3) < 0)
> +if (VIR_ALLOC_N(fds, 3 + virCommandGetNumSendBuffers(cmd)) < 0)
>  goto cleanup;
>
>  for (;;) {
> @@ -2183,6 +2246,8 @@ virCommandProcessIO(virCommandPtr cmd)
>  nfds++;
>  }
>
> +nfds += virCommandAddSendBuffersFillPollfd(cmd, fds, nfds);
> +
>  if (nfds == 0)
>  break;
>
> @@ -2255,6 +2320,9 @@ virCommandProcessIO(virCommandPtr cmd)
>  if (inoff == inlen)
>  VIR_FORCE_CLOSE(cmd->inpipe);
>  }
> +} else if (fds[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
> +if (virCommandSendBuffersHandlePoll(cmd, [i]) < 0)
> +goto cleanup;
>  }
>  }
>  }
> --
> 2.20.1
>

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2 14/21] utils: Convert pollfd array to be allocated

2019-07-10 Thread Stefan Berger

On 7/10/19 2:47 PM, Marc-André Lureau wrote:

On Wed, Jul 10, 2019 at 10:12 PM Stefan Berger
 wrote:

Convert the struct pollfd *fds to be allocated rather than residing
on the stack.


why? give some context to the commit message. thanks



Preparation for the next patch where the size of the array becomes 
dynamic...



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 14/21] utils: Convert pollfd array to be allocated

2019-07-10 Thread Marc-André Lureau
On Wed, Jul 10, 2019 at 10:12 PM Stefan Berger
 wrote:
>
> Convert the struct pollfd *fds to be allocated rather than residing
> on the stack.
>

why? give some context to the commit message. thanks

> Signed-off-by: Stefan Berger 
> ---
>  src/util/vircommand.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/src/util/vircommand.c b/src/util/vircommand.c
> index e32377497b..898ee0df45 100644
> --- a/src/util/vircommand.c
> +++ b/src/util/vircommand.c
> @@ -2123,6 +2123,7 @@ virCommandProcessIO(virCommandPtr cmd)
>  size_t inlen = 0, outlen = 0, errlen = 0;
>  size_t inoff = 0;
>  int ret = 0;
> +VIR_AUTOFREE(struct pollfd *) fds = NULL;
>
>  if (dryRunBuffer || dryRunCallback) {
>  VIR_DEBUG("Dry run requested, skipping I/O processing");
> @@ -2154,9 +2155,11 @@ virCommandProcessIO(virCommandPtr cmd)
>  goto cleanup;
>  ret = -1;
>
> +if (VIR_ALLOC_N(fds, 3) < 0)
> +goto cleanup;
> +
>  for (;;) {
>  size_t i;
> -struct pollfd fds[3];
>  int nfds = 0;
>
>  if (cmd->inpipe != -1) {
> --
> 2.20.1
>

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 08/21] tpm: Move virtpm.c from utils dir to own tpm dir

2019-07-10 Thread Stefan Berger
Move virtpm.c from utils dir to its own tpm dir. This change
is mostly driven by the later introduction of virtpm_conf.c where
the define function like XYZTypeFromString() that we cannot
include from utils dir.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 po/POTFILES  |  2 +-
 src/Makefile.am  |  1 +
 src/conf/Makefile.inc.am |  1 +
 src/libvirt_private.syms |  8 
 src/qemu/Makefile.inc.am |  1 +
 src/security/Makefile.inc.am |  1 +
 src/tpm/Makefile.inc.am  | 17 +
 src/{util => tpm}/virtpm.c   |  0
 src/{util => tpm}/virtpm.h   |  0
 src/util/Makefile.inc.am |  2 --
 tests/Makefile.am|  1 +
 11 files changed, 27 insertions(+), 7 deletions(-)
 create mode 100644 src/tpm/Makefile.inc.am
 rename src/{util => tpm}/virtpm.c (100%)
 rename src/{util => tpm}/virtpm.h (100%)

diff --git a/po/POTFILES b/po/POTFILES
index 8017712ff4..e3c1a8edae 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -188,6 +188,7 @@ src/storage/storage_backend_zfs.c
 src/storage/storage_driver.c
 src/storage/storage_util.c
 src/test/test_driver.c
+src/tpm/virtpm.c
 src/util/iohelper.c
 src/util/viralloc.c
 src/util/virarptable.c
@@ -266,7 +267,6 @@ src/util/virsysinfo.c
 src/util/virthreadjob.c
 src/util/virthreadpool.c
 src/util/virtime.c
-src/util/virtpm.c
 src/util/virtypedparam.c
 src/util/viruri.c
 src/util/virusb.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b562dc250..5f7c9001fe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -122,6 +122,7 @@ include node_device/Makefile.inc.am
 include secret/Makefile.inc.am
 include storage/Makefile.inc.am
 include remote/Makefile.inc.am
+include tpm/Makefile.inc.am
 
 
 THREAD_LIBS = $(LIB_PTHREAD) $(LTLIBMULTITHREAD)
diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index 6b52ba674b..08c7c9da7f 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -178,6 +178,7 @@ libvirt_la_BUILT_LIBADD += libvirt_conf.la
 libvirt_conf_la_SOURCES = $(CONF_SOURCES)
 libvirt_conf_la_CFLAGS = \
-I$(srcdir)/conf \
+   -I$(srcdir)/tpm \
$(AM_CFLAGS) \
$(NULL)
 libvirt_conf_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 34937adc5d..e29007cab1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1445,6 +1445,10 @@ virSecurityManagerTransactionStart;
 virSecurityManagerVerify;
 
 
+# tpm/virtpm.h
+virTPMCreateCancelPath;
+
+
 # util/viralloc.h
 virAlloc;
 virAllocN;
@@ -3175,10 +3179,6 @@ virTimeStringThen;
 virTimeStringThenRaw;
 
 
-# util/virtpm.h
-virTPMCreateCancelPath;
-
-
 # util/virtypedparam.h
 virTypedParameterAssign;
 virTypedParameterAssignFromStr;
diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am
index 254ba07dc0..72b28e731d 100644
--- a/src/qemu/Makefile.inc.am
+++ b/src/qemu/Makefile.inc.am
@@ -84,6 +84,7 @@ libvirt_driver_qemu_impl_la_CFLAGS = \
-I$(srcdir)/access \
-I$(srcdir)/conf \
-I$(srcdir)/secret \
+   -I$(srcdir)/tpm \
$(AM_CFLAGS) \
$(NULL)
 libvirt_driver_qemu_impl_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/security/Makefile.inc.am b/src/security/Makefile.inc.am
index 64e0f46857..3e110596dc 100644
--- a/src/security/Makefile.inc.am
+++ b/src/security/Makefile.inc.am
@@ -47,6 +47,7 @@ noinst_LTLIBRARIES += libvirt_security_manager.la
 libvirt_la_BUILT_LIBADD += libvirt_security_manager.la
 libvirt_security_manager_la_CFLAGS = \
-I$(srcdir)/conf \
+   -I$(srcdir)/tpm \
$(AM_CFLAGS) \
$(NULL)
 libvirt_security_manager_la_LDFLAGS = $(AM_LDFLAGS)
diff --git a/src/tpm/Makefile.inc.am b/src/tpm/Makefile.inc.am
new file mode 100644
index 00..1f5131bf34
--- /dev/null
+++ b/src/tpm/Makefile.inc.am
@@ -0,0 +1,17 @@
+# vim: filetype=automake
+
+TPM_UTIL_SOURCES = \
+   tpm/virtpm.h \
+   tpm/virtpm.c \
+   $(NULL)
+
+
+EXTRA_DIST += \
+   $(TPM_UTIL_SOURCES) \
+   $(NULL)
+
+noinst_LTLIBRARIES += libvirt_tpm.la
+libvirt_la_BUILT_LIBADD += libvirt_tpm.la
+libvirt_tpm_la_CFLAGS = $(AM_CFLAGS)
+libvirt_tpm_la_LDFLAGS = $(AM_LDFLAGS)
+libvirt_tpm_la_SOURCES = $(TPM_UTIL_SOURCES)
diff --git a/src/util/virtpm.c b/src/tpm/virtpm.c
similarity index 100%
rename from src/util/virtpm.c
rename to src/tpm/virtpm.c
diff --git a/src/util/virtpm.h b/src/tpm/virtpm.h
similarity index 100%
rename from src/util/virtpm.h
rename to src/tpm/virtpm.h
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
index c757f5a6ae..8b2ff6be6b 100644
--- a/src/util/Makefile.inc.am
+++ b/src/util/Makefile.inc.am
@@ -205,8 +205,6 @@ UTIL_SOURCES = \
util/virthreadpool.h \
util/virtime.c \
util/virtime.h \
-   util/virtpm.c \
-   util/virtpm.h \
util/virtypedparam.c \
util/virtypedparam.h \
util/virusb.c \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 115afa1c1a..ffc9f7f92e 100644
--- 

[libvirt] [PATCH v2 21/21] docs: Extend TPM docs with new encryption element

2019-07-10 Thread Stefan Berger
Describe the encryption element in the TPM's domain XML.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/formatdomain.html.in | 16 
 1 file changed, 16 insertions(+)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a7a6ec32a5..9fa391748e 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8212,6 +8212,9 @@ qemu-kvm -net nic,model=? /dev/null
   TPM functionality for each VM. QEMU talks to it over a Unix socket. With
   the emulator device type each guest gets its own private TPM.
   'emulator' since 4.5.0
+  The state of the TPM emulator can be encrypted by providing an
+  encryption element.
+  'encryption' since 5.6.0
 
 
  Example: usage of the TPM Emulator
@@ -8221,6 +8224,9 @@ qemu-kvm -net nic,model=? /dev/null
   devices
 tpm model='tpm-tis'
   backend type='emulator' version='2.0'
+encryption format='vtpm'
+  secret type='passphrase' usage='VTPM_example'/
+/encryption
   /backend
 /tpm
   /devices
@@ -8283,6 +8289,16 @@ qemu-kvm -net nic,model=? /dev/null
   '2.0' : creates a TPM 2.0
 
   
+  encryption
+  
+
+  The encryption element allows the state of a TPM 
emulator
+  to be encrypted. The format attribute must be 
vtpm.
+  The secret element must reference a secret object using
+  either its usage or uuid. The 
type
+  attribute must be set to passphrase.
+
+  
 
 
 NVRAM device
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 13/21] utils: Implement function to pass a buffer to send via a fd to virCommand

2019-07-10 Thread Stefan Berger
Implement virCommandSetSendBuffer() that allows the caller to pass a
file descriptor and buffer to virCommand. virCommand will write the
buffer into the file descriptor. That file descriptor could be the
write end of a pipe or one of the file descriptors of a socketpair.
The other file descriptor should be passed to the launched process to
read the data from.

Only implement the function to allocate memory for send buffers
and to free them later on.

Signed-off-by: Stefan Berger 
---
 src/libvirt_private.syms |  1 +
 src/util/vircommand.c| 62 
 src/util/vircommand.h|  5 
 3 files changed, 68 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d2045895a1..3feb862fb4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1734,6 +1734,7 @@ virCommandSetOutputBuffer;
 virCommandSetOutputFD;
 virCommandSetPidFile;
 virCommandSetPreExecHook;
+virCommandSetSendBuffer;
 virCommandSetSELinuxLabel;
 virCommandSetUID;
 virCommandSetUmask;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 8695c98d1b..e32377497b 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -77,6 +77,16 @@ struct _virCommandFD {
 unsigned int flags;
 };
 
+typedef struct _virCommandSendBuffer virCommandSendBuffer;
+typedef virCommandSendBuffer *virCommandSendBufferPtr;
+
+struct _virCommandSendBuffer {
+int fd;
+unsigned char *buffer;
+size_t buflen;
+off_t offset;
+};
+
 struct _virCommand {
 int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
 
@@ -136,6 +146,9 @@ struct _virCommand {
 char *appArmorProfile;
 #endif
 int mask;
+
+virCommandSendBufferPtr sendBuffers;
+size_t numSendBuffers;
 };
 
 /* See virCommandSetDryRun for description for this variable */
@@ -1741,6 +1754,53 @@ virCommandSetWorkingDirectory(virCommandPtr cmd, const 
char *pwd)
 }
 
 
+static void
+virCommandFreeSendBuffers(virCommandPtr cmd)
+{
+size_t i;
+
+for (i = 0; i < cmd->numSendBuffers; i++) {
+VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+VIR_FREE(cmd->sendBuffers[i].buffer);
+}
+VIR_FREE(cmd->sendBuffers);
+}
+
+
+/**
+ * virCommandSetSendBuffer
+ * @cmd: the command to modify
+ *
+ * Pass a buffer to virCommand that will be written into the
+ * given file descriptor. The buffer will be freed automatically
+ * and the file descriptor closed.
+ */
+int
+virCommandSetSendBuffer(virCommandPtr cmd,
+int fd,
+unsigned char *buffer, size_t buflen)
+{
+size_t i = cmd->numSendBuffers;
+
+if (!cmd || cmd->has_error)
+return -1;
+
+if (VIR_REALLOC_N(cmd->sendBuffers, i + 1) < 0) {
+cmd->has_error = ENOMEM;
+return -1;
+}
+
+cmd->sendBuffers[i].fd = fd;
+cmd->sendBuffers[i].buffer = buffer;
+cmd->sendBuffers[i].buflen = buflen;
+cmd->sendBuffers[i].offset = 0;
+
+cmd->numSendBuffers++;
+
+return 0;
+}
+
+
 /**
  * virCommandSetInputBuffer:
  * @cmd: the command to modify
@@ -2880,6 +2940,8 @@ virCommandFree(virCommandPtr cmd)
 VIR_FREE(cmd->appArmorProfile);
 #endif
 
+virCommandFreeSendBuffers(cmd);
+
 VIR_FREE(cmd);
 }
 
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index c9a8d3c41c..716e84af3d 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -148,6 +148,11 @@ void virCommandAddArgList(virCommandPtr cmd,
 void virCommandSetWorkingDirectory(virCommandPtr cmd,
const char *pwd) ATTRIBUTE_NONNULL(2);
 
+int virCommandSetSendBuffer(virCommandPtr cmd,
+int fd,
+unsigned char *buffer, size_t buflen)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
+
 void virCommandSetInputBuffer(virCommandPtr cmd,
   const char *inbuf) ATTRIBUTE_NONNULL(2);
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 03/21] util: Add VIR_STORAGE_ENCRYPTION_FORMAT_VTPM

2019-07-10 Thread Stefan Berger
Add VIR_STORAGE_ENCRYPTION_FORMAT_VTPM with string 'vtpm' for
support of encrypting vTPM storage.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/qemu/qemu_block.c   | 1 +
 src/util/virstorageencryption.c | 2 +-
 src/util/virstorageencryption.h | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 0a6522577d..c3296c36f5 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1184,6 +1184,7 @@ qemuBlockStorageSourceGetCryptoProps(virStorageSourcePtr 
src,
 encformat = "luks";
 break;
 
+case VIR_STORAGE_ENCRYPTION_FORMAT_VTPM:
 case VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT:
 case VIR_STORAGE_ENCRYPTION_FORMAT_LAST:
 default:
diff --git a/src/util/virstorageencryption.c b/src/util/virstorageencryption.c
index 49df7fddd8..4c7356d47a 100644
--- a/src/util/virstorageencryption.c
+++ b/src/util/virstorageencryption.c
@@ -44,7 +44,7 @@ VIR_ENUM_IMPL(virStorageEncryptionSecret,
 
 VIR_ENUM_IMPL(virStorageEncryptionFormat,
   VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
-  "default", "qcow", "luks",
+  "default", "qcow", "luks", "vtpm",
 );
 
 static void
diff --git a/src/util/virstorageencryption.h b/src/util/virstorageencryption.h
index 3e5485d88b..29bd00056c 100644
--- a/src/util/virstorageencryption.h
+++ b/src/util/virstorageencryption.h
@@ -59,6 +59,7 @@ typedef enum {
 VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0,
 VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */
 VIR_STORAGE_ENCRYPTION_FORMAT_LUKS,
+VIR_STORAGE_ENCRYPTION_FORMAT_VTPM,
 
 VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
 } virStorageEncryptionFormatType;
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 19/21] tpm: Check TPM XML device configuration changes after edit

2019-07-10 Thread Stefan Berger
Since swtpm does not support getting started once it was created
with encrypted enabled, we don't allow encryption to be removed.
Similarly, we do not allow encrypted to be added once swtpm has
run.

Signed-off-by: Stefan Berger 
---
 src/conf/domain_conf.c| 56 +++
 src/conf/domain_conf.h|  4 +++
 src/libvirt_private.syms  |  1 +
 src/qemu/qemu_driver.c| 28 
 src/qemu/qemu_extdevice.c |  2 +-
 src/qemu/qemu_extdevice.h |  3 +++
 6 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index df6238c299..dba8da0e5d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31435,3 +31435,59 @@ virDomainGraphicsNeedsAutoRenderNode(const 
virDomainGraphicsDef *graphics)
 
 return true;
 }
+
+
+static int
+virDomainCheckTPMChanges(virDomainDefPtr def,
+ virDomainDefPtr newDef)
+{
+bool oldEnc, newEnc;
+
+if (!def->tpm)
+return 0;
+
+switch (def->tpm->type) {
+case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+if (virFileExists(def->tpm->data.emulator.storagepath)) {
+/* VM has been started */
+/* Once a VM was started with an encrypted state we allow
+ * less configuration changes.
+ */
+oldEnc = def->tpm->data.emulator.encryption;
+if (oldEnc && def->tpm->type != newDef->tpm->type) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Changing the type of TPM is not allowed"));
+return -1;
+}
+if (oldEnc && !newDef->tpm) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Removing an encrypted TPM is not allowed"));
+return -1;
+}
+newEnc = newDef->tpm->data.emulator.encryption;
+if (oldEnc != newEnc) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("TPM state encryption cannot be changed "
+ "once VM was started"));
+return -1;
+}
+}
+break;
+case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+case VIR_DOMAIN_TPM_TYPE_LAST:
+break;
+}
+
+return 0;
+}
+
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def,
+virDomainDefPtr newDef)
+{
+if (!def || !newDef)
+return 0;
+
+return virDomainCheckTPMChanges(def, newDef);
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a03986623a..a61faa7d57 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3623,3 +3623,7 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef 
*graphics);
 
 bool
 virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics);
+
+int
+virDomainCheckDeviceChanges(virDomainDefPtr def, virDomainDefPtr newDef)
+ATTRIBUTE_NONNULL(2);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 804d244313..d8e99ad566 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -205,6 +205,7 @@ virDomainBootTypeFromString;
 virDomainBootTypeToString;
 virDomainCapabilitiesPolicyTypeToString;
 virDomainCapsFeatureTypeToString;
+virDomainCheckDeviceChanges;
 virDomainChrConsoleTargetTypeFromString;
 virDomainChrConsoleTargetTypeToString;
 virDomainChrDefForeach;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ef2e980216..8f224582b6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -52,6 +52,7 @@
 #include "qemu_migration_params.h"
 #include "qemu_blockjob.h"
 #include "qemu_security.h"
+#include "qemu_extdevice.h"
 
 #include "virerror.h"
 #include "virlog.h"
@@ -7568,6 +7569,30 @@ qemuDomainCreate(virDomainPtr dom)
 return qemuDomainCreateWithFlags(dom, 0);
 }
 
+static int
+qemuDomainCheckDeviceChanges(virQEMUDriverPtr driver,
+ virDomainDefPtr def)
+{
+virDomainObjPtr vm;
+int ret;
+
+vm = virDomainObjListFindByUUID(driver->domains, def->uuid);
+if (!vm)
+return 0;
+
+if (qemuExtDevicesInitPaths(driver, vm->def) < 0) {
+ret = -1;
+goto cleanup;
+}
+
+ret = virDomainCheckDeviceChanges(vm->def, def);
+
+ cleanup:
+virDomainObjEndAPI();
+
+return ret;
+}
+
 static virDomainPtr
 qemuDomainDefineXMLFlags(virConnectPtr conn,
  const char *xml,
@@ -7604,6 +7629,9 @@ qemuDomainDefineXMLFlags(virConnectPtr conn,
 if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
 goto cleanup;
 
+if (qemuDomainCheckDeviceChanges(driver, def) < 0)
+goto cleanup;
+
 if (!(vm = virDomainObjListAdd(driver->domains, def,
driver->xmlopt,
0, )))
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index a21caefaba..e576bca165 100644
--- 

[libvirt] [PATCH v2 15/21] utils: Write a maximum of MAX_PIPE_FEED_BYTES into a pipe

2019-07-10 Thread Stefan Berger
To avoid blocking on a write on a pipe that the receiving process
does not read from, write only MAX_PIPE_FEED_BYTES into the pipe
so that we can serve other pipes as well.

Signed-off-by: Stefan Berger 
---
 src/util/vircommand.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 898ee0df45..0e367eeeab 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -86,6 +86,8 @@ struct _virCommandSendBuffer {
 size_t buflen;
 off_t offset;
 };
+/* max. number of bytes we write to pipe to avoid blocking on it */
+#define MAX_PIPE_FEED_BYTES 1024
 
 struct _virCommand {
 int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
@@ -2237,7 +2239,7 @@ virCommandProcessIO(virCommandPtr cmd)
 int done;
 
 done = write(cmd->inpipe, cmd->inbuf + inoff,
- inlen - inoff);
+ MIN(inlen - inoff, MAX_PIPE_FEED_BYTES));
 if (done < 0) {
 if (errno == EPIPE) {
 VIR_DEBUG("child closed stdin early, ignoring EPIPE "
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 20/21] docs: Extend Secret XML documentation with vtpm usage type

2019-07-10 Thread Stefan Berger
Extend the Secret XML documentation with vtpm usage type.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/formatsecret.html.in | 61 +--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/docs/formatsecret.html.in b/docs/formatsecret.html.in
index defbe71731..8d0630a7c3 100644
--- a/docs/formatsecret.html.in
+++ b/docs/formatsecret.html.in
@@ -42,8 +42,8 @@
 Specifies what this secret is used for.  A mandatory
 type attribute specifies the usage category, currently
 only volume, ceph, iscsi,
-and tls are defined. Specific usage categories
-are described below.
+tls, and vtpm are defined. Specific usage
+categories are described below.
   
 
 
@@ -322,6 +322,63 @@ Secret 718c71bd-67b5-4a2b-87ec-a24e8ca200dc created
 
 # MYSECRET=`printf %s "letmein" | base64`
 # virsh secret-set-value 718c71bd-67b5-4a2b-87ec-a24e8ca200dc $MYSECRET
+Secret value set
+
+
+
+Usage type "vtpm"
+
+
+  This secret is associated with a virtualized TPM (vTPM) and serves
+  as a passphrase for deriving a key from for encrypting the state
+  of the vTPM.
+  The usage type='vtpm' element must contain
+  a single name element that specifies a usage name
+  for the secret.  The vTPM secret can then be used by UUID or by
+  this usage name via the encryption element of
+  a tpm when using an
+  emulator.
+  Since 5.6.0. The following is an example
+  of the steps to be taken.  First create a vtpm-secret.xml file:
+
+
+# cat vtpm-secret.xml
+secret ephemeral='no' private='yes'
+   descriptionsample vTPM secret/description
+   usage type='vtpm'
+  nameVTPM_example/name
+   /usage
+/secret
+
+# virsh secret-define vtpm-secret.xml
+Secret 6dd3e4a5-1d76-44ce-961f-f119f5aad935 created
+
+# virsh secret-list
+ UUID   Usage
+
+ 6dd3e4a5-1d76-44ce-961f-f119f5aad935   vtpm VTPM_example
+
+#
+
+
+
+
+  A secret may also be defined via the
+  
+   virSecretDefineXML API.
+
+  Once the secret is defined, a secret value will need to be set. The
+  secret would be the passphrase used to decrypt the vTPM state.
+  The following is a simple example of using
+  virsh secret-set-value to set the secret value. The
+  
+  virSecretSetValue API may also be used to set
+  a more secure secret without using printable/readable characters.
+
+
+
+# MYSECRET=`printf %s "open sesame" | base64`
+# virsh secret-set-value 6dd3e4a5-1d76-44ce-961f-f119f5aad935 $MYSECRET
 Secret value set
 
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 11/21] tpm: Check whether previously found executables were updated

2019-07-10 Thread Stefan Berger
Check whether previously found executables were updated and if
so look for them again. This helps to use updated features of
swtpm and its tools upon updating them.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/qemu/qemu_tpm.c |  1 +
 src/tpm/virtpm.c| 34 ++
 2 files changed, 35 insertions(+)

diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 61b4f72320..2afa8db448 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c
index 0179b1e8be..e4735f9c4d 100644
--- a/src/tpm/virtpm.c
+++ b/src/tpm/virtpm.c
@@ -77,8 +77,13 @@ virTPMCreateCancelPath(const char *devpath)
  * executables for the swtpm; to be found on the host
  */
 static char *swtpm_path;
+static struct stat swtpm_stat;
+
 static char *swtpm_setup;
+static struct stat swtpm_setup_stat;
+
 static char *swtpm_ioctl;
+static struct stat swtpm_ioctl_stat;
 
 const char *
 virTPMGetSwtpm(void)
@@ -116,18 +121,22 @@ virTPMEmulatorInit(void)
 static const struct {
 const char *name;
 char **path;
+struct stat *stat;
 } prgs[] = {
 {
 .name = "swtpm",
 .path = _path,
+.stat = _stat,
 },
 {
 .name = "swtpm_setup",
 .path = _setup,
+.stat = _setup_stat,
 },
 {
 .name = "swtpm_ioctl",
 .path = _ioctl,
+.stat = _ioctl_stat,
 }
 };
 size_t i;
@@ -135,6 +144,23 @@ virTPMEmulatorInit(void)
 for (i = 0; i < ARRAY_CARDINALITY(prgs); i++) {
 char *path;
 bool findit = *prgs[i].path == NULL;
+struct stat statbuf;
+char *tmp;
+
+if (!findit) {
+/* has executables changed? */
+if (stat(*prgs[i].path, ) < 0) {
+virReportSystemError(errno,
+ _("Could not stat %s"), path);
+findit = true;
+}
+if (!findit &&
+memcmp(_mtim,
+   [i].stat->st_mtime,
+   sizeof(statbuf.st_mtim))) {
+findit = true;
+}
+}
 
 if (findit) {
 path = virFindFileInPath(prgs[i].name);
@@ -151,7 +177,15 @@ virTPMEmulatorInit(void)
 VIR_FREE(path);
 return -1;
 }
+if (stat(path, prgs[i].stat) < 0) {
+virReportSystemError(errno,
+ _("Could not stat %s"), path);
+VIR_FREE(path);
+return -1;
+}
+tmp = *prgs[i].path;
 *prgs[i].path = path;
+VIR_FREE(tmp);
 }
 }
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 07/21] tests: Add tests for QEMU command line generation with encrypted TPM

2019-07-10 Thread Stefan Berger
The QEMU command line does not change when TPM state is encrypted
compared to when it is plain.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 .../tpm-emulator-tpm2-enc.x86_64-latest.args  | 35 +++
 tests/qemuxml2argvtest.c  |  1 +
 2 files changed, 36 insertions(+)
 create mode 100644 
tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args

diff --git a/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args 
b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args
new file mode 100644
index 00..3c8dc8e483
--- /dev/null
+++ b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args
@@ -0,0 +1,35 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-TPM-VM \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-TPM-VM/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-TPM-VM/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-TPM-VM/.config \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=TPM-VM,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-TPM-VM/master-key.aes \
+-machine pc-i440fx-2.12,accel=tcg,usb=off,dump-guest-core=off \
+-m 2048 \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid 11d7cd22-da89-3094-6212-079a48a309a1 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot menu=on,strict=on \
+-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
+-tpmdev emulator,id=tpm-tpm0,chardev=chrtpm \
+-chardev socket,id=chrtpm,path=/dev/test \
+-device tpm-tis,tpmdev=tpm-tpm0,id=tpm0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 91ca35d469..9c02cac8fc 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2082,6 +2082,7 @@ mymain(void)
 QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, 
QEMU_CAPS_DEVICE_TPM_TIS);
 DO_TEST_CAPS_LATEST("tpm-emulator");
 DO_TEST_CAPS_LATEST("tpm-emulator-tpm2");
+DO_TEST_CAPS_LATEST("tpm-emulator-tpm2-enc");
 
 DO_TEST_PARSE_ERROR("pci-domain-invalid", NONE);
 DO_TEST_PARSE_ERROR("pci-bus-invalid", NONE);
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 01/21] secret: Add support for usage type vTPM, extend schema and test case

2019-07-10 Thread Stefan Berger
Add support for usage type vTPM to secret.
Extend the schema for the Secret to support the vTPM usage type
and add a test case for parsing the Secret with usage type vTPM.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/schemas/secret.rng  | 10 ++
 include/libvirt/libvirt-secret.h |  1 +
 src/conf/secret_conf.c   | 13 +
 src/util/virsecret.c |  2 +-
 tests/secretxml2xmlin/usage-vtpm.xml |  7 +++
 tests/secretxml2xmltest.c|  1 +
 6 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 tests/secretxml2xmlin/usage-vtpm.xml

diff --git a/docs/schemas/secret.rng b/docs/schemas/secret.rng
index 1e94d66e48..e0add8a5e9 100644
--- a/docs/schemas/secret.rng
+++ b/docs/schemas/secret.rng
@@ -37,6 +37,7 @@
   
   
   
+  
   
 
   
@@ -81,4 +82,13 @@
 
   
 
+  
+
+  vtpm
+
+
+  
+
+  
+
 
diff --git a/include/libvirt/libvirt-secret.h b/include/libvirt/libvirt-secret.h
index 9a1065f0f3..e5aaac9450 100644
--- a/include/libvirt/libvirt-secret.h
+++ b/include/libvirt/libvirt-secret.h
@@ -43,6 +43,7 @@ typedef enum {
 VIR_SECRET_USAGE_TYPE_CEPH = 2,
 VIR_SECRET_USAGE_TYPE_ISCSI = 3,
 VIR_SECRET_USAGE_TYPE_TLS = 4,
+VIR_SECRET_USAGE_TYPE_VTPM = 5,
 
 # ifdef VIR_ENUM_SENTINELS
 VIR_SECRET_USAGE_TYPE_LAST
diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c
index 5b85a7c0be..b291339e77 100644
--- a/src/conf/secret_conf.c
+++ b/src/conf/secret_conf.c
@@ -110,6 +110,15 @@ virSecretDefParseUsage(xmlXPathContextPtr ctxt,
 }
 break;
 
+case VIR_SECRET_USAGE_TYPE_VTPM:
+def->usage_id = virXPathString("string(./usage/name)", ctxt);
+if (!def->usage_id) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("vTPM usage specified, but name is missing"));
+return -1;
+}
+break;
+
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected secret usage type %d"),
@@ -257,6 +266,10 @@ virSecretDefFormatUsage(virBufferPtr buf,
 virBufferEscapeString(buf, "%s\n", def->usage_id);
 break;
 
+case VIR_SECRET_USAGE_TYPE_VTPM:
+virBufferEscapeString(buf, "%s\n", def->usage_id);
+break;
+
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected secret usage type %d"),
diff --git a/src/util/virsecret.c b/src/util/virsecret.c
index 854dc72b06..7844a76a56 100644
--- a/src/util/virsecret.c
+++ b/src/util/virsecret.c
@@ -34,7 +34,7 @@ VIR_LOG_INIT("util.secret");
 
 VIR_ENUM_IMPL(virSecretUsage,
   VIR_SECRET_USAGE_TYPE_LAST,
-  "none", "volume", "ceph", "iscsi", "tls",
+  "none", "volume", "ceph", "iscsi", "tls", "vtpm",
 );
 
 void
diff --git a/tests/secretxml2xmlin/usage-vtpm.xml 
b/tests/secretxml2xmlin/usage-vtpm.xml
new file mode 100644
index 00..5baff3034d
--- /dev/null
+++ b/tests/secretxml2xmlin/usage-vtpm.xml
@@ -0,0 +1,7 @@
+
+  aa6c7af2-45a7-477c-85a2-fe86d9f2514e
+  vTPM secret
+  
+vTPMvTPMvTPM
+  
+
diff --git a/tests/secretxml2xmltest.c b/tests/secretxml2xmltest.c
index fd93703424..595583346a 100644
--- a/tests/secretxml2xmltest.c
+++ b/tests/secretxml2xmltest.c
@@ -80,6 +80,7 @@ mymain(void)
 DO_TEST("usage-ceph");
 DO_TEST("usage-iscsi");
 DO_TEST("usage-tls");
+DO_TEST("usage-vtpm");
 
 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 05/21] schema: Extend the TPM XML schema with support for encryption

2019-07-10 Thread Stefan Berger
Extend the TPM XML schema with support for an encryption node.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 docs/schemas/domaincommon.rng | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 31db599ab9..4a4f4f8a4d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4316,6 +4316,7 @@
   
  emulator
   
+  
 
   
   
@@ -4345,6 +4346,35 @@
 
   
 
+  
+
+  
+
+  vtpm
+
+
+  
+
+  
+
+  
+
+  
+
+  passphrase
+
+  
+  
+
+  
+
+
+  
+
+  
+
+  
+
   
 
   
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 00/21] Add support for vTPM state encryption

2019-07-10 Thread 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:


  

  

  
  


The vTPM secret holding the passphrase looks like this:


  2c9ceaba-c6ef-4f38-86fd-6e3adb2df5cd
  vTPM passphrase example
  
vtpm_example
  



The swtpm v0.2 (upcoming) 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

Stefan Berger (21):
  secret: Add support for usage type vTPM, extend schema and test case
  tests: Add already existing test case tpm-emulator-tpm2
  util: Add VIR_STORAGE_ENCRYPTION_FORMAT_VTPM
  conf: Extend TPM XML parser with encryption support
  schema: Extend the TPM XML schema with support for encryption
  tests: Add test for TPM XML encryption parser and formatter
  tests: Add tests for QEMU command line generation with encrypted TPM
  tpm: Move virtpm.c from utils dir to own tpm dir
  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: Write a maximum of MAX_PIPE_FEED_BYTES into a pipe
  utils: Extend virCommandProcessIO to including the send buffers
  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 |  16 +
 docs/formatsecret.html.in |  61 +++-
 docs/schemas/domaincommon.rng |  30 ++
 docs/schemas/secret.rng   |  10 +
 include/libvirt/libvirt-secret.h  |   1 +
 po/POTFILES   |   2 +-
 src/Makefile.am   |   1 +
 src/conf/Makefile.inc.am  |   7 +
 src/conf/domain_conf.c|  96 +-
 src/conf/domain_conf.h|   5 +
 src/conf/secret_conf.c|  13 +
 src/conf/virtpm_conf.c|  36 ++
 src/conf/virtpm_conf.h|  36 ++
 src/libvirt_private.syms  |  21 +-
 src/qemu/Makefile.inc.am  |   1 +
 src/qemu/qemu_block.c |   1 +
 src/qemu/qemu_driver.c|  28 ++
 src/qemu/qemu_extdevice.c |   2 +-
 src/qemu/qemu_extdevice.h |   3 +
 src/qemu/qemu_tpm.c   | 197 ++-
 src/security/Makefile.inc.am  |   1 +
 src/tpm/Makefile.inc.am   |  20 ++
 src/tpm/virtpm.c  | 325 ++
 src/{util => tpm}/virtpm.h|   8 +
 src/util/Makefile.inc.am  |   2 -
 src/util/vircommand.c | 139 +++-
 src/util/vircommand.h |   5 +
 src/util/virsecret.c  |   2 +-
 src/util/virstorageencryption.c   |   2 +-
 src/util/virstorageencryption.h   |   1 +
 src/util/virtpm.c |  74 
 tests/Makefile.am |   1 +
 .../tpm-emulator-tpm2-enc.x86_64-latest.args  |  35 ++
 .../tpm-emulator-tpm2-enc.xml |  34 ++
 tests/qemuxml2argvtest.c  |   1 +
 .../tpm-emulator-tpm2-enc.xml |  38 ++
 tests/qemuxml2xmltest.c   |   2 +
 tests/secretxml2xmlin/usage-vtpm.xml  |   7 +
 tests/secretxml2xmltest.c |   1 +
 39 files changed, 1099 insertions(+), 166 deletions(-)
 create mode 100644 src/conf/virtpm_conf.c
 create mode 100644 src/conf/virtpm_conf.h
 create mode 100644 src/tpm/Makefile.inc.am
 create mode 100644 src/tpm/virtpm.c
 rename src/{util => tpm}/virtpm.h (77%)
 delete mode 100644 src/util/virtpm.c
 create mode 100644 
tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.x86_64-latest.args
 

[libvirt] [PATCH v2 09/21] tpm: Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c

2019-07-10 Thread Stefan Berger
Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c and introduce
a few functions to query the executables needed for virCommands.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/libvirt_private.syms |  4 ++
 src/qemu/qemu_tpm.c  | 83 
 src/tpm/virtpm.c | 91 
 src/tpm/virtpm.h |  5 +++
 4 files changed, 108 insertions(+), 75 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e29007cab1..e33d7d9f14 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1447,6 +1447,10 @@ virSecurityManagerVerify;
 
 # tpm/virtpm.h
 virTPMCreateCancelPath;
+virTPMEmulatorInit;
+virTPMGetSwtpm;
+virTPMGetSwtpmIoctl;
+virTPMGetSwtpmSetup;
 
 
 # util/viralloc.h
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index cc8c69433b..61b4f72320 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -41,79 +41,12 @@
 #include "configmake.h"
 #include "dirname.h"
 #include "qemu_tpm.h"
+#include "virtpm.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 VIR_LOG_INIT("qemu.tpm");
 
-/*
- * executables for the swtpm; to be found on the host
- */
-static char *swtpm_path;
-static char *swtpm_setup;
-static char *swtpm_ioctl;
-
-/*
- * qemuTPMEmulatorInit
- *
- * Initialize the Emulator functions by searching for necessary
- * executables that we will use to start and setup the swtpm
- */
-static int
-qemuTPMEmulatorInit(void)
-{
-if (!swtpm_path) {
-swtpm_path = virFindFileInPath("swtpm");
-if (!swtpm_path) {
-virReportSystemError(ENOENT, "%s",
- _("Unable to find 'swtpm' binary in $PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_path)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("TPM emulator %s is not an executable"),
-   swtpm_path);
-VIR_FREE(swtpm_path);
-return -1;
-}
-}
-
-if (!swtpm_setup) {
-swtpm_setup = virFindFileInPath("swtpm_setup");
-if (!swtpm_setup) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find 'swtpm_setup' in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_setup)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("'%s' is not an executable"),
-   swtpm_setup);
-VIR_FREE(swtpm_setup);
-return -1;
-}
-}
-
-if (!swtpm_ioctl) {
-swtpm_ioctl = virFindFileInPath("swtpm_ioctl");
-if (!swtpm_ioctl) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find swtpm_ioctl in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_ioctl)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("swtpm_ioctl program %s is not an executable"),
-   swtpm_ioctl);
-VIR_FREE(swtpm_ioctl);
-return -1;
-}
-}
-
-return 0;
-}
-
-
 /*
  * qemuTPMCreateEmulatorStoragePath
  *
@@ -350,7 +283,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
 if (!pidfile)
 return -ENOMEM;
 
-ret = virPidFileReadPathIfAlive(pidfile, pid, swtpm_path);
+ret = virPidFileReadPathIfAlive(pidfile, pid, virTPMGetSwtpm());
 
 VIR_FREE(pidfile);
 
@@ -386,7 +319,7 @@ qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
 {
 int ret = -1;
 
-if (qemuTPMEmulatorInit() < 0)
+if (virTPMEmulatorInit() < 0)
 return -1;
 
 /* create log dir ... allow 'tss' user to cd into it */
@@ -478,7 +411,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
  "this requires privileged mode for a "
  "TPM 1.2\n"), 0600);
 
-cmd = virCommandNew(swtpm_setup);
+cmd = virCommandNew(virTPMGetSwtpmSetup());
 if (!cmd)
 goto cleanup;
 
@@ -518,7 +451,7 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not run '%s'. exitstatus: %d; "
  "Check error log '%s' for details."),
-  swtpm_setup, exitstatus, logfile);
+  virTPMGetSwtpmSetup(), exitstatus, logfile);
 goto cleanup;
 }
 
@@ -575,7 +508,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 
 unlink(tpm->data.emulator.source.data.nix.path);
 
-cmd = virCommandNew(swtpm_path);
+cmd = virCommandNew(virTPMGetSwtpm());
 if (!cmd)
 goto error;
 
@@ -640,7 +573,7 @@ qemuTPMEmulatorStop(const char *swtpmStateDir,
 char *pathname;
 char *errbuf = NULL;
 
-if (qemuTPMEmulatorInit() < 0)
+if (virTPMEmulatorInit() < 0)
 return;
 
 if 

[libvirt] [PATCH v2 04/21] conf: Extend TPM XML parser with encryption support

2019-07-10 Thread Stefan Berger
Extend the TPM device XML parser and XML generator with emulator
state encryption support.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/conf/domain_conf.c | 40 +++-
 src/conf/domain_conf.h |  1 +
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3323c9a5b1..df6238c299 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2950,6 +2950,7 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def)
 virDomainChrSourceDefClear(>data.emulator.source);
 VIR_FREE(def->data.emulator.storagepath);
 VIR_FREE(def->data.emulator.logfile);
+virStorageEncryptionFree(def->data.emulator.encryption);
 break;
 case VIR_DOMAIN_TPM_TYPE_LAST:
 break;
@@ -13048,6 +13049,16 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr 
xmlopt,
  * 
  *   
  * 
+ *
+ * Emulator state encryption is supported with the following:
+ *
+ * 
+ *   
+ * 
+ *
+ * 
+ *   
+ * 
  */
 static virDomainTPMDefPtr
 virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
@@ -13063,6 +13074,7 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
 VIR_AUTOFREE(char *) backend = NULL;
 VIR_AUTOFREE(char *) version = NULL;
 VIR_AUTOFREE(xmlNodePtr *) backends = NULL;
+xmlNodePtr encnode = NULL;
 
 if (VIR_ALLOC(def) < 0)
 return NULL;
@@ -13126,6 +13138,21 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt,
 def->data.passthrough.source.type = VIR_DOMAIN_CHR_TYPE_DEV;
 break;
 case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+encnode = virXPathNode("./backend/encryption", ctxt);
+if (encnode) {
+def->data.emulator.encryption =
+   virStorageEncryptionParseNode(encnode, ctxt);
+if (!def->data.emulator.encryption)
+goto error;
+if (def->data.emulator.encryption->format !=
+VIR_STORAGE_ENCRYPTION_FORMAT_VTPM) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("Unsupported vTPM encryption type '%s'"),
+   virStorageEncryptionFormatTypeToString(
+   def->data.emulator.encryption->format));
+goto error;
+}
+}
 break;
 case VIR_DOMAIN_TPM_TYPE_LAST:
 goto error;
@@ -25949,8 +25976,19 @@ virDomainTPMDefFormat(virBufferPtr buf,
 virBufferAddLit(buf, "\n");
 break;
 case VIR_DOMAIN_TPM_TYPE_EMULATOR:
-virBufferAsprintf(buf, " version='%s'/>\n",
+virBufferAsprintf(buf, " version='%s'",
   virDomainTPMVersionTypeToString(def->version));
+if (def->data.emulator.encryption) {
+virBufferAddLit(buf, ">\n");
+virBufferAdjustIndent(buf, 2);
+if (virStorageEncryptionFormat(buf,
+   def->data.emulator.encryption) < 0)
+return -1;
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+} else {
+virBufferAddLit(buf, "/>\n");
+}
 break;
 case VIR_DOMAIN_TPM_TYPE_LAST:
 break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c1b5fc1337..a03986623a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1270,6 +1270,7 @@ struct _virDomainTPMDef {
 virDomainChrSourceDef source;
 char *storagepath;
 char *logfile;
+virStorageEncryptionPtr encryption;
 } emulator;
 } data;
 };
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 02/21] tests: Add already existing test case tpm-emulator-tpm2

2019-07-10 Thread Stefan Berger
Add an already existing test case tpm-emulator-tpm2 to qemuxml2xmltest.c

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 tests/qemuxml2xmltest.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index a64b17ac28..a29958ae29 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -653,6 +653,7 @@ mymain(void)
 DO_TEST("tpm-passthrough", NONE);
 DO_TEST("tpm-passthrough-crb", NONE);
 DO_TEST("tpm-emulator", NONE);
+DO_TEST("tpm-emulator-tpm2", NONE);
 
 DO_TEST("metadata", NONE);
 DO_TEST("metadata-duplicate", NONE);
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 17/21] tpm: Use fd to pass password to swtpm_setup and swtpm

2019-07-10 Thread Stefan Berger
Allow vTPM state encryption when swtpm_setup and swtpm support
passing a passphrase using a file descriptor.

This patch enables the encryption of the vTPM state only. It does
not encrypt the state during migration, so the destination secret
does not need to have the same password at this point.

Signed-off-by: Stefan Berger 
---
 src/libvirt_private.syms |   2 +
 src/qemu/qemu_tpm.c  | 104 ++-
 src/tpm/virtpm.c |  16 ++
 src/tpm/virtpm.h |   3 ++
 4 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3feb862fb4..804d244313 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1456,6 +1456,8 @@ virTPMEmulatorInit;
 virTPMGetSwtpm;
 virTPMGetSwtpmIoctl;
 virTPMGetSwtpmSetup;
+virTPMSwtpmCapsGet;
+virTPMSwtpmSetupCapsGet;
 
 
 # util/viralloc.h
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index 2afa8db448..a8cec0d873 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -43,6 +43,8 @@
 #include "dirname.h"
 #include "qemu_tpm.h"
 #include "virtpm.h"
+#include "secret_util.h"
+#include "virtpm_conf.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -372,6 +374,63 @@ qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
 return ret;
 }
 
+/*
+ * qemuTPMSetupEncryption
+ *
+ * @encryption: pointer to virStorageEncryption holding secret
+ * @cmd: the virCommand to transfer the secret to
+ *
+ * Returns file descriptor representing the read-end of a pipe.
+ * The passphrase can be read from this pipe. Returns < 0 in case
+ * of error.
+ *
+ * This function reads the passphrase and writes it into the
+ * write-end of a pipe so that the read-end of the pipe can be
+ * passed to the emulator for reading the passphrase from.
+ */
+static int
+qemuTPMSetupEncryption(virStorageEncryptionPtr encryption,
+   virCommandPtr cmd)
+{
+int ret = -1;
+int pipefd[2] = { -1, -1 };
+virConnectPtr conn;
+VIR_AUTOFREE(uint8_t *) secret = NULL;
+size_t secret_len;
+
+conn = virGetConnectSecret();
+if (!conn)
+return -1;
+
+if (virSecretGetSecretString(conn, >secrets[0]->seclookupdef,
+ VIR_SECRET_USAGE_TYPE_VTPM,
+ , _len) < 0)
+goto error;
+
+if (pipe(pipefd) == -1) {
+virReportSystemError(errno, "%s",
+ _("Unable to create pipe"));
+goto error;
+}
+
+if (virCommandSetSendBuffer(cmd, pipefd[1], secret, secret_len) < 0)
+goto error;
+
+secret = NULL;
+ret = pipefd[0];
+
+ cleanup:
+virObjectUnref(conn);
+
+return ret;
+
+ error:
+VIR_FREE(secret);
+VIR_FORCE_CLOSE(pipefd[1]);
+VIR_FORCE_CLOSE(pipefd[0]);
+
+goto cleanup;
+}
 
 /*
  * qemuTPMEmulatorRunSetup
@@ -386,6 +445,7 @@ qemuTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm,
  * @logfile: The file to write the log into; it must be writable
  *   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
  *
  * Setup the external swtpm by creating endorsement key and
  * certificates for it.
@@ -398,13 +458,15 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
 uid_t swtpm_user,
 gid_t swtpm_group,
 const char *logfile,
-const virDomainTPMVersion tpmversion)
+const virDomainTPMVersion tpmversion,
+virStorageEncryptionPtr encryption)
 {
 virCommandPtr cmd = NULL;
 int exitstatus;
 int ret = -1;
 char uuid[VIR_UUID_STRING_BUFLEN];
 char *vmid = NULL;
+VIR_AUTOCLOSE pwdfile_fd = -1;
 
 if (!privileged && tpmversion == VIR_DOMAIN_TPM_VERSION_1_2)
 return virFileWriteStr(logfile,
@@ -434,6 +496,23 @@ qemuTPMEmulatorRunSetup(const char *storagepath,
 break;
 }
 
+if (encryption) {
+if (!virTPMSwtpmSetupCapsGet(
+VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD)) {
+virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+_("%s does not support passing a passphrase using a file "
+  "descriptor"), virTPMGetSwtpmSetup());
+goto cleanup;
+}
+if ((pwdfile_fd = qemuTPMSetupEncryption(encryption, cmd)) < 0)
+goto cleanup;
+
+virCommandAddArg(cmd, "--pwdfile-fd");
+virCommandAddArgFormat(cmd, "%d", pwdfile_fd);
+virCommandAddArgList(cmd, "--cipher", "aes-256-cbc", NULL);
+virCommandPassFD(cmd, pwdfile_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+pwdfile_fd = -1;
+}
 
 virCommandAddArgList(cmd,
  "--tpm-state", storagepath,
@@ -496,6 +575,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 virCommandPtr cmd = NULL;
 bool created 

[libvirt] [PATCH v2 16/21] utils: Extend virCommandProcessIO to including the send buffers

2019-07-10 Thread Stefan Berger
Signed-off-by: Stefan Berger 
---
 src/util/vircommand.c | 70 ++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 0e367eeeab..357a9888a1 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -1803,6 +1803,69 @@ virCommandSetSendBuffer(virCommandPtr cmd,
 }
 
 
+static int
+virCommandGetNumSendBuffers(virCommandPtr cmd)
+{
+return cmd->numSendBuffers;
+}
+
+
+static int
+virCommandAddSendBuffersFillPollfd(virCommandPtr cmd,
+   struct pollfd *fds,
+   int startidx)
+{
+size_t i, j;
+
+for (i = 0, j = 0; i < cmd->numSendBuffers; i++) {
+if (cmd->sendBuffers[i].fd >= 0) {
+fds[startidx + j].fd = cmd->sendBuffers[i].fd;
+fds[startidx + j].events = POLLOUT;
+fds[startidx + j].revents = 0;
+j++;
+}
+}
+
+return j;
+}
+
+
+static int
+virCommandSendBuffersHandlePoll(virCommandPtr cmd,
+struct pollfd *fds)
+{
+size_t i;
+int done;
+
+for (i = 0; i < cmd->numSendBuffers; i++) {
+if (fds->fd == cmd->sendBuffers[i].fd)
+break;
+}
+if (i == cmd->numSendBuffers)
+return 0;
+
+done = write(fds->fd,
+ cmd->sendBuffers[i].buffer + cmd->sendBuffers[i].offset,
+ MIN(cmd->sendBuffers[i].buflen - cmd->sendBuffers[i].offset,
+ MAX_PIPE_FEED_BYTES));
+if (done < 0) {
+if (errno == EPIPE) {
+VIR_DEBUG("child closed PIPE early, ignoring EPIPE "
+  "on fd %d", cmd->sendBuffers[i].fd);
+VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+} else if (errno != EINTR && errno != EAGAIN) {
+virReportSystemError(errno, "%s",
+ _("unable to write to child input"));
+return -1;
+}
+} else {
+cmd->sendBuffers[i].offset += done;
+if (cmd->sendBuffers[i].offset == cmd->sendBuffers[i].buflen)
+VIR_FORCE_CLOSE(cmd->sendBuffers[i].fd);
+}
+return 0;
+}
+
 /**
  * virCommandSetInputBuffer:
  * @cmd: the command to modify
@@ -2157,7 +2220,7 @@ virCommandProcessIO(virCommandPtr cmd)
 goto cleanup;
 ret = -1;
 
-if (VIR_ALLOC_N(fds, 3) < 0)
+if (VIR_ALLOC_N(fds, 3 + virCommandGetNumSendBuffers(cmd)) < 0)
 goto cleanup;
 
 for (;;) {
@@ -2183,6 +2246,8 @@ virCommandProcessIO(virCommandPtr cmd)
 nfds++;
 }
 
+nfds += virCommandAddSendBuffersFillPollfd(cmd, fds, nfds);
+
 if (nfds == 0)
 break;
 
@@ -2255,6 +2320,9 @@ virCommandProcessIO(virCommandPtr cmd)
 if (inoff == inlen)
 VIR_FORCE_CLOSE(cmd->inpipe);
 }
+} else if (fds[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
+if (virCommandSendBuffersHandlePoll(cmd, [i]) < 0)
+goto cleanup;
 }
 }
 }
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 18/21] tpm: Pass migration key passphrase via fd to swtpm

2019-07-10 Thread Stefan Berger
This patch now passes the passphrase as a migration key to swtpm.
This now encrypts the state of the TPM while a VM is migrated between
hosts or when suspended into a file. Since the migration key secret
is the same as the state encryption secret, this now requires that
the migration destination host has the same secret value.

Signed-off-by: Stefan Berger 
---
 src/qemu/qemu_tpm.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
index a8cec0d873..7362df8b4d 100644
--- a/src/qemu/qemu_tpm.c
+++ b/src/qemu/qemu_tpm.c
@@ -576,6 +576,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 bool created = false;
 char *pidfile;
 VIR_AUTOCLOSE pwdfile_fd = -1;
+VIR_AUTOCLOSE migpwdfile_fd = -1;
 
 if (qemuTPMCreateEmulatorStorage(tpm->data.emulator.storagepath,
  , swtpm_user, swtpm_group) < 0)
@@ -637,7 +638,9 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
 }
 
 pwdfile_fd = qemuTPMSetupEncryption(tpm->data.emulator.encryption, 
cmd);
-if (pwdfile_fd < 0)
+migpwdfile_fd = qemuTPMSetupEncryption(tpm->data.emulator.encryption,
+   cmd);
+if (pwdfile_fd < 0 || migpwdfile_fd < 0)
 goto error;
 
 virCommandAddArg(cmd, "--key");
@@ -645,6 +648,12 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm,
pwdfile_fd);
 virCommandPassFD(cmd, pwdfile_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
 pwdfile_fd = -1;
+
+virCommandAddArg(cmd, "--migration-key");
+virCommandAddArgFormat(cmd, "pwdfd=%d,mode=aes-256-cbc,kdf=pbkdf2",
+   migpwdfile_fd);
+virCommandPassFD(cmd, migpwdfile_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+migpwdfile_fd = -1;
 }
 
 return cmd;
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 12/21] tpm: Parse the capabilities supported by swtpm and swtpm_setup

2019-07-10 Thread Stefan Berger
Run 'swtpm socket --print-capabilities' and
'swtpm_setup --print-capabilities' to get the JSON object of the
features the programs are supporting and parse them into a bitmap.

Signed-off-by: Stefan Berger 
---
 src/conf/Makefile.inc.am |   6 ++
 src/conf/virtpm_conf.c   |  36 
 src/conf/virtpm_conf.h   |  36 
 src/libvirt_private.syms |   5 ++
 src/tpm/Makefile.inc.am  |   5 +-
 src/tpm/virtpm.c | 124 +--
 6 files changed, 207 insertions(+), 5 deletions(-)
 create mode 100644 src/conf/virtpm_conf.c
 create mode 100644 src/conf/virtpm_conf.h

diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index 08c7c9da7f..e42425fcc5 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -153,6 +153,11 @@ DEVICE_CONF_SOURCES = \
conf/device_conf.h \
$(NULL)
 
+TPM_CONF_SOURCES = \
+   conf/virtpm_conf.c \
+   conf/virtpm_conf.h \
+   $(NULL)
+
 CONF_SOURCES = \
$(NETDEV_CONF_SOURCES) \
$(DOMAIN_CONF_SOURCES) \
@@ -171,6 +176,7 @@ CONF_SOURCES = \
$(CPU_CONF_SOURCES) \
$(CHRDEV_CONF_SOURCES) \
$(DEVICE_CONF_SOURCES) \
+   $(TPM_CONF_SOURCES) \
$(NULL)
 
 noinst_LTLIBRARIES += libvirt_conf.la
diff --git a/src/conf/virtpm_conf.c b/src/conf/virtpm_conf.c
new file mode 100644
index 00..12e69e67b3
--- /dev/null
+++ b/src/conf/virtpm_conf.c
@@ -0,0 +1,36 @@
+/*
+ * virtpm_conf.c: vTPM XML processing
+ *
+ * Copyright (C) 2019 IBM Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * .
+ */
+
+#include 
+
+#include "virenum.h"
+#include "virtpm_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_ENUM_IMPL(virTPMSwtpmFeature,
+  VIR_TPM_SWTPM_FEATURE_LAST,
+  "cmdarg-pwd-fd",
+);
+
+VIR_ENUM_IMPL(virTPMSwtpmSetupFeature,
+  VIR_TPM_SWTPM_SETUP_FEATURE_LAST,
+  "cmdarg-pwdfile-fd",
+);
diff --git a/src/conf/virtpm_conf.h b/src/conf/virtpm_conf.h
new file mode 100644
index 00..73c6c67271
--- /dev/null
+++ b/src/conf/virtpm_conf.h
@@ -0,0 +1,36 @@
+/*
+ * virtpm_conf.h: vTPM XML processing
+ *
+ * Copyright (C) 2019 IBM Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * .
+ */
+
+#pragma once
+
+typedef enum {
+VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD,
+
+VIR_TPM_SWTPM_FEATURE_LAST
+} virTPMSwtpmFeature;
+
+typedef enum {
+VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD,
+
+VIR_TPM_SWTPM_SETUP_FEATURE_LAST
+} virTPMSwtpmSetupFeature;
+
+VIR_ENUM_DECL(virTPMSwtpmFeature);
+VIR_ENUM_DECL(virTPMSwtpmSetupFeature);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e33d7d9f14..d2045895a1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1236,6 +1236,11 @@ virStoragePoolObjVolumeGetNames;
 virStoragePoolObjVolumeListExport;
 
 
+# conf/virtpm_conf.h
+virTPMSwtpmFeatureTypeFromString;
+virTPMSwtpmSetupFeatureTypeFromString;
+
+
 # cpu/cpu.h
 cpuDecode;
 cpuEncode;
diff --git a/src/tpm/Makefile.inc.am b/src/tpm/Makefile.inc.am
index 1f5131bf34..d8a15c406c 100644
--- a/src/tpm/Makefile.inc.am
+++ b/src/tpm/Makefile.inc.am
@@ -12,6 +12,9 @@ EXTRA_DIST += \
 
 noinst_LTLIBRARIES += libvirt_tpm.la
 libvirt_la_BUILT_LIBADD += libvirt_tpm.la
-libvirt_tpm_la_CFLAGS = $(AM_CFLAGS)
+libvirt_tpm_la_CFLAGS = \
+   -I$(srcdir)/conf \
+   $(AM_CFLAGS) \
+   $(NULL)
 libvirt_tpm_la_LDFLAGS = $(AM_LDFLAGS)
 libvirt_tpm_la_SOURCES = $(TPM_UTIL_SOURCES)
diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c
index e4735f9c4d..e2c2960a01 100644
--- a/src/tpm/virtpm.c
+++ b/src/tpm/virtpm.c
@@ -27,6 +27,10 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virtpm.h"
+#include 

[libvirt] [PATCH v2 06/21] tests: Add test for TPM XML encryption parser and formatter

2019-07-10 Thread Stefan Berger
Add a test case for the TPM XML encryption parser and formatter.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 .../tpm-emulator-tpm2-enc.xml | 34 +
 .../tpm-emulator-tpm2-enc.xml | 38 +++
 tests/qemuxml2xmltest.c   |  1 +
 3 files changed, 73 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
 create mode 100644 tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml

diff --git a/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml 
b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
new file mode 100644
index 00..3838518e65
--- /dev/null
+++ b/tests/qemuxml2argvdata/tpm-emulator-tpm2-enc.xml
@@ -0,0 +1,34 @@
+
+  TPM-VM
+  11d7cd22-da89-3094-6212-079a48a309a1
+  2097152
+  512288
+  1
+  
+hvm
+
+
+  
+  
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+
+
+
+
+  
+
+  
+
+  
+
+
+  
+
diff --git a/tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml 
b/tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml
new file mode 100644
index 00..7083fc9c13
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/tpm-emulator-tpm2-enc.xml
@@ -0,0 +1,38 @@
+
+  TPM-VM
+  11d7cd22-da89-3094-6212-079a48a309a1
+  2097152
+  512288
+  1
+  
+hvm
+
+
+  
+  
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+
+
+
+
+
+  
+
+  
+
+  
+
+
+  
+
+  
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index a29958ae29..f6cd56cc8f 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -654,6 +654,7 @@ mymain(void)
 DO_TEST("tpm-passthrough-crb", NONE);
 DO_TEST("tpm-emulator", NONE);
 DO_TEST("tpm-emulator-tpm2", NONE);
+DO_TEST("tpm-emulator-tpm2-enc", NONE);
 
 DO_TEST("metadata", NONE);
 DO_TEST("metadata-duplicate", NONE);
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 14/21] utils: Convert pollfd array to be allocated

2019-07-10 Thread Stefan Berger
Convert the struct pollfd *fds to be allocated rather than residing
on the stack.

Signed-off-by: Stefan Berger 
---
 src/util/vircommand.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index e32377497b..898ee0df45 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -2123,6 +2123,7 @@ virCommandProcessIO(virCommandPtr cmd)
 size_t inlen = 0, outlen = 0, errlen = 0;
 size_t inoff = 0;
 int ret = 0;
+VIR_AUTOFREE(struct pollfd *) fds = NULL;
 
 if (dryRunBuffer || dryRunCallback) {
 VIR_DEBUG("Dry run requested, skipping I/O processing");
@@ -2154,9 +2155,11 @@ virCommandProcessIO(virCommandPtr cmd)
 goto cleanup;
 ret = -1;
 
+if (VIR_ALLOC_N(fds, 3) < 0)
+goto cleanup;
+
 for (;;) {
 size_t i;
-struct pollfd fds[3];
 int nfds = 0;
 
 if (cmd->inpipe != -1) {
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 10/21] tpm: Refactor virTPMEmulatorInit to use loop

2019-07-10 Thread Stefan Berger
Refactor virTPMEmulatorInit to use a loop with parameters. This allows
for easier extension later on.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
 src/tpm/virtpm.c | 80 ++--
 1 file changed, 37 insertions(+), 43 deletions(-)

diff --git a/src/tpm/virtpm.c b/src/tpm/virtpm.c
index 4635d8add0..0179b1e8be 100644
--- a/src/tpm/virtpm.c
+++ b/src/tpm/virtpm.c
@@ -113,51 +113,45 @@ virTPMGetSwtpmIoctl(void)
 int
 virTPMEmulatorInit(void)
 {
-if (!swtpm_path) {
-swtpm_path = virFindFileInPath("swtpm");
-if (!swtpm_path) {
-virReportSystemError(ENOENT, "%s",
- _("Unable to find 'swtpm' binary in $PATH"));
-return -1;
+static const struct {
+const char *name;
+char **path;
+} prgs[] = {
+{
+.name = "swtpm",
+.path = _path,
+},
+{
+.name = "swtpm_setup",
+.path = _setup,
+},
+{
+.name = "swtpm_ioctl",
+.path = _ioctl,
 }
-if (!virFileIsExecutable(swtpm_path)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("TPM emulator %s is not an executable"),
-   swtpm_path);
-VIR_FREE(swtpm_path);
-return -1;
-}
-}
-
-if (!swtpm_setup) {
-swtpm_setup = virFindFileInPath("swtpm_setup");
-if (!swtpm_setup) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find 'swtpm_setup' in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_setup)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("'%s' is not an executable"),
-   swtpm_setup);
-VIR_FREE(swtpm_setup);
-return -1;
-}
-}
+};
+size_t i;
 
-if (!swtpm_ioctl) {
-swtpm_ioctl = virFindFileInPath("swtpm_ioctl");
-if (!swtpm_ioctl) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Could not find swtpm_ioctl in PATH"));
-return -1;
-}
-if (!virFileIsExecutable(swtpm_ioctl)) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("swtpm_ioctl program %s is not an executable"),
-   swtpm_ioctl);
-VIR_FREE(swtpm_ioctl);
-return -1;
+for (i = 0; i < ARRAY_CARDINALITY(prgs); i++) {
+char *path;
+bool findit = *prgs[i].path == NULL;
+
+if (findit) {
+path = virFindFileInPath(prgs[i].name);
+if (!path) {
+virReportSystemError(ENOENT,
+_("Unable to find '%s' binary in $PATH"),
+prgs[i].name);
+return -1;
+}
+if (!virFileIsExecutable(path)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("%s is not an executable"),
+   path);
+VIR_FREE(path);
+return -1;
+}
+*prgs[i].path = path;
 }
 }
 
-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2] logging: ensure virtlogd rollover takes priority over logrotate

2019-07-10 Thread Daniel P . Berrangé
The virtlogd config is set to rollover logs every 2 MB.

Normally a logrotate config file is also installed to handle cases where
virtlogd is disabled. This is set to rollover weekly with no size
constraint.

As a result logrotate can interfere with virtlogd's, rolling over files
that virtlogd has already taken care of.

This changes logrotate configs to rollover based on a max size
constraint of 2 MB + 1 byte. When virtlogd is running the log files will
never get this large, making logrotate a no-op.

If the user changes the size in virtlogd's config to something larger,
they are responsible for also changing the logrotate config suitably.

The LXC driver doesn't use virtlogd, but its logrotate config is altered
to match the QEMU driver logrotate, just for the sake of consistency.

Signed-off-by: Daniel P. Berrangé 
---
 src/logging/virtlogd.conf  |  6 ++
 src/remote/libvirtd.libxl.logrotate.in |  2 +-
 src/remote/libvirtd.lxc.logrotate.in   |  2 +-
 src/remote/libvirtd.qemu.logrotate.in  | 10 +-
 4 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/logging/virtlogd.conf b/src/logging/virtlogd.conf
index 72da7f0705..bc41edbc6b 100644
--- a/src/logging/virtlogd.conf
+++ b/src/logging/virtlogd.conf
@@ -90,6 +90,12 @@
 #admin_max_clients = 5
 
 # Maximum file size before rolling over. Defaults to 2 MB
+#
+# Beware that a logrotate config file might be installed too,
+# to handle cases where virtlogd is disabled. To ensure that
+# the logrotate config is a no-op when virtlogd is running,
+# make sure that max_size here is smaller than size listed
+# in the logrotate config.
 #max_size = 2097152
 
 # Maximum number of backup files to keep. Defaults to 3,
diff --git a/src/remote/libvirtd.libxl.logrotate.in 
b/src/remote/libvirtd.libxl.logrotate.in
index cb7f07d846..1461c1efa1 100644
--- a/src/remote/libvirtd.libxl.logrotate.in
+++ b/src/remote/libvirtd.libxl.logrotate.in
@@ -1,5 +1,5 @@
 @localstatedir@/log/libvirt/libxl/*.log {
-weekly
+size 2097153
 missingok
 rotate 4
 compress
diff --git a/src/remote/libvirtd.lxc.logrotate.in 
b/src/remote/libvirtd.lxc.logrotate.in
index 2bb9dfba12..b88dabb58e 100644
--- a/src/remote/libvirtd.lxc.logrotate.in
+++ b/src/remote/libvirtd.lxc.logrotate.in
@@ -1,5 +1,5 @@
 @localstatedir@/log/libvirt/lxc/*.log {
-weekly
+size 2097153
 missingok
 rotate 4
 compress
diff --git a/src/remote/libvirtd.qemu.logrotate.in 
b/src/remote/libvirtd.qemu.logrotate.in
index cdb399ef23..78f2ca875e 100644
--- a/src/remote/libvirtd.qemu.logrotate.in
+++ b/src/remote/libvirtd.qemu.logrotate.in
@@ -1,5 +1,13 @@
 @localstatedir@/log/libvirt/qemu/*.log {
-weekly
+# The QEMU driver is configured to use virtlogd by
+# default, which will perform log rollover.
+# This logrotate config is still installed for cases
+# where the user has switched off virtlogd.
+#
+# If virtlogd is active, ensure that size here is
+# larger than 'max_size' in the virtlogd config
+# so that logrotate becomes a no-op
+size 2097153
 missingok
 rotate 4
 compress
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 05/12] nodedev: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
On Wed, Jul 10, 2019 at 07:02:08PM +0200, Michal Privoznik wrote:
> On 7/10/19 5:47 PM, Daniel P. Berrangé wrote:
> > When we allow multiple instances of the driver for the same user
> > account, using a separate root directory, we need to ensure mutual
> > exclusion. Use a pidfile to guarantee this.
> > 
> > In privileged libvirtd this ends up locking
> > 
> > /var/run/libvirt/nodedev/driver.pid
> > 
> > In unprivileged libvirtd this ends up locking
> > 
> >/run/user/$UID/libvirt/nodedev/run/driver.pid
> > 
> > NB, the latter can vary depending on $XDG_RUNTIME_DIR
> > 
> > Signed-off-by: Daniel P. Berrangé 
> > ---
> >   src/conf/virnodedeviceobj.h|  5 +
> >   src/node_device/node_device_hal.c  | 31 +
> >   src/node_device/node_device_udev.c | 32 ++
> >   3 files changed, 68 insertions(+)
> 
> Side note, isn't it time to finally kill hal backend? Is somebody still
> using it?

We were wanting Roman's confirmation that its no longer desired
for BSD.

https://www.redhat.com/archives/libvir-list/2019-May/msg00207.html

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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 4/6] test: Add various vir*Flags API

2019-07-10 Thread Eric Blake
On 7/8/19 10:37 PM, Eric Blake wrote:
> Even though we don't accept any flags, it is unfriendly to callers
> that use the modern API to have to fall back to the flag-free API.
> 
> Note that virDomainBlockStats does not trivially forward to
> virDomainBlockStatsFlags, so that one is omitted.
> 
> Signed-off-by: Eric Blake 
> ---
>  src/test/test_driver.c | 34 --
>  1 file changed, 28 insertions(+), 6 deletions(-)
> 
> diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> index 7dd448bb20..49d7030d21 100644
> --- a/src/test/test_driver.c
> +++ b/src/test/test_driver.c
> @@ -2469,12 +2469,15 @@ static int testDomainSetMaxMemory(virDomainPtr domain,
>  return 0;
>  }
> 
> -static int testDomainSetMemory(virDomainPtr domain,
> -   unsigned long memory)
> +static int testDomainSetMemoryFlags(virDomainPtr domain,
> +unsigned long memory,
> +unsigned int flags)
>  {
>  virDomainObjPtr privdom;
>  int ret = -1;
> 
> +virCheckFlags(0, -1);
> +

As discussed in v2, this should probably accept VIR_DOMAIN_AFFECT_LIVE,
and maybe even VIR_DOMAIN_AFFECT_MAXIMUM_MEMORY...


> +static int testDomainSetMemory(virDomainPtr domain,
> +   unsigned long memory)
> +{
> +return testDomainSetMemoryFlags(domain, memory, 0);

where this should pass VIR_DOMAIN_AFFECT_LIVE instead of 0, and we may
want to implement testDomainSetMaxMemory(),...


> +static int testDomainPinVcpu(virDomainPtr domain,
> + unsigned int vcpu,
> + unsigned char *cpumap,
> + int maplen)
> +{
> +return testDomainPinVcpuFlags(domain, vcpu, cpumap, maplen, 0);

and another interface that should probably pass VIR_DOMAIN_AFFECT_LIVE.

Looks like I'll be doing a v3.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 05/12] nodedev: acquire a pidfile in the driver root directory

2019-07-10 Thread Michal Privoznik

On 7/10/19 5:47 PM, Daniel P. Berrangé wrote:

When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

/var/run/libvirt/nodedev/driver.pid

In unprivileged libvirtd this ends up locking

   /run/user/$UID/libvirt/nodedev/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
  src/conf/virnodedeviceobj.h|  5 +
  src/node_device/node_device_hal.c  | 31 +
  src/node_device/node_device_udev.c | 32 ++
  3 files changed, 68 insertions(+)


Side note, isn't it time to finally kill hal backend? Is somebody still 
using it?


Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 00/12] introduce locking into every driver

2019-07-10 Thread Michal Privoznik

On 7/10/19 5:47 PM, Daniel P. Berrangé wrote:

As part of the proposal to introduce an embedded driver feature, we
decided we ought to have each driver acquire a lock against the virtual
root it is configured to use. This will prevent two apps from running an
embedded driver with the same root.

   https://www.redhat.com/archives/libvir-list/2019-May/msg00467.html

It turns out that this will also be useful for the per-driver split
daemons work I am working on. In that case libvirtd will exist as a
monolithic daemon running all drivers, and we'll also have per-driver
daemons like virtqemud, virtnetworkd, etc. It is only valid to run in
one setup on the host. ie you must choose libvirtd, or choose per-driver
daemons, never both.

The per-driver locking will provide very useful protection against
mistakes in this respect.

Since the locking is functionally independant of both patch series, I'm
sending it now.

Daniel P. Berrangé (12):
   qemu: acquire a pidfile in the driver root directory
   secrets: acquire a pidfile in the driver root directory
   network: acquire a pidfile in the driver root directory
   storage: acquire a pidfile in the driver root directory
   nodedev: acquire a pidfile in the driver root directory
   interface: acquire a pidfile in the driver root directory
   nwfilter: acquire a pidfile in the driver root directory
   libxl: remove obsolete check for xend during driver startup
   libxl: acquire a pidfile in the driver root directory
   lxc: acquire a pidfile in the driver root directory
   vz: acquire a pidfile in the driver root directory
   bhyve: acquire a pidfile in the driver root directory

  src/bhyve/bhyve_driver.c|  9 +
  src/bhyve/bhyve_utils.h |  3 ++
  src/conf/virnodedeviceobj.h |  5 +++
  src/conf/virnwfilterobj.h   |  4 +++
  src/conf/virstorageobj.h|  3 ++
  src/interface/interface_backend_netcf.c | 45 +++--
  src/interface/interface_backend_udev.c  | 44 +++-
  src/libxl/libxl_conf.h  |  3 ++
  src/libxl/libxl_driver.c| 37 
  src/lxc/lxc_conf.h  |  3 ++
  src/lxc/lxc_driver.c|  9 +
  src/network/bridge_driver.c | 10 ++
  src/network/bridge_driver_platform.h|  3 ++
  src/node_device/node_device_hal.c   | 31 +
  src/node_device/node_device_udev.c  | 32 ++
  src/nwfilter/nwfilter_driver.c  | 19 +++
  src/qemu/qemu_conf.h|  3 ++
  src/qemu/qemu_driver.c  |  9 +
  src/secret/secret_driver.c  | 44 +++-
  src/storage/storage_driver.c| 11 ++
  src/vz/vz_driver.c  | 40 +++---
  21 files changed, 327 insertions(+), 40 deletions(-)



Reviewed-by: Michal Privoznik 

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [dockerfiles PATCH 3/3] Add Debian 10 Dockerfiles

2019-07-10 Thread Andrea Bolognani
The corresponding libvirt-jenkins-ci commit is 0e593724d190.

Signed-off-by: Andrea Bolognani 
---
 buildenv-debian-10-cross-aarch64.Dockerfile  | 100 +++
 buildenv-debian-10-cross-armv6l.Dockerfile   |  98 ++
 buildenv-debian-10-cross-armv7l.Dockerfile   |  99 ++
 buildenv-debian-10-cross-i686.Dockerfile |  99 ++
 buildenv-debian-10-cross-mips.Dockerfile |  99 ++
 buildenv-debian-10-cross-mips64el.Dockerfile |  99 ++
 buildenv-debian-10-cross-mipsel.Dockerfile   |  99 ++
 buildenv-debian-10-cross-ppc64le.Dockerfile  |  99 ++
 buildenv-debian-10-cross-s390x.Dockerfile|  99 ++
 buildenv-debian-10.Dockerfile|  89 +
 10 files changed, 980 insertions(+)
 create mode 100644 buildenv-debian-10-cross-aarch64.Dockerfile
 create mode 100644 buildenv-debian-10-cross-armv6l.Dockerfile
 create mode 100644 buildenv-debian-10-cross-armv7l.Dockerfile
 create mode 100644 buildenv-debian-10-cross-i686.Dockerfile
 create mode 100644 buildenv-debian-10-cross-mips.Dockerfile
 create mode 100644 buildenv-debian-10-cross-mips64el.Dockerfile
 create mode 100644 buildenv-debian-10-cross-mipsel.Dockerfile
 create mode 100644 buildenv-debian-10-cross-ppc64le.Dockerfile
 create mode 100644 buildenv-debian-10-cross-s390x.Dockerfile
 create mode 100644 buildenv-debian-10.Dockerfile

diff --git a/buildenv-debian-10-cross-aarch64.Dockerfile 
b/buildenv-debian-10-cross-aarch64.Dockerfile
new file mode 100644
index 000..9498453
--- /dev/null
+++ b/buildenv-debian-10-cross-aarch64.Dockerfile
@@ -0,0 +1,100 @@
+FROM debian:10
+
+RUN export DEBIAN_FRONTEND=noninteractive && \
+apt-get update && \
+apt-get dist-upgrade -y && \
+apt-get install --no-install-recommends -y \
+augeas-tools \
+autoconf \
+automake \
+autopoint \
+bash \
+bash-completion \
+ca-certificates \
+ccache \
+chrony \
+dnsmasq-base \
+dwarves \
+ebtables \
+gcc \
+gdb \
+gettext \
+git \
+iproute2 \
+kmod \
+libc-dev-bin \
+libtool \
+libtool-bin \
+libxml2-utils \
+lsof \
+lvm2 \
+make \
+net-tools \
+nfs-common \
+numad \
+open-iscsi \
+parted \
+patch \
+perl \
+pkgconf \
+policykit-1 \
+qemu-utils \
+radvd \
+screen \
+scrub \
+strace \
+sudo \
+vim \
+xsltproc \
+zfs-fuse && \
+apt-get autoremove -y && \
+apt-get autoclean -y
+
+RUN export DEBIAN_FRONTEND=noninteractive && \
+dpkg --add-architecture arm64 && \
+apt-get update && \
+apt-get dist-upgrade -y && \
+apt-get install --no-install-recommends -y \
+gcc-aarch64-linux-gnu \
+libacl1-dev:arm64 \
+libapparmor-dev:arm64 \
+libattr1-dev:arm64 \
+libaudit-dev:arm64 \
+libavahi-client-dev:arm64 \
+libblkid-dev:arm64 \
+libc6-dev:arm64 \
+libcap-ng-dev:arm64 \
+libcurl4-gnutls-dev:arm64 \
+libdbus-1-dev:arm64 \
+libdevmapper-dev:arm64 \
+libfuse-dev:arm64 \
+libglusterfs-dev:arm64 \
+libgnutls28-dev:arm64 \
+libiscsi-dev:arm64 \
+libncurses-dev:arm64 \
+libnl-3-dev:arm64 \
+libnl-route-3-dev:arm64 \
+libnuma-dev:arm64 \
+libparted-dev:arm64 \
+libpcap0.8-dev:arm64 \
+libpciaccess-dev:arm64 \
+librbd-dev:arm64 \
+libreadline-dev:arm64 \
+libsanlock-dev:arm64 \
+libsasl2-dev:arm64 \
+libselinux1-dev:arm64 \
+libssh-gcrypt-dev:arm64 \
+libssh2-1-dev:arm64 \
+libtirpc-dev:arm64 \
+libudev-dev:arm64 \
+libxen-dev:arm64 \
+libxml2-dev:arm64 \
+libyajl-dev:arm64 \
+xfslibs-dev:arm64 && \
+apt-get autoremove -y && \
+apt-get autoclean -y
+
+ENV ABI "aarch64-linux-gnu"
+ENV CONFIGURE_OPTS "--host=aarch64-linux-gnu \
+--target=aarch64-linux-gnu"
+ENV PKG_CONFIG_LIBDIR "/usr/lib/aarch64-linux-gnu/pkgconfig"
diff --git a/buildenv-debian-10-cross-armv6l.Dockerfile 
b/buildenv-debian-10-cross-armv6l.Dockerfile
new file mode 100644
index 000..d15cad1
--- /dev/null
+++ b/buildenv-debian-10-cross-armv6l.Dockerfile
@@ -0,0 +1,98 @@
+FROM debian:10
+
+RUN export DEBIAN_FRONTEND=noninteractive && \
+apt-get update && \
+apt-get dist-upgrade -y 

[libvirt] [dockerfiles PATCH 2/3] Re-introduce Ubuntu 16.04 Dockerfile

2019-07-10 Thread Andrea Bolognani
It was dropped by commit 277bab7b5aa4, but as it turns out
doing so was not the correct course of action.

The corresponding libvirt-jenkins-ci commit is 864210561aac.

Signed-off-by: Andrea Bolognani 
---
 buildenv-ubuntu-16.Dockerfile | 91 +++
 1 file changed, 91 insertions(+)
 create mode 100644 buildenv-ubuntu-16.Dockerfile

diff --git a/buildenv-ubuntu-16.Dockerfile b/buildenv-ubuntu-16.Dockerfile
new file mode 100644
index 000..12060a1
--- /dev/null
+++ b/buildenv-ubuntu-16.Dockerfile
@@ -0,0 +1,91 @@
+FROM ubuntu:16.04
+
+RUN export DEBIAN_FRONTEND=noninteractive && \
+apt-get update && \
+apt-get dist-upgrade -y && \
+apt-get install --no-install-recommends -y \
+augeas-tools \
+autoconf \
+automake \
+autopoint \
+bash \
+bash-completion \
+ca-certificates \
+ccache \
+chrony \
+dnsmasq-base \
+dwarves \
+ebtables \
+gcc \
+gdb \
+gettext \
+git \
+glusterfs-common \
+iproute2 \
+kmod \
+libacl1-dev \
+libapparmor-dev \
+libattr1-dev \
+libaudit-dev \
+libavahi-client-dev \
+libblkid-dev \
+libc-dev-bin \
+libc6-dev \
+libcap-ng-dev \
+libcurl4-gnutls-dev \
+libdbus-1-dev \
+libdevmapper-dev \
+libfuse-dev \
+libgnutls28-dev \
+libiscsi-dev \
+libncurses-dev \
+libnetcf-dev \
+libnl-3-dev \
+libnl-route-3-dev \
+libnuma-dev \
+libopenwsman-dev \
+libparted-dev \
+libpcap0.8-dev \
+libpciaccess-dev \
+librbd-dev \
+libreadline-dev \
+libsanlock-dev \
+libsasl2-dev \
+libselinux1-dev \
+libssh-dev \
+libssh2-1-dev \
+libtirpc-dev \
+libtool \
+libtool-bin \
+libudev-dev \
+libxen-dev \
+libxml2-dev \
+libxml2-utils \
+libyajl-dev \
+lsof \
+lvm2 \
+make \
+net-tools \
+nfs-common \
+numad \
+open-iscsi \
+parted \
+patch \
+perl \
+pkgconf \
+policykit-1 \
+qemu-utils \
+radvd \
+screen \
+scrub \
+sheepdog \
+strace \
+sudo \
+systemtap-sdt-dev \
+vim \
+wireshark-dev \
+xfslibs-dev \
+xsltproc \
+zfs-fuse && \
+apt-get autoremove -y && \
+apt-get autoclean -y
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [dockerfiles PATCH 0/3] Various updates

2019-07-10 Thread Andrea Bolognani
All patches pushed under the Dockerfiles refresh and trivial rule.

Andrea Bolognani (3):
  Refresh after recent changes
  Re-introduce Ubuntu 16.04 Dockerfile
  Add Debian 10 Dockerfiles

 buildenv-centos-7.Dockerfile | 151 ++---
 buildenv-debian-10-cross-aarch64.Dockerfile  | 100 +
 buildenv-debian-10-cross-armv6l.Dockerfile   |  98 
 buildenv-debian-10-cross-armv7l.Dockerfile   |  99 
 buildenv-debian-10-cross-i686.Dockerfile |  99 
 buildenv-debian-10-cross-mips.Dockerfile |  99 
 buildenv-debian-10-cross-mips64el.Dockerfile |  99 
 buildenv-debian-10-cross-mipsel.Dockerfile   |  99 
 buildenv-debian-10-cross-ppc64le.Dockerfile  |  99 
 buildenv-debian-10-cross-s390x.Dockerfile|  99 
 buildenv-debian-10.Dockerfile|  89 
 buildenv-fedora-29.Dockerfile| 173 +++---
 buildenv-fedora-30.Dockerfile| 173 +++---
 buildenv-fedora-rawhide.Dockerfile   | 223 ++-
 buildenv-ubuntu-16.Dockerfile|  91 
 15 files changed, 1433 insertions(+), 358 deletions(-)
 create mode 100644 buildenv-debian-10-cross-aarch64.Dockerfile
 create mode 100644 buildenv-debian-10-cross-armv6l.Dockerfile
 create mode 100644 buildenv-debian-10-cross-armv7l.Dockerfile
 create mode 100644 buildenv-debian-10-cross-i686.Dockerfile
 create mode 100644 buildenv-debian-10-cross-mips.Dockerfile
 create mode 100644 buildenv-debian-10-cross-mips64el.Dockerfile
 create mode 100644 buildenv-debian-10-cross-mipsel.Dockerfile
 create mode 100644 buildenv-debian-10-cross-ppc64le.Dockerfile
 create mode 100644 buildenv-debian-10-cross-s390x.Dockerfile
 create mode 100644 buildenv-debian-10.Dockerfile
 create mode 100644 buildenv-ubuntu-16.Dockerfile

-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [dockerfiles PATCH 1/3] Refresh after recent changes

2019-07-10 Thread Andrea Bolognani
The corresponding libvirt-jenkins-ci commit is aba4604e6721.

Signed-off-by: Andrea Bolognani 
---
 buildenv-centos-7.Dockerfile   | 151 +--
 buildenv-fedora-29.Dockerfile  | 173 +++---
 buildenv-fedora-30.Dockerfile  | 173 +++---
 buildenv-fedora-rawhide.Dockerfile | 223 +++--
 4 files changed, 362 insertions(+), 358 deletions(-)

diff --git a/buildenv-centos-7.Dockerfile b/buildenv-centos-7.Dockerfile
index 9e79723..298bbc7 100644
--- a/buildenv-centos-7.Dockerfile
+++ b/buildenv-centos-7.Dockerfile
@@ -1,80 +1,81 @@
 FROM centos:centos7
 
 RUN yum update -y && \
-yum install -y audit-libs-devel \
-augeas \
-autoconf \
-automake \
-avahi-devel \
-bash \
-bash-completion \
-ca-certificates \
-chrony \
-cyrus-sasl-devel \
-dbus-devel \
-device-mapper-devel \
-dnsmasq \
-ebtables \
-fuse-devel \
-gcc \
-gdb \
-gettext \
-gettext-devel \
-git \
-glibc-common \
-glibc-devel \
-glusterfs-api-devel \
-gnutls-devel \
-iproute \
-iscsi-initiator-utils \
-kmod \
-libacl-devel \
-libattr-devel \
-libblkid-devel \
-libcap-ng-devel \
-libcurl-devel \
-libiscsi-devel \
-libnl3-devel \
-libpcap-devel \
-libpciaccess-devel \
-librbd1-devel \
-libselinux-devel \
-libssh-devel \
-libssh2-devel \
-libtirpc-devel \
-libtool \
-libudev-devel \
-libwsman-devel \
-libxml2 \
-libxml2-devel \
-libxslt \
-lsof \
-lvm2 \
-make \
-ncurses-devel \
-net-tools \
-netcf-devel \
-nfs-utils \
-numactl-devel \
-numad \
-parted \
-parted-devel \
-patch \
-perl \
-pkgconfig \
-polkit \
-qemu-img \
-radvd \
-readline-devel \
-rpm-build \
-sanlock-devel \
-screen \
-scrub \
-strace \
-sudo \
-systemtap-sdt-devel \
-vim \
-xfsprogs-devel \
-yajl-devel && \
+yum install -y \
+audit-libs-devel \
+augeas \
+autoconf \
+automake \
+avahi-devel \
+bash \
+bash-completion \
+ca-certificates \
+chrony \
+cyrus-sasl-devel \
+dbus-devel \
+device-mapper-devel \
+dnsmasq \
+ebtables \
+fuse-devel \
+gcc \
+gdb \
+gettext \
+gettext-devel \
+git \
+glibc-common \
+glibc-devel \
+glusterfs-api-devel \
+gnutls-devel \
+iproute \
+iscsi-initiator-utils \
+kmod \
+libacl-devel \
+libattr-devel \
+libblkid-devel \
+libcap-ng-devel \
+libcurl-devel \
+libiscsi-devel \
+libnl3-devel \
+libpcap-devel \
+libpciaccess-devel \
+librbd1-devel \
+libselinux-devel \
+libssh-devel \
+libssh2-devel \
+libtirpc-devel \
+libtool \
+libudev-devel \
+libwsman-devel \
+libxml2 \
+libxml2-devel \
+libxslt \
+lsof \
+lvm2 \
+make \
+ncurses-devel \
+net-tools \
+netcf-devel \
+nfs-utils \
+numactl-devel \
+numad \
+parted \
+parted-devel \
+patch \
+perl \
+pkgconfig \
+polkit \
+qemu-img \
+radvd \
+readline-devel \
+rpm-build \
+sanlock-devel \
+screen \
+scrub \
+strace \
+sudo \
+systemtap-sdt-devel \
+vim \
+xfsprogs-devel \
+yajl-devel && \
 yum autoremove -y && \
 yum clean all -y
diff --git a/buildenv-fedora-29.Dockerfile b/buildenv-fedora-29.Dockerfile
index b7086b1..bf2bf0a 100644
--- a/buildenv-fedora-29.Dockerfile
+++ b/buildenv-fedora-29.Dockerfile
@@ -1,88 +1,89 @@
 FROM fedora:29
 
-RUN yum update -y && \
-yum install -y audit-libs-devel \
-augeas \
-autoconf \
-automake \
-avahi-devel \
-bash \
-bash-completion \
-ca-certificates \
-ccache \
-chrony \
-cppi \
-cyrus-sasl-devel \
-dbus-devel \
-device-mapper-devel \
-dnsmasq \
-

Re: [libvirt] [PATCH 06/23] util: add APIs for facilitating use of systemd activation FDs

2019-07-10 Thread Ján Tomko

On Thu, Jun 27, 2019 at 10:54:35AM +0100, Daniel P. Berrangé wrote:

When receiving multiple FDs from systemd during service activation it is
neccessary to identify which purpose each FD is used for. While this
could be inferred by looking for the specific IP ports or UNIX socket
paths, this requires the systemd config to always match what is expected
by the code. Using systemd FD names we can remove this restriction and
simply identify FDs based on an arbitrary name.

The FD names are passed by systemd in the LISTEN_FDNAMES env variable
which is populated with the socket unit file names, unless overriden
by using the FileDescriptorName setting.

This is supported since the system 227 release and unfortunately RHEL7
lacks this version. Thus the code has some back compat support whereby
we look at the TCP ports or the UNIX socket paths to identify what
socket maps to which name. This back compat code is written such that
is it easly deleted when we are able to mandate newer systemd.

Signed-off-by: Daniel P. Berrangé 
---
src/libvirt_private.syms |   5 +
src/util/virsystemd.c| 362 +++
src/util/virsystemd.h|  30 
tests/virsystemdtest.c   | 169 ++
4 files changed, 566 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1adf735a38..ee1073e680 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3102,6 +3102,11 @@ virSysinfoReadS390;


# util/virsystemd.h
+virSystemdGetActivation;
+virSystemdActivationClaimFDs;
+virSystemdActivationComplete;
+virSystemdActivationFree;
+virSystemdActivationHasName;
virSystemdCanHibernate;
virSystemdCanHybridSleep;
virSystemdCanSuspend;


This hunk is not sorted properly.

Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 09/12] libxl: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/libxl/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/libxl/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/libxl/libxl_conf.h   |  3 +++
 src/libxl/libxl_driver.c | 11 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 136b5ae1ac..552f039d2a 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -111,6 +111,9 @@ struct _libxlDriverPrivate {
  * then lockless thereafter */
 libxlDriverConfigPtr config;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 /* Atomic inc/dec only */
 unsigned int nactive;
 
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index ac10fb6dbc..a99c7471bb 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -53,6 +53,7 @@
 #include "viraccessapicheck.h"
 #include "viratomic.h"
 #include "virhostdev.h"
+#include "virpidfile.h"
 #include "locking/domain_lock.h"
 #include "virnetdevtap.h"
 #include "cpu/cpu.h"
@@ -506,7 +507,6 @@ libxlStateCleanup(void)
 return -1;
 
 virObjectUnref(libxl_driver->hostdevMgr);
-virObjectUnref(libxl_driver->config);
 virObjectUnref(libxl_driver->xmlopt);
 virObjectUnref(libxl_driver->domains);
 virPortAllocatorRangeFree(libxl_driver->reservedGraphicsPorts);
@@ -516,6 +516,10 @@ libxlStateCleanup(void)
 virObjectUnref(libxl_driver->domainEventState);
 virSysinfoDefFree(libxl_driver->hostsysinfo);
 
+if (libxl_driver->lockFD != -1)
+virPidFileRelease(libxl_driver->config->stateDir, "driver", 
libxl_driver->lockFD);
+
+virObjectUnref(libxl_driver->config);
 virMutexDestroy(_driver->lock);
 VIR_FREE(libxl_driver);
 
@@ -658,6 +662,7 @@ libxlStateInitialize(bool privileged,
 if (VIR_ALLOC(libxl_driver) < 0)
 return -1;
 
+libxl_driver->lockFD = -1;
 if (virMutexInit(_driver->lock) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot initialize mutex"));
@@ -741,6 +746,10 @@ libxlStateInitialize(bool privileged,
 goto error;
 }
 
+if ((libxl_driver->lockFD =
+ virPidFileAcquire(cfg->stateDir, "driver", true, getpid())) < 0)
+goto error;
+
 if (!(libxl_driver->lockManager =
   virLockManagerPluginNew(cfg->lockManagerName ?
   cfg->lockManagerName : "nop",
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 08/12] libxl: remove obsolete check for xend during driver startup

2019-07-10 Thread Daniel P . Berrangé
No supported build targets for libvirt still ship xend, so there is no
need for the libxl driver to check for it anymore.

Signed-off-by: Daniel P. Berrangé 
---
 src/libxl/libxl_driver.c | 26 --
 1 file changed, 4 insertions(+), 22 deletions(-)

diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 731700ded6..ac10fb6dbc 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -525,12 +525,10 @@ libxlStateCleanup(void)
 static bool
 libxlDriverShouldLoad(bool privileged)
 {
-bool ret = false;
-
 /* Don't load if non-root */
 if (!privileged) {
 VIR_INFO("Not running privileged, disabling libxenlight driver");
-return ret;
+return false;
 }
 
 if (virFileExists(HYPERVISOR_CAPABILITIES)) {
@@ -549,31 +547,15 @@ libxlDriverShouldLoad(bool privileged)
 VIR_INFO("No Xen capabilities detected, probably not running "
  "in a Xen Dom0.  Disabling libxenlight driver");
 
-return ret;
+return false;
 }
 } else if (!virFileExists(HYPERVISOR_XENSTORED)) {
 VIR_INFO("Disabling driver as neither " HYPERVISOR_CAPABILITIES
  " nor " HYPERVISOR_XENSTORED " exist");
-return ret;
+return false;
 }
 
-/* Don't load if legacy xen toolstack (xend) is in use */
-if (virFileExists("/usr/sbin/xend")) {
-virCommandPtr cmd;
-
-cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
-if (virCommandRun(cmd, NULL) == 0) {
-VIR_INFO("Legacy xen tool stack seems to be in use, disabling "
- "libxenlight driver.");
-} else {
-ret = true;
-}
-virCommandFree(cmd);
-} else {
-ret = true;
-}
-
-return ret;
+return true;
 }
 
 /* Callbacks wrapping libvirt's event loop interface */
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 12/12] bhyve: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/bhyve/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/bhyve/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/bhyve/bhyve_driver.c | 9 +
 src/bhyve/bhyve_utils.h  | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 4ce9ef0b95..cfcf4e1fba 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -43,6 +43,7 @@
 #include "virthread.h"
 #include "virlog.h"
 #include "virfile.h"
+#include "virpidfile.h"
 #include "virtypedparam.h"
 #include "virrandom.h"
 #include "virstring.h"
@@ -1203,6 +1204,9 @@ bhyveStateCleanup(void)
 virObjectUnref(bhyve_driver->config);
 virPortAllocatorRangeFree(bhyve_driver->remotePorts);
 
+if (bhyve_driver->lockFD != -1)
+virPidFileRelease(BHYVE_STATE_DIR, "driver", bhyve_driver->lockFD);
+
 virMutexDestroy(_driver->lock);
 VIR_FREE(bhyve_driver);
 
@@ -1222,6 +1226,7 @@ bhyveStateInitialize(bool privileged,
 if (VIR_ALLOC(bhyve_driver) < 0)
 return -1;
 
+bhyve_driver->lockFD = -1;
 if (virMutexInit(_driver->lock) < 0) {
 VIR_FREE(bhyve_driver);
 return -1;
@@ -1274,6 +1279,10 @@ bhyveStateInitialize(bool privileged,
 goto cleanup;
 }
 
+if ((bhyve_driver->lockFD =
+ virPidFileAcquire(BHYVE_STATE_DIR, "driver", true, getpid())) < 0)
+goto cleanup;
+
 if (virDomainObjListLoadAllConfigs(bhyve_driver->domains,
BHYVE_STATE_DIR,
NULL, true,
diff --git a/src/bhyve/bhyve_utils.h b/src/bhyve/bhyve_utils.h
index 26956d7d21..3d212e3ccf 100644
--- a/src/bhyve/bhyve_utils.h
+++ b/src/bhyve/bhyve_utils.h
@@ -48,6 +48,9 @@ struct _bhyveConn {
 
 virBhyveDriverConfigPtr config;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 virDomainObjListPtr domains;
 virCapsPtr caps;
 virDomainXMLOptionPtr xmlopt;
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 11/12] vz: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/vz/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/vz/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/vz/vz_driver.c | 40 +++-
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
index 2286f9a04f..c5152c309c 100644
--- a/src/vz/vz_driver.c
+++ b/src/vz/vz_driver.c
@@ -41,6 +41,7 @@
 #include "vircommand.h"
 #include "configmake.h"
 #include "virfile.h"
+#include "virpidfile.h"
 #include "virstoragefile.h"
 #include "virstring.h"
 #include "cpu/cpu.h"
@@ -59,8 +60,13 @@ VIR_LOG_INIT("parallels.parallels_driver");
 
 #define PRLCTL  "prlctl"
 
+#define VZ_STATEDIR LOCALSTATEDIR "/run/libvirt/vz"
+
 static virClassPtr vzDriverClass;
 
+static bool vz_driver_privileged;
+/* pid file FD, ensures two copies of the driver can't use the same root */
+static int vz_driver_lock_fd = -1;
 static virMutex vz_driver_lock;
 static vzDriverPtr vz_driver;
 static vzConnPtr vz_conn_list;
@@ -166,6 +172,11 @@ VIR_ONCE_GLOBAL_INIT(vzDriver);
 vzDriverPtr
 vzGetDriverConnection(void)
 {
+if (!vz_driver_privileged) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   "%s", _("vz state driver is not active"));
+return NULL;
+}
 virMutexLock(_driver_lock);
 if (!vz_driver)
 vz_driver = vzDriverObjNew();
@@ -4087,18 +4098,37 @@ static virConnectDriver vzConnectDriver = {
 static int
 vzStateCleanup(void)
 {
-virObjectUnref(vz_driver);
-vz_driver = NULL;
-virMutexDestroy(_driver_lock);
-prlsdkDeinit();
+if (vz_driver_privileged) {
+virObjectUnref(vz_driver);
+vz_driver = NULL;
+if (vz_driver_lock_fd != -1)
+virPidFileRelease(VZ_STATEDIR, "driver", vz_driver_lock_fd);
+virMutexDestroy(_driver_lock);
+prlsdkDeinit();
+}
 return 0;
 }
 
 static int
-vzStateInitialize(bool privileged ATTRIBUTE_UNUSED,
+vzStateInitialize(bool privileged,
   virStateInhibitCallback callback ATTRIBUTE_UNUSED,
   void *opaque ATTRIBUTE_UNUSED)
 {
+if (!privileged)
+return 0;
+
+vz_driver_privileged = privileged;
+
+if (virFileMakePathWithMode(VZ_STATEDIR, S_IRWXU) < 0) {
+virReportSystemError(errno, _("cannot create state directory '%s'"),
+ VZ_STATEDIR);
+return -1;
+}
+
+if ((vz_driver_lock_fd =
+ virPidFileAcquire(VZ_STATEDIR, "driver", true, getpid())) < 0)
+return -1;
+
 if (prlsdkInit() < 0) {
 VIR_DEBUG("%s", _("Can't initialize Parallels SDK"));
 return -1;
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 10/12] lxc: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/lxc/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/lxc/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/lxc/lxc_conf.h   | 3 +++
 src/lxc/lxc_driver.c | 9 +
 2 files changed, 12 insertions(+)

diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index dc5531ebf9..e26ca22d3c 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -70,6 +70,9 @@ struct _virLXCDriver {
  * then lockless thereafter */
 virLXCDriverConfigPtr config;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 /* Require lock to get a reference on the object,
  * lockless access thereafter */
 virCapsPtr caps;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 9db2a02dee..3982c24f34 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1559,6 +1559,7 @@ static int lxcStateInitialize(bool privileged,
 
 if (VIR_ALLOC(lxc_driver) < 0)
 return -1;
+lxc_driver->lockFD = -1;
 if (virMutexInit(_driver->lock) < 0) {
 VIR_FREE(lxc_driver);
 return -1;
@@ -1605,6 +1606,10 @@ static int lxcStateInitialize(bool privileged,
 goto cleanup;
 }
 
+if ((lxc_driver->lockFD =
+ virPidFileAcquire(cfg->stateDir, "driver", true, getpid())) < 0)
+goto cleanup;
+
 /* Get all the running persistent or transient configs first */
 if (virDomainObjListLoadAllConfigs(lxc_driver->domains,
cfg->stateDir,
@@ -1696,6 +1701,10 @@ static int lxcStateCleanup(void)
 virObjectUnref(lxc_driver->caps);
 virObjectUnref(lxc_driver->securityManager);
 virObjectUnref(lxc_driver->xmlopt);
+
+if (lxc_driver->lockFD != -1)
+virPidFileRelease(lxc_driver->config->stateDir, "driver", 
lxc_driver->lockFD);
+
 virObjectUnref(lxc_driver->config);
 virMutexDestroy(_driver->lock);
 VIR_FREE(lxc_driver);
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 07/12] nwfilter: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/nwfilter/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/nwfilter/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/virnwfilterobj.h  |  4 
 src/nwfilter/nwfilter_driver.c | 19 +++
 2 files changed, 23 insertions(+)

diff --git a/src/conf/virnwfilterobj.h b/src/conf/virnwfilterobj.h
index bdf5c51fe2..a6bdfb3864 100644
--- a/src/conf/virnwfilterobj.h
+++ b/src/conf/virnwfilterobj.h
@@ -36,10 +36,14 @@ struct _virNWFilterDriverState {
 virMutex lock;
 bool privileged;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 virNWFilterObjListPtr nwfilters;
 
 virNWFilterBindingObjListPtr bindings;
 
+char *stateDir;
 char *configDir;
 char *bindingDir;
 };
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index fdfc6f48fa..43561241f6 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -38,6 +38,7 @@
 #include "nwfilter_gentech_driver.h"
 #include "configmake.h"
 #include "virfile.h"
+#include "virpidfile.h"
 #include "virstring.h"
 #include "viraccessapicheck.h"
 
@@ -188,6 +189,7 @@ nwfilterStateInitialize(bool privileged,
 if (VIR_ALLOC(driver) < 0)
 return -1;
 
+driver->lockFD = -1;
 if (virMutexInit(>lock) < 0)
 goto err_free_driverstate;
 
@@ -203,6 +205,19 @@ nwfilterStateInitialize(bool privileged,
 
 nwfilterDriverLock();
 
+if (VIR_STRDUP(driver->stateDir, LOCALSTATEDIR "/run/libvirt/nwfilter") < 
0)
+goto error;
+
+if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
+virReportSystemError(errno, _("cannot create state directory '%s'"),
+ driver->stateDir);
+goto error;
+}
+
+if ((driver->lockFD =
+ virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
+goto error;
+
 if (virNWFilterIPAddrMapInit() < 0)
 goto err_free_driverstate;
 if (virNWFilterLearnInit() < 0)
@@ -346,6 +361,10 @@ nwfilterStateCleanup(void)
 
 nwfilterDriverRemoveDBusMatches();
 
+if (driver->lockFD != -1)
+virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
+
+VIR_FREE(driver->stateDir);
 VIR_FREE(driver->configDir);
 VIR_FREE(driver->bindingDir);
 nwfilterDriverUnlock();
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 06/12] interface: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/interface/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/interface/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/interface/interface_backend_netcf.c | 45 +++--
 src/interface/interface_backend_udev.c  | 44 +++-
 2 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/src/interface/interface_backend_netcf.c 
b/src/interface/interface_backend_netcf.c
index cf8eb9488d..868e49c56e 100644
--- a/src/interface/interface_backend_netcf.c
+++ b/src/interface/interface_backend_netcf.c
@@ -29,10 +29,14 @@
 #include "interface_conf.h"
 #include "viralloc.h"
 #include "virlog.h"
+#include "virfile.h"
+#include "virpidfile.h"
 #include "virstring.h"
 #include "viraccessapicheck.h"
 #include "virinterfaceobj.h"
 
+#include "configmake.h"
+
 #define VIR_FROM_THIS VIR_FROM_INTERFACE
 
 VIR_LOG_INIT("interface.interface_backend_netcf");
@@ -43,6 +47,10 @@ VIR_LOG_INIT("interface.interface_backend_netcf");
 typedef struct
 {
 virObjectLockable parent;
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
+char *stateDir;
 struct netcf *netcf;
 bool privileged;
 } virNetcfDriverState, *virNetcfDriverStatePtr;
@@ -71,6 +79,11 @@ virNetcfDriverStateDispose(void *obj)
 
 if (_driver->netcf)
 ncf_close(_driver->netcf);
+
+if (_driver->lockFD != -1)
+virPidFileRelease(_driver->stateDir, "driver", _driver->lockFD);
+
+VIR_FREE(_driver->stateDir);
 }
 
 
@@ -87,15 +100,41 @@ netcfStateInitialize(bool privileged,
 
 driver->privileged = privileged;
 
+if (privileged) {
+if (virAsprintf(>stateDir,
+"%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
+goto error;
+} else {
+VIR_AUTOFREE(char *) rundir = NULL;
+
+if (!(rundir = virGetUserRuntimeDirectory()))
+goto error;
+if (virAsprintf(>stateDir, "%s/nodedev/run", rundir) < 0)
+goto error;
+}
+
+if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
+virReportSystemError(errno, _("cannot create state directory '%s'"),
+ driver->stateDir);
+goto error;
+}
+
+if ((driver->lockFD =
+ virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
+goto error;
+
 /* open netcf */
 if (ncf_init(>netcf, NULL) != 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to initialize netcf"));
-virObjectUnref(driver);
-driver = NULL;
-return -1;
+goto error;
 }
 return 0;
+
+ error:
+virObjectUnref(driver);
+driver = NULL;
+return -1;
 }
 
 
diff --git a/src/interface/interface_backend_udev.c 
b/src/interface/interface_backend_udev.c
index 1373356246..fcd7f1c04a 100644
--- a/src/interface/interface_backend_udev.c
+++ b/src/interface/interface_backend_udev.c
@@ -32,14 +32,21 @@
 #include "interface_conf.h"
 #include "viralloc.h"
 #include "virstring.h"
+#include "virpidfile.h"
 #include "viraccessapicheck.h"
 #include "virinterfaceobj.h"
 #include "virnetdev.h"
 
+#include "configmake.h"
+
 #define VIR_FROM_THIS VIR_FROM_INTERFACE
 
 struct udev_iface_driver {
 struct udev *udev;
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
+char *stateDir;
 bool privileged;
 };
 
@@ -1157,6 +1164,9 @@ udevInterfaceIsActive(virInterfacePtr ifinfo)
 }
 
 
+static int
+udevStateCleanup(void);
+
 static int
 udevStateInitialize(bool privileged,
 virStateInhibitCallback callback ATTRIBUTE_UNUSED,
@@ -1167,6 +1177,31 @@ udevStateInitialize(bool privileged,
 if (VIR_ALLOC(driver) < 0)
 goto cleanup;
 
+driver->lockFD = -1;
+
+if (privileged) {
+if (virAsprintf(>stateDir,
+"%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
+goto cleanup;
+} else {
+VIR_AUTOFREE(char *) rundir = NULL;
+
+if (!(rundir = virGetUserRuntimeDirectory()))
+goto cleanup;
+if (virAsprintf(>stateDir, "%s/nodedev/run", rundir) < 0)
+goto cleanup;
+}
+
+if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
+virReportSystemError(errno, _("cannot create state directory '%s'"),
+ driver->stateDir);
+goto cleanup;
+}
+
+if ((driver->lockFD =
+ virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
+goto cleanup;
+
 driver->udev = udev_new();
 if (!driver->udev) {
 

[libvirt] [PATCH 05/12] nodedev: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/nodedev/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/nodedev/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/virnodedeviceobj.h|  5 +
 src/node_device/node_device_hal.c  | 31 +
 src/node_device/node_device_udev.c | 32 ++
 3 files changed, 68 insertions(+)

diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h
index 1abfcb9af4..c4d3c55d73 100644
--- a/src/conf/virnodedeviceobj.h
+++ b/src/conf/virnodedeviceobj.h
@@ -37,6 +37,11 @@ typedef virNodeDeviceDriverState 
*virNodeDeviceDriverStatePtr;
 struct _virNodeDeviceDriverState {
 virMutex lock;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
+char *stateDir;
+
 virNodeDeviceObjListPtr devs;   /* currently-known devices */
 void *privateData;  /* driver-specific private data */
 bool privileged;/* whether we run in privileged mode */
diff --git a/src/node_device/node_device_hal.c 
b/src/node_device/node_device_hal.c
index d1eb6c7851..876e808dce 100644
--- a/src/node_device/node_device_hal.c
+++ b/src/node_device/node_device_hal.c
@@ -33,10 +33,13 @@
 #include "viralloc.h"
 #include "viruuid.h"
 #include "virpci.h"
+#include "virpidfile.h"
 #include "virlog.h"
 #include "virdbus.h"
 #include "virstring.h"
 
+#include "configmake.h"
+
 #define VIR_FROM_THIS VIR_FROM_NODEDEV
 
 VIR_LOG_INIT("node_device.node_device_hal");
@@ -606,12 +609,36 @@ nodeStateInitialize(bool privileged ATTRIBUTE_UNUSED,
 if (VIR_ALLOC(driver) < 0)
 return -1;
 
+driver->lockFD = -1;
 if (virMutexInit(>lock) < 0) {
 VIR_FREE(driver);
 return -1;
 }
 nodeDeviceLock();
 
+if (privileged) {
+if (virAsprintf(>stateDir,
+"%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
+goto failure;
+} else {
+VIR_AUTOFREE(char *) rundir = NULL;
+
+if (!(rundir = virGetUserRuntimeDirectory()))
+goto failure;
+if (virAsprintf(>stateDir, "%s/nodedev/run", rundir) < 0)
+goto failure;
+}
+
+if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
+virReportSystemError(errno, _("cannot create state directory '%s'"),
+ driver->stateDir);
+goto failure;
+}
+
+if ((driver->lockFD =
+ virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
+goto failure;
+
 if (!(driver->devs = virNodeDeviceObjListNew()))
 goto failure;
 
@@ -708,6 +735,10 @@ nodeStateCleanup(void)
 virNodeDeviceObjListFree(driver->devs);
 (void)libhal_ctx_shutdown(hal_ctx, NULL);
 (void)libhal_ctx_free(hal_ctx);
+if (driver->lockFD != -1)
+virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
+
+VIR_FREE(driver->stateDir);
 nodeDeviceUnlock();
 virMutexDestroy(>lock);
 VIR_FREE(driver);
diff --git a/src/node_device/node_device_udev.c 
b/src/node_device/node_device_udev.c
index 276bf3dd99..d883462948 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -38,10 +38,13 @@
 #include "virbuffer.h"
 #include "virfile.h"
 #include "virpci.h"
+#include "virpidfile.h"
 #include "virstring.h"
 #include "virnetdev.h"
 #include "virmdev.h"
 
+#include "configmake.h"
+
 #define VIR_FROM_THIS VIR_FROM_NODEDEV
 
 VIR_LOG_INIT("node_device.node_device_udev");
@@ -1494,6 +1497,11 @@ nodeStateCleanup(void)
 virObjectUnref(driver->nodeDeviceEventState);
 
 virNodeDeviceObjListFree(driver->devs);
+
+if (driver->lockFD != -1)
+virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
+
+VIR_FREE(driver->stateDir);
 virMutexDestroy(>lock);
 VIR_FREE(driver);
 
@@ -1810,6 +1818,7 @@ nodeStateInitialize(bool privileged,
 if (VIR_ALLOC(driver) < 0)
 return -1;
 
+driver->lockFD = -1;
 if (virMutexInit(>lock) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unable to initialize mutex"));
@@ -1819,6 +1828,29 @@ nodeStateInitialize(bool privileged,
 
 driver->privileged = privileged;
 
+if (privileged) {
+if (virAsprintf(>stateDir,
+"%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
+goto cleanup;
+} else {
+VIR_AUTOFREE(char *) rundir = NULL;
+
+if (!(rundir = virGetUserRuntimeDirectory()))
+goto cleanup;
+if (virAsprintf(>stateDir, "%s/nodedev/run", rundir) < 0)
+goto cleanup;

[libvirt] [PATCH 03/12] network: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/network/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/network/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c  | 10 ++
 src/network/bridge_driver_platform.h |  3 +++
 2 files changed, 13 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 19faf7d514..6292e3b90a 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -597,6 +597,7 @@ networkStateInitialize(bool privileged,
 if (VIR_ALLOC(network_driver) < 0)
 goto error;
 
+network_driver->lockFD = -1;
 if (virMutexInit(_driver->lock) < 0) {
 VIR_FREE(network_driver);
 goto error;
@@ -651,6 +652,11 @@ networkStateInitialize(bool privileged,
 goto error;
 }
 
+if ((network_driver->lockFD =
+ virPidFileAcquire(network_driver->stateDir, "driver",
+   true, getpid())) < 0)
+goto error;
+
 /* if this fails now, it will be retried later with dnsmasqCapsRefresh() */
 network_driver->dnsmasqCaps = dnsmasqCapsNewFromBinary(DNSMASQ);
 
@@ -764,6 +770,10 @@ networkStateCleanup(void)
 /* free inactive networks */
 virObjectUnref(network_driver->networks);
 
+if (network_driver->lockFD != -1)
+virPidFileRelease(network_driver->stateDir, "driver",
+  network_driver->lockFD);
+
 VIR_FREE(network_driver->networkConfigDir);
 VIR_FREE(network_driver->networkAutostartDir);
 VIR_FREE(network_driver->stateDir);
diff --git a/src/network/bridge_driver_platform.h 
b/src/network/bridge_driver_platform.h
index 1efa0d2af4..95993c5e31 100644
--- a/src/network/bridge_driver_platform.h
+++ b/src/network/bridge_driver_platform.h
@@ -34,6 +34,9 @@ struct _virNetworkDriverState {
 /* Read-only */
 bool privileged;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 /* Immutable pointer, self-locking APIs */
 virNetworkObjListPtr networks;
 
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 04/12] storage: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/storage/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/storage/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/virstorageobj.h |  3 +++
 src/storage/storage_driver.c | 11 +++
 2 files changed, 14 insertions(+)

diff --git a/src/conf/virstorageobj.h b/src/conf/virstorageobj.h
index 92d229f9b4..4547a0df9b 100644
--- a/src/conf/virstorageobj.h
+++ b/src/conf/virstorageobj.h
@@ -37,6 +37,9 @@ typedef virStorageDriverState *virStorageDriverStatePtr;
 struct _virStorageDriverState {
 virMutex lock;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 virStoragePoolObjListPtr pools;
 
 char *configDir;
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 496d51b1e0..03ac6a6845 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -43,6 +43,7 @@
 #include "virlog.h"
 #include "virfile.h"
 #include "virfdstream.h"
+#include "virpidfile.h"
 #include "configmake.h"
 #include "virsecret.h"
 #include "virstring.h"
@@ -256,6 +257,7 @@ storageStateInitialize(bool privileged,
 if (VIR_ALLOC(driver) < 0)
 return -1;
 
+driver->lockFD = -1;
 if (virMutexInit(>lock) < 0) {
 VIR_FREE(driver);
 return -1;
@@ -296,6 +298,11 @@ storageStateInitialize(bool privileged,
 goto error;
 }
 
+if ((driver->lockFD =
+ virPidFileAcquire(driver->stateDir, "driver",
+   true, getpid())) < 0)
+goto error;
+
 if (virStoragePoolObjLoadAllState(driver->pools,
   driver->stateDir) < 0)
 goto error;
@@ -371,6 +378,10 @@ storageStateCleanup(void)
 /* free inactive pools */
 virObjectUnref(driver->pools);
 
+if (driver->lockFD != -1)
+virPidFileRelease(driver->stateDir, "driver",
+  driver->lockFD);
+
 VIR_FREE(driver->configDir);
 VIR_FREE(driver->autostartDir);
 VIR_FREE(driver->stateDir);
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 02/12] secrets: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/secrets/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/secrets/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/secret/secret_driver.c | 44 +++---
 1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
index ac85f5d195..9344948db4 100644
--- a/src/secret/secret_driver.c
+++ b/src/secret/secret_driver.c
@@ -37,6 +37,7 @@
 #include "viruuid.h"
 #include "virerror.h"
 #include "virfile.h"
+#include "virpidfile.h"
 #include "configmake.h"
 #include "virstring.h"
 #include "viraccessapicheck.h"
@@ -56,8 +57,12 @@ struct _virSecretDriverState {
 virMutex lock;
 bool privileged; /* readonly */
 virSecretObjListPtr secrets;
+char *stateDir;
 char *configDir;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 /* Immutable pointer, self-locking APIs */
 virObjectEventStatePtr secretEventState;
 };
@@ -434,6 +439,10 @@ secretStateCleanup(void)
 
 virObjectUnref(driver->secretEventState);
 
+if (driver->lockFD != -1)
+virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
+
+VIR_FREE(driver->stateDir);
 secretDriverUnlock();
 virMutexDestroy(>lock);
 VIR_FREE(driver);
@@ -447,11 +456,10 @@ secretStateInitialize(bool privileged,
   virStateInhibitCallback callback ATTRIBUTE_UNUSED,
   void *opaque ATTRIBUTE_UNUSED)
 {
-char *base = NULL;
-
 if (VIR_ALLOC(driver) < 0)
 return -1;
 
+driver->lockFD = -1;
 if (virMutexInit(>lock) < 0) {
 VIR_FREE(driver);
 return -1;
@@ -462,15 +470,26 @@ secretStateInitialize(bool privileged,
 driver->privileged = privileged;
 
 if (privileged) {
-if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0)
+if (virAsprintf(>configDir,
+"%s/libvirt/secrets", SYSCONFDIR) < 0)
+goto error;
+if (virAsprintf(>stateDir,
+"%s/run/libvirt/secrets", LOCALSTATEDIR) < 0)
 goto error;
 } else {
-if (!(base = virGetUserConfigDirectory()))
+VIR_AUTOFREE(char *) rundir = NULL;
+VIR_AUTOFREE(char *) cfgdir = NULL;
+
+if (!(cfgdir = virGetUserConfigDirectory()))
+goto error;
+if (virAsprintf(>configDir, "%s/secrets/", cfgdir) < 0)
+goto error;
+
+if (!(rundir = virGetUserRuntimeDirectory()))
+goto error;
+if (virAsprintf(>stateDir, "%s/secrets/run", rundir) < 0)
 goto error;
 }
-if (virAsprintf(>configDir, "%s/secrets", base) < 0)
-goto error;
-VIR_FREE(base);
 
 if (virFileMakePathWithMode(driver->configDir, S_IRWXU) < 0) {
 virReportSystemError(errno, _("cannot create config directory '%s'"),
@@ -478,6 +497,16 @@ secretStateInitialize(bool privileged,
 goto error;
 }
 
+if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
+virReportSystemError(errno, _("cannot create state directory '%s'"),
+ driver->stateDir);
+goto error;
+}
+
+if ((driver->lockFD =
+ virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
+goto error;
+
 if (!(driver->secrets = virSecretObjListNew()))
 goto error;
 
@@ -488,7 +517,6 @@ secretStateInitialize(bool privileged,
 return 0;
 
  error:
-VIR_FREE(base);
 secretDriverUnlock();
 secretStateCleanup();
 return -1;
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 00/12] introduce locking into every driver

2019-07-10 Thread Daniel P . Berrangé
As part of the proposal to introduce an embedded driver feature, we
decided we ought to have each driver acquire a lock against the virtual
root it is configured to use. This will prevent two apps from running an
embedded driver with the same root.

  https://www.redhat.com/archives/libvir-list/2019-May/msg00467.html

It turns out that this will also be useful for the per-driver split
daemons work I am working on. In that case libvirtd will exist as a
monolithic daemon running all drivers, and we'll also have per-driver
daemons like virtqemud, virtnetworkd, etc. It is only valid to run in
one setup on the host. ie you must choose libvirtd, or choose per-driver
daemons, never both.

The per-driver locking will provide very useful protection against
mistakes in this respect.

Since the locking is functionally independant of both patch series, I'm
sending it now.

Daniel P. Berrangé (12):
  qemu: acquire a pidfile in the driver root directory
  secrets: acquire a pidfile in the driver root directory
  network: acquire a pidfile in the driver root directory
  storage: acquire a pidfile in the driver root directory
  nodedev: acquire a pidfile in the driver root directory
  interface: acquire a pidfile in the driver root directory
  nwfilter: acquire a pidfile in the driver root directory
  libxl: remove obsolete check for xend during driver startup
  libxl: acquire a pidfile in the driver root directory
  lxc: acquire a pidfile in the driver root directory
  vz: acquire a pidfile in the driver root directory
  bhyve: acquire a pidfile in the driver root directory

 src/bhyve/bhyve_driver.c|  9 +
 src/bhyve/bhyve_utils.h |  3 ++
 src/conf/virnodedeviceobj.h |  5 +++
 src/conf/virnwfilterobj.h   |  4 +++
 src/conf/virstorageobj.h|  3 ++
 src/interface/interface_backend_netcf.c | 45 +++--
 src/interface/interface_backend_udev.c  | 44 +++-
 src/libxl/libxl_conf.h  |  3 ++
 src/libxl/libxl_driver.c| 37 
 src/lxc/lxc_conf.h  |  3 ++
 src/lxc/lxc_driver.c|  9 +
 src/network/bridge_driver.c | 10 ++
 src/network/bridge_driver_platform.h|  3 ++
 src/node_device/node_device_hal.c   | 31 +
 src/node_device/node_device_udev.c  | 32 ++
 src/nwfilter/nwfilter_driver.c  | 19 +++
 src/qemu/qemu_conf.h|  3 ++
 src/qemu/qemu_driver.c  |  9 +
 src/secret/secret_driver.c  | 44 +++-
 src/storage/storage_driver.c| 11 ++
 src/vz/vz_driver.c  | 40 +++---
 21 files changed, 327 insertions(+), 40 deletions(-)

-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 01/12] qemu: acquire a pidfile in the driver root directory

2019-07-10 Thread Daniel P . Berrangé
When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/qemu/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/qemu/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé 
---
 src/qemu/qemu_conf.h   | 3 +++
 src/qemu/qemu_driver.c | 9 +
 2 files changed, 12 insertions(+)

diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index e51514a344..2229b76e89 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -221,6 +221,9 @@ struct _virQEMUDriver {
  * then lockless thereafter */
 virQEMUDriverConfigPtr config;
 
+/* pid file FD, ensures two copies of the driver can't use the same root */
+int lockFD;
+
 /* Immutable pointer, self-locking APIs */
 virThreadPoolPtr workerPool;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5a75f23981..8bc069d3e2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -70,6 +70,7 @@
 #include "node_device_conf.h"
 #include "virpci.h"
 #include "virusb.h"
+#include "virpidfile.h"
 #include "virprocess.h"
 #include "libvirt_internal.h"
 #include "virxml.h"
@@ -587,6 +588,8 @@ qemuStateInitialize(bool privileged,
 if (VIR_ALLOC(qemu_driver) < 0)
 return -1;
 
+qemu_driver->lockFD = -1;
+
 if (virMutexInit(_driver->lock) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot initialize mutex"));
@@ -673,6 +676,10 @@ qemuStateInitialize(bool privileged,
 goto error;
 }
 
+if ((qemu_driver->lockFD =
+ virPidFileAcquire(cfg->stateDir, "driver", true, getpid())) < 0)
+goto error;
+
 qemu_driver->qemuImgBinary = virFindFileInPath("qemu-img");
 
 if (!(qemu_driver->lockManager =
@@ -1032,6 +1039,8 @@ qemuStateCleanup(void)
 if (!qemu_driver)
 return -1;
 
+if (qemu_driver->lockFD != -1)
+virPidFileRelease(qemu_driver->config->stateDir, "driver", 
qemu_driver->lockFD);
 virThreadPoolFree(qemu_driver->workerPool);
 virObjectUnref(qemu_driver->config);
 virObjectUnref(qemu_driver->hostdevMgr);
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 2/2] domain_conf: move DomainMergeBlkioDevice out of QEMU and LXC drivers

2019-07-10 Thread Ilias Stamatis
The qemuDomainMergeBlkioDevice and lxcDomainMergeBlkioDevice
functions residing in the QEMU and LXC drivers respectively are
completely identical.

By moving the code to src/conf we avoid code duplication and we make the
function available to other drivers that might need to call it such as
the test driver.

Signed-off-by: Ilias Stamatis 
---
 src/conf/domain_conf.c   | 70 ++
 src/conf/domain_conf.h   |  7 
 src/libvirt_private.syms |  1 +
 src/lxc/lxc_driver.c | 72 +--
 src/qemu/qemu_driver.c   | 81 +++-
 5 files changed, 86 insertions(+), 145 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e10390189c..80e463cc3f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30334,6 +30334,76 @@ virDomainParseBlkioDeviceStr(char *blkioDeviceStr,
 }


+/* Modify dest_array to reflect all blkio device changes described in
+ * src_array.  */
+int
+virDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
+  size_t *dest_size,
+  virBlkioDevicePtr src_array,
+  size_t src_size,
+  const char *type)
+{
+size_t i, j;
+virBlkioDevicePtr dest, src;
+
+for (i = 0; i < src_size; i++) {
+bool found = false;
+
+src = _array[i];
+for (j = 0; j < *dest_size; j++) {
+dest = &(*dest_array)[j];
+if (STREQ(src->path, dest->path)) {
+found = true;
+
+if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
+dest->weight = src->weight;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
+dest->riops = src->riops;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
+dest->wiops = src->wiops;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
+dest->rbps = src->rbps;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
+dest->wbps = src->wbps;
+} else {
+virReportError(VIR_ERR_INVALID_ARG, _("Unknown parameter 
%s"),
+   type);
+return -1;
+}
+break;
+}
+}
+if (!found) {
+if (!src->weight && !src->riops && !src->wiops && !src->rbps && 
!src->wbps)
+continue;
+if (VIR_EXPAND_N(*dest_array, *dest_size, 1) < 0)
+return -1;
+dest = &(*dest_array)[*dest_size - 1];
+
+if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
+dest->weight = src->weight;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
+dest->riops = src->riops;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
+dest->wiops = src->wiops;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
+dest->rbps = src->rbps;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
+dest->wbps = src->wbps;
+} else {
+*dest_size = *dest_size - 1;
+return -1;
+}
+
+dest->path = src->path;
+src->path = NULL;
+}
+}
+
+return 0;
+}
+
+
 int
 virDomainGetBlkioParametersAssignFromDef(virDomainDefPtr def,
  virTypedParameterPtr params,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f31193b8d6..df02f60109 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3547,6 +3547,13 @@ virDomainGetBlkioParametersAssignFromDef(virDomainDefPtr 
def,
  int *nparams,
  int maxparams);

+int
+virDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
+  size_t *dest_size,
+  virBlkioDevicePtr src_array,
+  size_t src_size,
+  const char *type);
+
 int virDomainDiskSetBlockIOTune(virDomainDiskDefPtr disk,
 virDomainBlockIoTuneInfo *info);

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5de3e6483f..a85c99525f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -455,6 +455,7 @@ virDomainMemoryModelTypeToString;
 virDomainMemoryRemove;
 virDomainMemorySourceTypeFromString;
 virDomainMemorySourceTypeToString;
+virDomainMergeBlkioDevice;
 virDomainNetAllocateActualDevice;
 virDomainNetAppendIPAddress;
 virDomainNetBandwidthUpdate;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 0b3ca6a3ce..ad83cc94d7 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2102,74 

[libvirt] [PATCH 1/2] domain_conf: move DomainParseBlkioDeviceStr out of QEMU and LXC drivers

2019-07-10 Thread Ilias Stamatis
The qemuDomainParseBlkioDeviceStr and lxcDomainParseBlkioDeviceSts
functions residing in the QEMU and LXC drivers respectively are
completely identical.

By moving the code to src/conf we avoid code duplication and we make the
function available to other drivers that might need to call it such as
the test driver.

Signed-off-by: Ilias Stamatis 
---
 src/conf/domain_conf.c   | 115 +++
 src/conf/domain_conf.h   |   6 ++
 src/libvirt_private.syms |   1 +
 src/lxc/lxc_driver.c | 112 +-
 src/qemu/qemu_driver.c   | 126 +++
 5 files changed, 132 insertions(+), 228 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3323c9a5b1..e10390189c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30219,6 +30219,121 @@ virDomainDefGetShortName(const virDomainDef *def)

 #undef VIR_DOMAIN_SHORT_NAME_MAX

+
+/* blkioDeviceStr in the form of /device/path,weight,/device/path,weight
+ * for example, /dev/disk/by-path/pci-:00:1f.2-scsi-0:0:0:0,800
+ */
+int
+virDomainParseBlkioDeviceStr(char *blkioDeviceStr,
+ const char *type,
+ virBlkioDevicePtr *dev,
+ size_t *size)
+{
+char *temp;
+int ndevices = 0;
+int nsep = 0;
+size_t i;
+virBlkioDevicePtr result = NULL;
+
+*dev = NULL;
+*size = 0;
+
+if (STREQ(blkioDeviceStr, ""))
+return 0;
+
+temp = blkioDeviceStr;
+while (temp) {
+temp = strchr(temp, ',');
+if (temp) {
+temp++;
+nsep++;
+}
+}
+
+/* A valid string must have even number of fields, hence an odd
+ * number of commas.  */
+if (!(nsep & 1))
+goto parse_error;
+
+ndevices = (nsep + 1) / 2;
+
+if (VIR_ALLOC_N(result, ndevices) < 0)
+return -1;
+
+i = 0;
+temp = blkioDeviceStr;
+while (temp) {
+char *p = temp;
+
+/* device path */
+p = strchr(p, ',');
+if (!p)
+goto parse_error;
+
+if (VIR_STRNDUP(result[i].path, temp, p - temp) < 0)
+goto cleanup;
+
+/* value */
+temp = p + 1;
+
+if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT)) {
+if (virStrToLong_uip(temp, , 10, [i].weight) < 0)
+goto number_error;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS)) {
+if (virStrToLong_uip(temp, , 10, [i].riops) < 0)
+goto number_error;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS)) {
+if (virStrToLong_uip(temp, , 10, [i].wiops) < 0)
+goto number_error;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_READ_BPS)) {
+if (virStrToLong_ullp(temp, , 10, [i].rbps) < 0)
+goto number_error;
+} else if (STREQ(type, VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS)) {
+if (virStrToLong_ullp(temp, , 10, [i].wbps) < 0)
+goto number_error;
+} else {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("unknown parameter '%s'"), type);
+goto cleanup;
+}
+
+i++;
+
+if (*p == '\0')
+break;
+else if (*p != ',')
+goto parse_error;
+temp = p + 1;
+}
+
+if (!i)
+VIR_FREE(result);
+
+*dev = result;
+*size = i;
+
+return 0;
+
+ parse_error:
+virReportError(VIR_ERR_INVALID_ARG,
+   _("unable to parse blkio device '%s' '%s'"),
+   type, blkioDeviceStr);
+goto cleanup;
+
+ number_error:
+virReportError(VIR_ERR_INVALID_ARG,
+   _("invalid value '%s' for parameter '%s' of device '%s'"),
+   temp, type, result[i].path);
+
+ cleanup:
+if (result) {
+virBlkioDeviceArrayClear(result, ndevices);
+VIR_FREE(result);
+}
+return -1;
+}
+
+
 int
 virDomainGetBlkioParametersAssignFromDef(virDomainDefPtr def,
  virTypedParameterPtr params,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c1b5fc1337..f31193b8d6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3535,6 +3535,12 @@ bool virDomainDefHasMemballoon(const virDomainDef *def) 
ATTRIBUTE_NONNULL(1);

 char *virDomainDefGetShortName(const virDomainDef *def) ATTRIBUTE_NONNULL(1);

+int
+virDomainParseBlkioDeviceStr(char *blkioDeviceStr,
+ const char *type,
+ virBlkioDevicePtr *dev,
+ size_t *size);
+
 int
 virDomainGetBlkioParametersAssignFromDef(virDomainDefPtr def,
  virTypedParameterPtr params,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0545c08428..5de3e6483f 100644
--- a/src/libvirt_private.syms
+++ 

[libvirt] [PATCH 0/2] qemu and lxc: remove duplicate code and move some definitions to domain_conf

2019-07-10 Thread Ilias Stamatis
Ilias Stamatis (2):
  domain_conf: move DomainParseBlkioDeviceStr out of QEMU and LXC
drivers
  domain_conf: move DomainMergeBlkioDevice out of QEMU and LXC drivers

 src/conf/domain_conf.c   | 185 ++
 src/conf/domain_conf.h   |  13 +++
 src/libvirt_private.syms |   2 +
 src/lxc/lxc_driver.c | 184 +-
 src/qemu/qemu_driver.c   | 207 +++
 5 files changed, 218 insertions(+), 373 deletions(-)

--
2.22.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 05/23] util: add API for resolving socket service names

2019-07-10 Thread Ján Tomko

On Thu, Jun 27, 2019 at 10:54:34AM +0100, Daniel P. Berrangé wrote:

The getservent() APIs are not re-entrant safe so cannot be used in any
threaded program. Add a wrapper around getaddrinfo() for resolving the
service names to a port number.

Signed-off-by: Daniel P. Berrangé 
---
src/libvirt_private.syms |  1 +
src/util/virsocketaddr.c | 51 
src/util/virsocketaddr.h |  2 ++
3 files changed, 54 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ce614e04bd..1adf735a38 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2919,6 +2919,7 @@ virSocketAddrParseIPv4;
virSocketAddrParseIPv6;
virSocketAddrPrefixToNetmask;
virSocketAddrPTRDomain;
+virSocketAddrResolveService;
virSocketAddrSetIPv4Addr;
virSocketAddrSetIPv4AddrNetOrder;
virSocketAddrSetIPv6Addr;
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 7a50cbe040..790bc0ebec 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -235,6 +235,57 @@ virSocketAddrParseIPv6(virSocketAddrPtr addr, const char 
*val)
return virSocketAddrParse(addr, val, AF_INET6);
}

+/**
+ * virSocketAddrResolveService:
+ * @service: a service name or port number
+ *
+ * Resolve a service, which might be a plain port or service name,
+ * into a port number for IPv4/IPv6 usage
+ *
+ * Returns a numberic port number


or -1 on error


+ */


Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 04/23] util: add VIR_AUTOSTRUCT for directly calling a struct free function

2019-07-10 Thread Ján Tomko

On Thu, Jun 27, 2019 at 10:54:33AM +0100, Daniel P. Berrangé wrote:

The current VIR_AUTOPTR macro assumes that the struct needs to have a
auto-free function auto-generated to call the real free function.

The new VIR_AUTOSTRUCT macro allows for structs which already have a
free function which takes a pointer to a pointer to the struct and can
thus be used directly for auto-cleanup.

Signed-off-by: Daniel P. Berrangé 
---
src/util/viralloc.h | 13 +
1 file changed, 13 insertions(+)

diff --git a/src/util/viralloc.h b/src/util/viralloc.h
index 2b82096fde..5de18b9ea0 100644
--- a/src/util/viralloc.h
+++ b/src/util/viralloc.h
@@ -614,3 +614,16 @@ void virAllocTestHook(void (*func)(int, void*), void 
*data);
 * when the variable goes out of scope.
 */
#define VIR_AUTOFREE(type) __attribute__((cleanup(virFree))) type
+
+/**
+ * VIR_AUTOSTRUCT:
+ * @type: type of the struct variable to be freed automatically
+ *
+ * Macro to automatically free the memory allocated to
+ * the struct variable declared with it by calling vir$STRUCTFree
+ * when the variable goes out of scope.
+ *
+ * The vir$STRUCTFree function must take a pointer to a pointer
+ * to the struct.
+ */
+#define VIR_AUTOSTRUCT(type) __attribute__((cleanup(type ## Free))) type


commit a4bfc2521f8aeff8f4e4431a8e2332cc74806b8a
   util: Move the VIR_AUTO(CLEAN|PTR) helper macros into a separate header

moved the macros not depending on other stuff from viralloc.h to virautoclean.h

This macro would better fit there.

Also, sc_require_attribute_cleanup_initialization will need a touch-up.
Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 03/23] rpc: add helper API for getting UNIX path from socket object

2019-07-10 Thread Ján Tomko

On Thu, Jun 27, 2019 at 10:54:32AM +0100, Daniel P. Berrangé wrote:

Signed-off-by: Daniel P. Berrangé 
---
src/libvirt_remote.syms | 1 +
src/rpc/virnetsocket.c  | 8 
src/rpc/virnetsocket.h  | 1 +
3 files changed, 10 insertions(+)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 02/23] util: add helper API for getting UNIX path from socket address

2019-07-10 Thread Ján Tomko

On Thu, Jun 27, 2019 at 10:54:31AM +0100, Daniel P. Berrangé wrote:

Signed-off-by: Daniel P. Berrangé 
---
src/libvirt_private.syms |  1 +
src/util/virsocketaddr.c | 42 
src/util/virsocketaddr.h |  2 ++
3 files changed, 45 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 34937adc5d..ce614e04bd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2903,6 +2903,7 @@ virSocketAddrFormat;
virSocketAddrFormatFull;
virSocketAddrGetIPPrefix;
virSocketAddrGetNumNetmaskBits;
+virSocketAddrGetPath;
virSocketAddrGetPort;
virSocketAddrGetRange;
virSocketAddrIsNetmask;
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 182e18aa8c..7a50cbe040 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -500,6 +500,7 @@ virSocketAddrSetPort(virSocketAddrPtr addr, int port)
return 0;
}

+


Unrelated whitespace.


/*
 * virSocketGetPort:
 * @addr: an initialized virSocketAddrPtr


Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 01/23] locking, logging: put a strong dep from admin socket to main socket

2019-07-10 Thread Ján Tomko

On Thu, Jun 27, 2019 at 10:54:30AM +0100, Daniel P. Berrangé wrote:

It doesn't make sense to have the admin socket active if the main
socket is not running, so bind their lifecycle together.

This ensures that if primary socket is stopped, the corresponding
admin socket is also stopped.

In the reverse, starting the admin socket will also automatically
start the primary socket.

Signed-off-by: Daniel P. Berrangé 
---
src/locking/virtlockd-admin.socket.in | 2 ++
src/logging/virtlogd-admin.socket.in  | 2 ++
2 files changed, 4 insertions(+)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH] vz: fix typo that lost the '#' in '#define'

2019-07-10 Thread Daniel P . Berrangé
Previous commit:

  commit faceedaf7170903065807e2c37dd0d1bd06a6ef5
  Author: Jonathon Jongsma 
  Date:   Tue Jun 18 11:13:12 2019 -0500

src/vz: use #pragma once in headers

accidentally chomped the "#" in a "#define" when re-indenting

Signed-off-by: Daniel P. Berrangé 
---
 src/vz/vz_utils.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/vz/vz_utils.h b/src/vz/vz_utils.h
index d9e3ebc30a..f116f9dd1f 100644
--- a/src/vz/vz_utils.h
+++ b/src/vz/vz_utils.h
@@ -145,7 +145,7 @@ vzGetDefaultSCSIModel(vzDriverPtr driver,
 
 int vzCheckUnsupportedGraphics(virDomainGraphicsDefPtr gr);
 
- define PARALLELS_BLOCK_STATS_FOREACH(OP) \
+#define PARALLELS_BLOCK_STATS_FOREACH(OP) \
 OP(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ, "read_requests") \
 OP(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES, "read_total") \
 OP(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ, "write_requests") \
-- 
2.21.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH] virfile: adds quobyte as a shared fs

2019-07-10 Thread Silvan Kaiser
Am Sa., 15. Juni 2019 um 14:59 Uhr schrieb Michal Prívozník <
mpriv...@redhat.com>:

> On 5/28/19 2:55 PM, Silvan Kaiser wrote:
> > Adds detection of a Quobyte shared file system for
> > live migration.
> >
> > Signed-off-by: Silvan Kaiser 
> > ---
> >  src/util/virfile.c| 13 -
> >  src/util/virfile.h|  1 +
> >  tests/virfiledata/mounts3.txt |  1 +
> >  tests/virfilemock.c   |  3 +++
> >  tests/virfiletest.c   |  1 +
> >  5 files changed, 18 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/util/virfile.c b/src/util/virfile.c
> > index f7415cf633..a46b8792f6 100644
> > --- a/src/util/virfile.c
> > +++ b/src/util/virfile.c
> > @@ -3434,6 +3434,9 @@ int virFilePrintf(FILE *fp, const char *msg, ...)
> >  # ifndef GPFS_SUPER_MAGIC
> >  #  define GPFS_SUPER_MAGIC 0x47504653
> >  # endif
> > +# ifndef QB_MAGIC
> > +#  define QB_MAGIC 0x51626d6e
> > +# endif
> >
> >  # define PROC_MOUNTS "/proc/mounts"
> >
> > @@ -3490,6 +3493,10 @@ virFileIsSharedFixFUSE(const char *path,
> >  VIR_DEBUG("Found gluster FUSE mountpoint=%s for path=%s. "
> >"Fixing shared FS type", mntDir, canonPath);
> >  *f_type = GFS2_MAGIC;
> > +} else if (STREQ_NULLABLE(mntType, "fuse.quobyte")) {
> > +VIR_DEBUG("Found Quobyte FUSE mountpoint=%s for path=%s. "
> > +  "Fixing shared FS type", mntDir, canonPath);
> > +*f_type = QB_MAGIC;
> >  }
> >
> >  ret = 0;
> > @@ -3582,6 +3589,9 @@ virFileIsSharedFSType(const char *path,
> >  if ((fstypes & VIR_FILE_SHFS_GPFS) &&
> >  (f_type == GPFS_SUPER_MAGIC))
> >  return 1;
> > +if ((fstypes & VIR_FILE_SHFS_QB) &&
> > +(f_type == QB_MAGIC))
> > +return 1;
> >
> >  return 0;
> >  }
> > @@ -3771,7 +3781,8 @@ int virFileIsSharedFS(const char *path)
> >   VIR_FILE_SHFS_SMB |
> >   VIR_FILE_SHFS_CIFS |
> >   VIR_FILE_SHFS_CEPH |
> > - VIR_FILE_SHFS_GPFS);
> > + VIR_FILE_SHFS_GPFS|
> > + VIR_FILE_SHFS_QB);
> >  }
> >
> >
> > diff --git a/src/util/virfile.h b/src/util/virfile.h
> > index 641960e2ca..e06855ea86 100644
> > --- a/src/util/virfile.h
> > +++ b/src/util/virfile.h
> > @@ -212,6 +212,7 @@ enum {
> >  VIR_FILE_SHFS_CIFS = (1 << 5),
> >  VIR_FILE_SHFS_CEPH = (1 << 6),
> >  VIR_FILE_SHFS_GPFS = (1 << 7),
> > +VIR_FILE_SHFS_QB = (1 << 8),
> >  };
> >
> >  int virFileIsSharedFSType(const char *path, int fstypes)
> ATTRIBUTE_NONNULL(1);
> > diff --git a/tests/virfiledata/mounts3.txt
> b/tests/virfiledata/mounts3.txt
> > index 4377e5d471..b91804a4e4 100644
> > --- a/tests/virfiledata/mounts3.txt
> > +++ b/tests/virfiledata/mounts3.txt
> > @@ -36,3 +36,4 @@ root@host:/tmp/mkdir /gluster/sshfs fuse.sshfs rw 0 0
> >  192.168.0.1:/ceph/data /ceph ceph
> rw,noatime,name=cephfs,secret=,acl,wsize=16777216 0 0
> >  192.168.0.1,192.168.0.2,192.168.0.3:/ceph/data2 /ceph/multi ceph
> rw,noatime,name=cephfs,secret=,acl,wsize=16777216 0 0
> >  gpfs_data /gpfs/data gpfs rw,relatime 0 0
> > +quobyte@192.168.0.1/data /quobyte fuse.quobyte
> rw,nosuid,nodev,noatime,user_id=0,group_id=0,allow_other 0 0
> > diff --git a/tests/virfilemock.c b/tests/virfilemock.c
> > index 106032f857..54c57d417b 100644
> > --- a/tests/virfilemock.c
> > +++ b/tests/virfilemock.c
> > @@ -92,6 +92,9 @@ setmntent(const char *filename, const char *type)
> >  #ifndef GPFS_SUPER_MAGIC
> >  # define GPFS_SUPER_MAGIC 0x47504653
> >  #endif
> > +# ifndef QB_MAGIC
> > +#  define QB_MAGIC 0x51626d6e
> > +# endif
>
> Misaligned lines. I'll fix that before push.


> But before ACK and push this, is there some place I can verify this
> magic number? Also, just to make sure we are on the same page here, a
> sole fact that a FS is distributed does not qualify it for being
> detected as shared FS by libvirt. Because of how qemu handles migration,
> libvirt can allow only those shared FS which are also cache coherent. I
> have no experience with quobyte and it looks like a proprietary
> solution. Wasn't it formerly known as XtreemFS?
>
> Michal
>

The magic number was defined only in this patch, so far we've never needed
to define this. It's serving as a unique id for the Quobyte filesystem.

Regarding cache coherence: yes this is supported. Quobyte has specific
libvirt
migration support to ensure this.

Regarding XtreemFS: Yep, Quobyte basically is a rewritten, improved and over
the years much more advanced proprietary version of XtreemFS. A major
portion
of the original xtreemfs dev team founded and/or worked/works at Quobyte.

Thanks for reviewing and sorry for the late reply, i was on vacation.
Best
Silvan


-- 
Dr.-Ing. Silvan Kaiser
Quobyte GmbH
Hardenbergplatz 2, 10623 Berlin - Germany
+49-30-814 591 800 - www.quobyte.com
Amtsgericht 

Re: [libvirt] [RFC] New domain job control and stat APIs

2019-07-10 Thread Peter Krempa
On Wed, Jul 10, 2019 at 08:38:20 -0500, Eric Blake wrote:
> On 7/10/19 7:27 AM, Peter Krempa wrote:
> > Currently we don't have a consolidated approach for managing
> > asynchronous long-running domain jobs. Historically there were
> > long-running jobs which interlocked with each other and thus there was
> > only one such job possible at given time (migration, save, restore, dump)
> 
> Yes, I agree with the problem statement. In fact, one of my questions
> when starting on incremental backup was whether I'd have to implement
> any of this first, or punt it to later. Well, here we are; it's later,
> and I still don't have incremental backup in.
> 
> > 
> > These jobs have a not very flexible set of APIs:
> > virDomainGetJobInfo, virDomainGetJobStats, virDomainAbortJob.
> > 
> > These don't really allow selecting which job to terminate since there's
> > only one, thus if we wanted to add different kinds of jobs which not
> > necessarily interlock but are able to run in parallel we had to
> > introduce another set of APIs.
> > 
> > This resulted into creation of block job APIs:
> > virDomainBlockJobAbort, virDomainGetBlockJobInfo
> > 
> > These allow parallel jobs (discriminated by disk to which the job
> > belongs) but are not universal and nor allow parallel jobs on a single
> > disk.
> > 
> > Similarly blockjobs can also become detached from the disk e.g. if the
> > guest unplugs the disk fronted. That way the job would linger in a limbo
> > and would not be controllable. (This is certainly a possibility with
> > -blockdev).
> > 
> > With -blockdev we also get a potentially long-running blockdev-create
> > job which is not bound to any disk as part of kicking of a snapshot or
> > block copy job. This one might also get stuck and in the current state
> > is not really controllable.
> > 
> > Additionally the upcomming block-backup job will be a combination of the
> > above. It's a job which spans multiple disks (thus not really a block
> > job in libvirt terminology) but not a domain job either as there
> > can be potentially more than one block backup job. The proposal for
> > block-backup introduces it's own single-purpose set of APIs for managing
> > the backup job only, but abuses the block job and domain job events to
> > distribute the async state updates.
> 
> At the bare minimum, a push job implementation has to send async state
> update events, but a pull job does not. If the backup API goes into
> 5.6.0 but not your new job control APIs, we can limit the qemu
> implementation to JUST pull backups for now (the XML has been shown to
> be extensible to add in push support once we also have sane APIs for
> managing async state updates with push support).
> 
> > 
> > With this series I want to introduce a set of APIs for managing the jobs
> > which are designed to be universal enough and a new event so that noting
> > will try to retrofit onto existing infrastructure.
> > 
> > An example of the job XML would be:
> > 
> > 
> >   
> > vda
> > vda[1]
> > vda[5]
> >   
> 
> Where what forms a valid  is dependent on the type='...' of the
> , correct?

Yes exactly.

> 
> >   
> >12345
> >12345
> >   
> > 
> 
> Looks reasonable.
> 
> > 
> > but this will be mostly a topic for the second part of this excercise
> > after we discuss the APIs.
> > 
> > The new infrastructure will also allow adding a flag for all the
> > existing APIs which kick-off a job so that the job will persist even
> > after it finishes. This will also properly implement the statistics for
> > a finished migration and similar.
> > 
> > Obviously we will need to take special care when wiring up these so that
> > the old APIs work for old situations and also the events are reported
> > correctly.
> > 
> > The initial idea would be to implement the stats XML both for the domain
> > jobs (migration, dump) and blockjobs to simplify the job for mgmt apps
> > so that they won't have to infer whether the given job type is already
> > reported in the new API.
> > 
> > Additionally we can also implement flags for the XML getter API that
> > will skip the stats gathering as that may require monitor interactions.
> > Also one possibility would be to return an abbreviated XML in the
> > listing API.
> 
> Makes sense.
> 
> > ---

[...]

> > +typedef enum {
> > +VIR_DOMAIN_JOB_STATE_NONE = 0, /* unknown job state */
> > +VIR_DOMAIN_JOB_STATE_RUNNING = 1, /* job is currently running */
> > +VIR_DOMAIN_JOB_STATE_READY = 2, /* job reached a synchronized state 
> > and may be finalized */
> > +VIR_DOMAIN_JOB_STATE_FAILED = 3, /* job has failed */
> > +VIR_DOMAIN_JOB_STATE_COMPLETED = 4, /* job has completed successfully 
> > */
> > +VIR_DOMAIN_JOB_STATE_ABORTED = 5, /* job has been aborted */
> > +[...]
> > +
> > +# ifdef VIR_ENUM_SENTINELS
> > +VIR_DOMAIN_JOB_STATE_LAST
> > +# endif
> > +} virDomainJobState;
> 
> Not all job types will utilize all of the possible job states, but I
> don't see that as an 

Re: [libvirt] Problem configuring selective dropping of root

2019-07-10 Thread Martin Kletzander

On Wed, Jul 10, 2019 at 03:44:54PM +0200, Stephan von Krawczynski wrote:

On Wed, 10 Jul 2019 14:48:14 +0200
Martin Kletzander  wrote:


On Tue, Jul 09, 2019 at 02:45:18PM +0200, Stephan von Krawczynski wrote:
>On Tue, 9 Jul 2019 14:26:08 +0200
>Pavel Hrdina  wrote:
>
>> On Tue, Jul 09, 2019 at 02:03:15PM +0200, Stephan von Krawczynski wrote:
>> > On Tue, 9 Jul 2019 09:40:23 +0100
>> > Daniel P. Berrangé  wrote:
>> >
>> > > On Mon, Jul 08, 2019 at 09:47:24PM +0200, Stephan von Krawczynski
>> > > wrote:
>> > > > Hello list,
>> > > >
>> > > > I came across a fundamental flaw in the libvirt user configuration
>> > > > lately and try to find a solution now. Here is the problem:
>> > > > I run several qemu instances on arch linux all configured via libvirt.
>> > > > The default config as user nobody:kvm was fine up to the day I tried
>> > > > to use a host filesystem via 9p. If you want to gain all user rights
>> > > > on the guest inside that fs you have to run qemu as root. So far so
>> > > > good. But if you have several qemus running and only one needs to be
>> > > > root, what to do? You can try to give a -runas by using .
>> > > > But that does not work, qemu instantly crashes. I think this is
>> > > > because to have _one_ root qemu, you have to configure libvirt to use
>> > > > root user. This means all rights to fs and so on are set to root and
>> > > > this is what lets qemu probably go crazy if dropping root by -runas.
>> > > > The whole thing would be a lot easier and more transparent if the user
>> > > > in libvirt wouldn't be a global config, but instead be part of the
>> > > > domain xml. This way every qemu started could use a different user and
>> > > > have different rights. In my case all but one could be nobody:kvm, and
>> > > > one root:root. This should not be to complicated based on whats
>> > > > already there, is it?
>> > >
>> > > Libvirt needs to know about the user/group QEMU is running at in order to
>> > > ensure it gets given access to the various files it needs to use. If you
>> > > look at the XML of the running guest you should see a 
>> > > describing the user/group it is running as currently.
>> > >
>> > > If no  is in the offline config, libvirt adds the default
>> > > seclabel, but if you want a different user/group, you can add the
>> > >  yourself.
>> > >
>> > > Regards,
>> > > Daniel
>> >
>> > Hello Daniel,
>> >
>> > well, tried that (as good as the docs are) by adding:
>> >
>> > 
>> >   nobody:kvm
>> > 
>> >
>> > This edit worked in virsh without giving errors.
>> > Starting the domain and then looking into the xml showed:
>> >
>> >   
>> >
>> > Consequently qemu runs still as root. My user:group setting simply
>> > vanished.
>> >
>> > I think at least some better docs are needed with a striking example of
>> > how to change user and group ...
>> > I may be biased, but how to set user and group is probably the most basic
>> > example of how to use seclabel - and I cannot find one.
>>
>> I agree that the documentation is not the best one.
>>
>> You need to use type='static' relabel='yes':
>>
>> 
>>   nobody:kvm
>> 
>>
>> To achieve that.
>>
>> In addition if you would like to have only one VM as root:root you
>> should keep the default config as nobody:kvm and use the root:root for
>> that specific VM.
>>
>> Pavel
>
>Hello Pavel,
>
>thank you for taking up the thread, but unfortunately your suggestion does not
>work:
>
>virsh # start collabora
>Fehler: Domain collabora konnte nicht gestartet werden
>Fehler: Interner Fehler: process exited while connecting to monitor:
>2019-07-09T12:34:00.735392Z qemu-system-x86_64: -object
>secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-17-collabora/master-key.aes:
>Unable to read /var/lib/libvirt/qemu/domain-17-collabora/master-key.aes:
>Failed to open file
>“/var/lib/libvirt/qemu/domain-17-collabora/master-key.aes”: Permission denied
>
>Obviously this is because "type='static'" means that libvirt does not care
>about setting the user rights for qemu, which then leads to this.

No, 'static' means you tell libvirt what the label should be, 'dynamic' means
libvirt will generate it automatically.

>I did think "relabel='yes'" should do that, but does not - or I have a deep
>misunderstanding concerning the seclabel parameters ...
>Thanks for any help to solve this, if there is no bug involved.
>

Relabel definitely does that and unless there is a bug it uses the seclabel for
the domain.  What could be happening is that one of the parent directories is
missing a browse permission for others (the last 'x' in rwxrwxrwx).  Could you
run the following commands and reply with the output?

ls -ld /var/lib/
ls -ld /var/lib/libvirt/
ls -ld /var/lib/libvirt/qemu/

Also what distribution are you using?  I remember there were some differences in
packaging related to the directory permissions.

Martin

>Dumpxml shows this btw:
>
>  
>nobody:kvm
>  
>
>which at least is what was configured.
>--
>Regards,
>Stephan


Hello Martin,


Re: [libvirt] Problem configuring selective dropping of root

2019-07-10 Thread Stephan von Krawczynski
On Wed, 10 Jul 2019 14:48:14 +0200
Martin Kletzander  wrote:

> On Tue, Jul 09, 2019 at 02:45:18PM +0200, Stephan von Krawczynski wrote:
> >On Tue, 9 Jul 2019 14:26:08 +0200
> >Pavel Hrdina  wrote:
> >  
> >> On Tue, Jul 09, 2019 at 02:03:15PM +0200, Stephan von Krawczynski wrote:  
> >> > On Tue, 9 Jul 2019 09:40:23 +0100
> >> > Daniel P. Berrangé  wrote:
> >> >  
> >> > > On Mon, Jul 08, 2019 at 09:47:24PM +0200, Stephan von Krawczynski
> >> > > wrote:  
> >> > > > Hello list,
> >> > > >
> >> > > > I came across a fundamental flaw in the libvirt user configuration
> >> > > > lately and try to find a solution now. Here is the problem:
> >> > > > I run several qemu instances on arch linux all configured via 
> >> > > > libvirt.
> >> > > > The default config as user nobody:kvm was fine up to the day I tried
> >> > > > to use a host filesystem via 9p. If you want to gain all user rights
> >> > > > on the guest inside that fs you have to run qemu as root. So far so
> >> > > > good. But if you have several qemus running and only one needs to be
> >> > > > root, what to do? You can try to give a -runas by using .
> >> > > > But that does not work, qemu instantly crashes. I think this is
> >> > > > because to have _one_ root qemu, you have to configure libvirt to use
> >> > > > root user. This means all rights to fs and so on are set to root and
> >> > > > this is what lets qemu probably go crazy if dropping root by -runas.
> >> > > > The whole thing would be a lot easier and more transparent if the 
> >> > > > user
> >> > > > in libvirt wouldn't be a global config, but instead be part of the
> >> > > > domain xml. This way every qemu started could use a different user 
> >> > > > and
> >> > > > have different rights. In my case all but one could be nobody:kvm, 
> >> > > > and
> >> > > > one root:root. This should not be to complicated based on whats
> >> > > > already there, is it?  
> >> > >
> >> > > Libvirt needs to know about the user/group QEMU is running at in order 
> >> > > to
> >> > > ensure it gets given access to the various files it needs to use. If 
> >> > > you
> >> > > look at the XML of the running guest you should see a 
> >> > > describing the user/group it is running as currently.
> >> > >
> >> > > If no  is in the offline config, libvirt adds the default
> >> > > seclabel, but if you want a different user/group, you can add the
> >> > >  yourself.
> >> > >
> >> > > Regards,
> >> > > Daniel  
> >> >
> >> > Hello Daniel,
> >> >
> >> > well, tried that (as good as the docs are) by adding:
> >> >
> >> > 
> >> >  nobody:kvm
> >> > 
> >> >
> >> > This edit worked in virsh without giving errors.
> >> > Starting the domain and then looking into the xml showed:
> >> >
> >> >   
> >> >
> >> > Consequently qemu runs still as root. My user:group setting simply
> >> > vanished.
> >> >
> >> > I think at least some better docs are needed with a striking example of
> >> > how to change user and group ...
> >> > I may be biased, but how to set user and group is probably the most basic
> >> > example of how to use seclabel - and I cannot find one.  
> >>
> >> I agree that the documentation is not the best one.
> >>
> >> You need to use type='static' relabel='yes':
> >>
> >> 
> >>   nobody:kvm
> >> 
> >>
> >> To achieve that.
> >>
> >> In addition if you would like to have only one VM as root:root you
> >> should keep the default config as nobody:kvm and use the root:root for
> >> that specific VM.
> >>
> >> Pavel  
> >
> >Hello Pavel,
> >
> >thank you for taking up the thread, but unfortunately your suggestion does 
> >not
> >work:
> >
> >virsh # start collabora
> >Fehler: Domain collabora konnte nicht gestartet werden
> >Fehler: Interner Fehler: process exited while connecting to monitor:
> >2019-07-09T12:34:00.735392Z qemu-system-x86_64: -object
> >secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-17-collabora/master-key.aes:
> >Unable to read /var/lib/libvirt/qemu/domain-17-collabora/master-key.aes:
> >Failed to open file
> >“/var/lib/libvirt/qemu/domain-17-collabora/master-key.aes”: Permission denied
> >
> >Obviously this is because "type='static'" means that libvirt does not care
> >about setting the user rights for qemu, which then leads to this.  
> 
> No, 'static' means you tell libvirt what the label should be, 'dynamic' means
> libvirt will generate it automatically.
> 
> >I did think "relabel='yes'" should do that, but does not - or I have a deep
> >misunderstanding concerning the seclabel parameters ...
> >Thanks for any help to solve this, if there is no bug involved.
> >  
> 
> Relabel definitely does that and unless there is a bug it uses the seclabel 
> for
> the domain.  What could be happening is that one of the parent directories is
> missing a browse permission for others (the last 'x' in rwxrwxrwx).  Could you
> run the following commands and reply with the output?
> 
> ls -ld /var/lib/
> ls -ld /var/lib/libvirt/
> ls -ld /var/lib/libvirt/qemu/
> 
> Also what distribution 

Re: [libvirt] [PATCH] rpc: always pass "-T -e none" args to ssh

2019-07-10 Thread Andrea Bolognani
On Tue, 2019-07-09 at 18:15 +0100, Daniel P. Berrangé wrote:
> Way back in the past, the "no_tty=1" option was added for the remote
> driver to disable local password prompting by disabling use of the local
> tty:
> 
>   commit b32f42984994a397441a1c48f1a002e906624c51
>   Author: Daniel P. Berrange 
>   Date:   Fri Sep 21 20:17:09 2007 +
> 
> Added a no_tty param to remote URIs to stop SSH prompting for password
> 
> This was done by adding "-T -o BatchMode=yes -e none" args to ssh. This
> achieved the desired results but is none the less semantically flawed
> because it is mixing up config parameters for the local tty vs the
> remote tty.
> 
> The "-T" arg stops allocation of a TTY on the remote host. This is good
> for all libvirt SSH tunnels as we never require a TTY for our usage
> model, so we should have just passed this unconditionally.
> 
> The "-e none" option disables the escape character for sessions with a
> TTY. If we pass "-T" this is not required, but it also not harmful to
> add it, so we should just pass it unconditionally too.
> 
> Only the "-o BatchMode=yes" option is related to disabling local
> password prompts and thus needs control via the no_tty URI param.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
>  src/rpc/virnetsocket.c   |  4 ++--
>  tests/virnetsockettest.c | 34 ++
>  2 files changed, 20 insertions(+), 18 deletions(-)

Great commit message!

The change makes sense, and the ssh documentation confirms the
options you mention indeed mean what you claim they do :)

Reviewed-by: Andrea Bolognani 

-- 
Andrea Bolognani / Red Hat / Virtualization

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [RFC] New domain job control and stat APIs

2019-07-10 Thread Eric Blake
On 7/10/19 7:27 AM, Peter Krempa wrote:
> Currently we don't have a consolidated approach for managing
> asynchronous long-running domain jobs. Historically there were
> long-running jobs which interlocked with each other and thus there was
> only one such job possible at given time (migration, save, restore, dump)

Yes, I agree with the problem statement. In fact, one of my questions
when starting on incremental backup was whether I'd have to implement
any of this first, or punt it to later. Well, here we are; it's later,
and I still don't have incremental backup in.

> 
> These jobs have a not very flexible set of APIs:
> virDomainGetJobInfo, virDomainGetJobStats, virDomainAbortJob.
> 
> These don't really allow selecting which job to terminate since there's
> only one, thus if we wanted to add different kinds of jobs which not
> necessarily interlock but are able to run in parallel we had to
> introduce another set of APIs.
> 
> This resulted into creation of block job APIs:
> virDomainBlockJobAbort, virDomainGetBlockJobInfo
> 
> These allow parallel jobs (discriminated by disk to which the job
> belongs) but are not universal and nor allow parallel jobs on a single
> disk.
> 
> Similarly blockjobs can also become detached from the disk e.g. if the
> guest unplugs the disk fronted. That way the job would linger in a limbo
> and would not be controllable. (This is certainly a possibility with
> -blockdev).
> 
> With -blockdev we also get a potentially long-running blockdev-create
> job which is not bound to any disk as part of kicking of a snapshot or
> block copy job. This one might also get stuck and in the current state
> is not really controllable.
> 
> Additionally the upcomming block-backup job will be a combination of the
> above. It's a job which spans multiple disks (thus not really a block
> job in libvirt terminology) but not a domain job either as there
> can be potentially more than one block backup job. The proposal for
> block-backup introduces it's own single-purpose set of APIs for managing
> the backup job only, but abuses the block job and domain job events to
> distribute the async state updates.

At the bare minimum, a push job implementation has to send async state
update events, but a pull job does not. If the backup API goes into
5.6.0 but not your new job control APIs, we can limit the qemu
implementation to JUST pull backups for now (the XML has been shown to
be extensible to add in push support once we also have sane APIs for
managing async state updates with push support).

> 
> With this series I want to introduce a set of APIs for managing the jobs
> which are designed to be universal enough and a new event so that noting
> will try to retrofit onto existing infrastructure.
> 
> An example of the job XML would be:
> 
> 
>   
> vda
> vda[1]
> vda[5]
>   

Where what forms a valid  is dependent on the type='...' of the
, correct?

>   
>12345
>12345
>   
> 

Looks reasonable.

> 
> but this will be mostly a topic for the second part of this excercise
> after we discuss the APIs.
> 
> The new infrastructure will also allow adding a flag for all the
> existing APIs which kick-off a job so that the job will persist even
> after it finishes. This will also properly implement the statistics for
> a finished migration and similar.
> 
> Obviously we will need to take special care when wiring up these so that
> the old APIs work for old situations and also the events are reported
> correctly.
> 
> The initial idea would be to implement the stats XML both for the domain
> jobs (migration, dump) and blockjobs to simplify the job for mgmt apps
> so that they won't have to infer whether the given job type is already
> reported in the new API.
> 
> Additionally we can also implement flags for the XML getter API that
> will skip the stats gathering as that may require monitor interactions.
> Also one possibility would be to return an abbreviated XML in the
> listing API.

Makes sense.

> ---
>  include/libvirt/libvirt-domain.h | 91 +++
>  src/libvirt-domain.c | 94 
>  2 files changed, 185 insertions(+)
> 
> diff --git a/include/libvirt/libvirt-domain.h 
> b/include/libvirt/libvirt-domain.h
> index 2dbd74d4f3..dac1be 100644
> --- a/include/libvirt/libvirt-domain.h
> +++ b/include/libvirt/libvirt-domain.h
> @@ -4485,6 +4485,28 @@ typedef void 
> (*virConnectDomainEventBlockThresholdCallback)(virConnectPtr conn,
>  unsigned long 
> long excess,
>  void *opaque);
> 
> +/**
> + * virConnectDomainEventJobStateCallback:
> + * @conn: connection object
> + * @dom: domain on which the event occurred
> + * @jobname: name of job which changed state
> + * @jobtype: type of the job
> + * @newstate: the new state the job entered
> + * @opaque: application specified data
> + *
> + * The 

Re: [libvirt] Problem configuring selective dropping of root

2019-07-10 Thread Martin Kletzander

On Tue, Jul 09, 2019 at 02:45:18PM +0200, Stephan von Krawczynski wrote:

On Tue, 9 Jul 2019 14:26:08 +0200
Pavel Hrdina  wrote:


On Tue, Jul 09, 2019 at 02:03:15PM +0200, Stephan von Krawczynski wrote:
> On Tue, 9 Jul 2019 09:40:23 +0100
> Daniel P. Berrangé  wrote:
>
> > On Mon, Jul 08, 2019 at 09:47:24PM +0200, Stephan von Krawczynski
> > wrote:
> > > Hello list,
> > >
> > > I came across a fundamental flaw in the libvirt user configuration
> > > lately and try to find a solution now. Here is the problem:
> > > I run several qemu instances on arch linux all configured via libvirt.
> > > The default config as user nobody:kvm was fine up to the day I tried
> > > to use a host filesystem via 9p. If you want to gain all user rights
> > > on the guest inside that fs you have to run qemu as root. So far so
> > > good. But if you have several qemus running and only one needs to be
> > > root, what to do? You can try to give a -runas by using .
> > > But that does not work, qemu instantly crashes. I think this is
> > > because to have _one_ root qemu, you have to configure libvirt to use
> > > root user. This means all rights to fs and so on are set to root and
> > > this is what lets qemu probably go crazy if dropping root by -runas.
> > > The whole thing would be a lot easier and more transparent if the user
> > > in libvirt wouldn't be a global config, but instead be part of the
> > > domain xml. This way every qemu started could use a different user and
> > > have different rights. In my case all but one could be nobody:kvm, and
> > > one root:root. This should not be to complicated based on whats
> > > already there, is it?
> >
> > Libvirt needs to know about the user/group QEMU is running at in order to
> > ensure it gets given access to the various files it needs to use. If you
> > look at the XML of the running guest you should see a 
> > describing the user/group it is running as currently.
> >
> > If no  is in the offline config, libvirt adds the default
> > seclabel, but if you want a different user/group, you can add the
> >  yourself.
> >
> > Regards,
> > Daniel
>
> Hello Daniel,
>
> well, tried that (as good as the docs are) by adding:
>
> 
>nobody:kvm
> 
>
> This edit worked in virsh without giving errors.
> Starting the domain and then looking into the xml showed:
>
>   
>
> Consequently qemu runs still as root. My user:group setting simply
> vanished.
>
> I think at least some better docs are needed with a striking example of
> how to change user and group ...
> I may be biased, but how to set user and group is probably the most basic
> example of how to use seclabel - and I cannot find one.

I agree that the documentation is not the best one.

You need to use type='static' relabel='yes':


  nobody:kvm


To achieve that.

In addition if you would like to have only one VM as root:root you
should keep the default config as nobody:kvm and use the root:root for
that specific VM.

Pavel


Hello Pavel,

thank you for taking up the thread, but unfortunately your suggestion does not
work:

virsh # start collabora
Fehler: Domain collabora konnte nicht gestartet werden
Fehler: Interner Fehler: process exited while connecting to monitor:
2019-07-09T12:34:00.735392Z qemu-system-x86_64: -object
secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-17-collabora/master-key.aes:
Unable to read /var/lib/libvirt/qemu/domain-17-collabora/master-key.aes:
Failed to open file
“/var/lib/libvirt/qemu/domain-17-collabora/master-key.aes”: Permission denied

Obviously this is because "type='static'" means that libvirt does not care
about setting the user rights for qemu, which then leads to this.


No, 'static' means you tell libvirt what the label should be, 'dynamic' means
libvirt will generate it automatically.


I did think "relabel='yes'" should do that, but does not - or I have a deep
misunderstanding concerning the seclabel parameters ...
Thanks for any help to solve this, if there is no bug involved.



Relabel definitely does that and unless there is a bug it uses the seclabel for
the domain.  What could be happening is that one of the parent directories is
missing a browse permission for others (the last 'x' in rwxrwxrwx).  Could you
run the following commands and reply with the output?

ls -ld /var/lib/
ls -ld /var/lib/libvirt/
ls -ld /var/lib/libvirt/qemu/

Also what distribution are you using?  I remember there were some differences in
packaging related to the directory permissions.

Martin


Dumpxml shows this btw:

 
   nobody:kvm
 

which at least is what was configured.
--
Regards,
Stephan


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


signature.asc
Description: PGP signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [RFC] New domain job control and stat APIs

2019-07-10 Thread Peter Krempa
Currently we don't have a consolidated approach for managing
asynchronous long-running domain jobs. Historically there were
long-running jobs which interlocked with each other and thus there was
only one such job possible at given time (migration, save, restore, dump)

These jobs have a not very flexible set of APIs:
virDomainGetJobInfo, virDomainGetJobStats, virDomainAbortJob.

These don't really allow selecting which job to terminate since there's
only one, thus if we wanted to add different kinds of jobs which not
necessarily interlock but are able to run in parallel we had to
introduce another set of APIs.

This resulted into creation of block job APIs:
virDomainBlockJobAbort, virDomainGetBlockJobInfo

These allow parallel jobs (discriminated by disk to which the job
belongs) but are not universal and nor allow parallel jobs on a single
disk.

Similarly blockjobs can also become detached from the disk e.g. if the
guest unplugs the disk fronted. That way the job would linger in a limbo
and would not be controllable. (This is certainly a possibility with
-blockdev).

With -blockdev we also get a potentially long-running blockdev-create
job which is not bound to any disk as part of kicking of a snapshot or
block copy job. This one might also get stuck and in the current state
is not really controllable.

Additionally the upcomming block-backup job will be a combination of the
above. It's a job which spans multiple disks (thus not really a block
job in libvirt terminology) but not a domain job either as there
can be potentially more than one block backup job. The proposal for
block-backup introduces it's own single-purpose set of APIs for managing
the backup job only, but abuses the block job and domain job events to
distribute the async state updates.

With this series I want to introduce a set of APIs for managing the jobs
which are designed to be universal enough and a new event so that noting
will try to retrofit onto existing infrastructure.

An example of the job XML would be:


  
vda
vda[1]
vda[5]
  
  
   12345
   12345
  


but this will be mostly a topic for the second part of this excercise
after we discuss the APIs.

The new infrastructure will also allow adding a flag for all the
existing APIs which kick-off a job so that the job will persist even
after it finishes. This will also properly implement the statistics for
a finished migration and similar.

Obviously we will need to take special care when wiring up these so that
the old APIs work for old situations and also the events are reported
correctly.

The initial idea would be to implement the stats XML both for the domain
jobs (migration, dump) and blockjobs to simplify the job for mgmt apps
so that they won't have to infer whether the given job type is already
reported in the new API.

Additionally we can also implement flags for the XML getter API that
will skip the stats gathering as that may require monitor interactions.
Also one possibility would be to return an abbreviated XML in the
listing API.
---
 include/libvirt/libvirt-domain.h | 91 +++
 src/libvirt-domain.c | 94 
 2 files changed, 185 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 2dbd74d4f3..dac1be 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4485,6 +4485,28 @@ typedef void 
(*virConnectDomainEventBlockThresholdCallback)(virConnectPtr conn,
 unsigned long long 
excess,
 void *opaque);

+/**
+ * virConnectDomainEventJobStateCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @jobname: name of job which changed state
+ * @jobtype: type of the job
+ * @newstate: the new state the job entered
+ * @opaque: application specified data
+ *
+ * The callback occurs when a long running domain job (see virDomainJobList)
+ * changes state.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_JOB_STATE with virConnectDomainEventRegisterAny()
+ */
+typedef void (*virConnectDomainEventJobStateCallback)(virConnectPtr conn,
+  virDomainPtr dom,
+  const char *jobname,
+  virDomainJobType jobtype,
+  virDomainJobState 
newstate,
+  void *opaque);
+
 /**
  * VIR_DOMAIN_EVENT_CALLBACK:
  *
@@ -4527,6 +4549,7 @@ typedef enum {
 VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* 
virConnectDomainEventDeviceRemovalFailedCallback */
 VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* 
virConnectDomainEventMetadataChangeCallback */
 

Re: [libvirt] [PATCH v2 1/9] vbox: Add various vir*Flags API

2019-07-10 Thread Eric Blake
On 7/10/19 2:09 AM, Peter Krempa wrote:
> On Tue, Jul 09, 2019 at 12:46:30 -0500, Eric Blake wrote:
>> Even though we don't accept any flags, it is unfriendly to callers
>> that use the modern API to have to fall back to the flag-free API.
>>
>> Signed-off-by: Eric Blake 
>> ---
>>  src/vbox/vbox_common.c | 24 ++--
>>  1 file changed, 22 insertions(+), 2 deletions(-)
> 
> [...]
> 
>> @@ -2775,6 +2788,11 @@ static int vboxDomainSetMemory(virDomainPtr dom, 
>> unsigned long memory)
>>  return ret;
>>  }
>>
>> +static int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory)
>> +{
>> +return vboxDomainSetMemoryFlags(dom, memory, 0);
> 
> The old API was operating on a live VM only so this shim should imply
> VIR_DOMAIN_AFFECT_LIVE.

Hmm. Commit 667ac11e used flag 0 for the test driver. But if I want to
reduce the number of driver callbacks by instead teaching the remote
driver when to call the legacy RPC, it's easier if ALL drivers shim-call
SetMemoryFlags(VIR_DOMAIN_AFFECT_LIVE) rather than some calling with 0
and others calling with AFFECT_LIVE.

The current list:
v5.5.0:src/hyperv/hyperv_driver.c:return
hypervDomainSetMemoryFlags(domain, memory, 0);
v5.5.0:src/libxl/libxl_driver.c:return
libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_LIVE);
v5.5.0:src/libxl/libxl_driver.c:return
libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
v5.5.0:src/lxc/lxc_driver.c:return lxcDomainSetMemoryFlags(dom,
newmem, VIR_DOMAIN_AFFECT_LIVE);
v5.5.0:src/lxc/lxc_driver.c:return lxcDomainSetMemoryFlags(dom,
newmax, VIR_DOMAIN_MEM_MAXIMUM);
v5.5.0:src/qemu/qemu_driver.c:return qemuDomainSetMemoryFlags(dom,
newmem, VIR_DOMAIN_AFFECT_LIVE);
v5.5.0:src/qemu/qemu_driver.c:return qemuDomainSetMemoryFlags(dom,
memory, VIR_DOMAIN_MEM_MAXIMUM);

my series adds:
test
vbox
xenapi

So it looks like hyperv has a bug in being inconsistent from everyone
else, if I follow your advice for the 3 new shims, although it currently
lacks a SetMaxMemory API at all.

You also appear to be right that making SetMaxMemory a shim everywhere
for SetMemoryFlags(VIR_DOMAIN_MEM_MAXMIUM) is a sensible idea, at least
for drivers that have a notion of setting max memory, but since not all
drivers had SetMaxMemory, it's harder to argue that the presence of the
new interface must require the legacy pair (especially if the new
interface blindly requires a specific flags pattern).  I'll have to look
more closely at what each driver is doing.

Our public docs currently state:

 * and will fail for transient domains. If neither flag is specified
 * (that is, @flags is VIR_DOMAIN_AFFECT_CURRENT), then an inactive domain
 * modifies persistent setup, while an active domain is hypervisor-dependent
 * on whether just live or both live and persistent state is changed.

which means that calling SetMemory() may be a synonym to either
SetMemoryFlags(_CURRENT==0) or to SetMemoryFlags(_LIVE).  But by
tweaking hyperv, we could change it so that the spec is more
tightly-worded as always being equivalent to SetMemoryFlags(_LIVE).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [jenkins-ci PATCH] guests: Always install the freshest point release

2019-07-10 Thread Andrea Bolognani
On Wed, 2019-07-10 at 09:42 +0200, Andrea Bolognani wrote:
> On Tue, 2019-07-09 at 18:48 +0200, Erik Skultety wrote:
> > On Tue, Jul 09, 2019 at 06:15:39PM +0200, Andrea Bolognani wrote:
> > > diff --git a/guests/host_vars/libvirt-debian-10/install.yml 
> > > b/guests/host_vars/libvirt-debian-10/install.yml
> > > index 0a30571..d6452b6 100644
> > > --- a/guests/host_vars/libvirt-debian-10/install.yml
> > > +++ b/guests/host_vars/libvirt-debian-10/install.yml
> > > @@ -1,2 +1,2 @@
> > >  ---
> > > -install_url: 
> > > http://deb.debian.org/debian/dists/buster/main/installer-amd64/
> > > +install_url: 
> > > http://deb.debian.org/debian/dists/buster-updates/main/installer-amd64/
> > > diff --git a/guests/host_vars/libvirt-debian-9/install.yml 
> > > b/guests/host_vars/libvirt-debian-9/install.yml
> > > index 7641753..a8c5d25 100644
> > > --- a/guests/host_vars/libvirt-debian-9/install.yml
> > > +++ b/guests/host_vars/libvirt-debian-9/install.yml
> > > @@ -1,2 +1,2 @@
> > >  ---
> > > -install_url: 
> > > http://deb.debian.org/debian/dists/stretch/main/installer-amd64/
> > > +install_url: 
> > > http://deb.debian.org/debian/dists/stretch-updates/main/installer-amd64/
> > 
> > These 2 URLs return 404 because /installer-amd64/ directory doesn't exist.
> 
> Good catch. Things might differ between Debian and Ubuntu on this
> front - I'll admit I only tested Ubuntu 16.04 before sending the
> patch. I'll look into it further and get back to you.

Yeah, so it looks like Ubuntu folks create updated versions of their
installer from time to time (each point release?), and make it
available under ${dist}-updates, whereas Debian folks either doen't
touch the installer after the initial release or substitute it in
place.

The takeaway is that these two hunks are incorrect, but we want the
remaining ones. Does that sound good to you?

-- 
Andrea Bolognani / Red Hat / Virtualization

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v2 1/9] vbox: Add various vir*Flags API

2019-07-10 Thread Eric Blake
On 7/10/19 2:02 AM, Peter Krempa wrote:
> On Tue, Jul 09, 2019 at 12:46:30 -0500, Eric Blake wrote:
>> Even though we don't accept any flags, it is unfriendly to callers
>> that use the modern API to have to fall back to the flag-free API.
>>
>> Signed-off-by: Eric Blake 
>> ---
>>  src/vbox/vbox_common.c | 24 ++--
>>  1 file changed, 22 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
>> index 54e31bec9d..44c98cadf6 100644
>> --- a/src/vbox/vbox_common.c
>> +++ b/src/vbox/vbox_common.c
>> @@ -553,7 +553,8 @@ static int vboxConnectClose(virConnectPtr conn)
>>  }
>>
>>  static int
>> -vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED)
>> +vboxDomainSaveFlags(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED,
>> +const char *dxml, unsigned int flags)
>>  {
>>  vboxDriverPtr data = dom->conn->privateData;
>>  IConsole *console = NULL;
>> @@ -564,6 +565,9 @@ vboxDomainSave(virDomainPtr dom, const char *path 
>> ATTRIBUTE_UNUSED)
>>  nsresult rc;
>>  int ret = -1;
>>
>> +virCheckFlags(0, -1);
>> +virCheckNonNullArgReturn(dxml, -1);
> 
> This reports: invalid argument: dxml in vboxDomainSave must not be NULL
> 
> I'm not certain that the internal function name makes sense to external
> users.

In which case I can hand-roll a more specific error instead of reusing
the common macro. But I do see pre-existing uses of
virCheckNonNullArgXXX in src/esx and src/vz prior to this patch, so it's
not the first time we've used the common macros.

> 
>> +
>>  if (!data->vboxObj)
>>  return ret;
>>
>> @@ -607,6 +611,12 @@ vboxDomainSave(virDomainPtr dom, const char *path 
>> ATTRIBUTE_UNUSED)
>>  return ret;
>>  }
>>
>> +static int
>> +vboxDomainSave(virDomainPtr dom, const char *path)
>> +{
>> +return vboxDomainSaveFlags(dom, path, NULL, 0);
> 
> So, this passes NULL 'dxml' into vboxDomainSaveFlags which explicitly
> rejects it. What's the point?
> 
> Ah I see. Was the above supposed to be virCheckNullArgGoto?

D'oh. Yes, I got it backwards.  The function wants to succeed only if
the user omitted the optional dxml argument.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 10/18] tpm: Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c

2019-07-10 Thread Stefan Berger

On 7/9/19 4:24 PM, Marc-André Lureau wrote:

On Tue, Jul 9, 2019 at 9:24 PM Stefan Berger  wrote:

Move qemuTPMEmulatorInit to virTPMEmulatorInit in virtpm.c and introduce
a few functions to query the executables needed for virCommands.

Signed-off-by: Stefan Berger 

Couldn't there be a TOCTOU issue?


It's not atomic and we cannot prevent modifications to the filesystem, 
if that's what you mean.





Anyway, for the move:
Reviewed-by: Marc-André Lureau 



Thanks.   Stefan


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

  1   2   >