<div dir="ltr">Hi<br><div><br><div class="gmail_quote"><div dir="ltr">On Fri, Feb 10, 2017 at 6:57 PM Michal Privoznik <<a href="mailto:mprivozn@redhat.com">mprivozn@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">So far, we are allowing /dev/vfio/vfio in the devices cgroup<br class="gmail_msg">
unconditionally (and creating it in the namespace too). Even if<br class="gmail_msg">
domain has no hostdev assignment configured. This is potential<br class="gmail_msg">
security hole. Therefore, when starting the domain (or<br class="gmail_msg">
hotplugging a hostdev) create & allow /dev/vfio/vfio too (if<br class="gmail_msg">
needed).<br class="gmail_msg">
<br class="gmail_msg">
Signed-off-by: Michal Privoznik <<a href="mailto:mprivozn@redhat.com" class="gmail_msg" target="_blank">mprivozn@redhat.com</a>><br class="gmail_msg"></blockquote><div><br></div><div>looks good to me,<br><br><br>Reviewed-by: Marc-André Lureau <<a href="mailto:marcandre.lureau@redhat.com">marcandre.lureau@redhat.com</a>><div style="color:rgb(0,0,0);font-family:sans;font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:21px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br class="inbox-inbox-Apple-interchange-newline"></div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br class="gmail_msg">
 src/qemu/qemu.conf                 |   2 +-<br class="gmail_msg">
 src/qemu/qemu_cgroup.c             |  53 ++++++++++++----<br class="gmail_msg">
 src/qemu/qemu_domain.c             | 124 ++++++++++++++++++++++++-------------<br class="gmail_msg">
 src/qemu/qemu_domain.h             |   5 +-<br class="gmail_msg">
 src/qemu/<a href="http://test_libvirtd_qemu.aug.in" rel="noreferrer" class="gmail_msg" target="_blank">test_libvirtd_qemu.aug.in</a> |   1 -<br class="gmail_msg">
 5 files changed, 125 insertions(+), 60 deletions(-)<br class="gmail_msg">
<br class="gmail_msg">
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf<br class="gmail_msg">
index 97d769d42..9f990c20d 100644<br class="gmail_msg">
--- a/src/qemu/qemu.conf<br class="gmail_msg">
+++ b/src/qemu/qemu.conf<br class="gmail_msg">
@@ -354,7 +354,7 @@<br class="gmail_msg">
 #    "/dev/null", "/dev/full", "/dev/zero",<br class="gmail_msg">
 #    "/dev/random", "/dev/urandom",<br class="gmail_msg">
 #    "/dev/ptmx", "/dev/kvm", "/dev/kqemu",<br class="gmail_msg">
-#    "/dev/rtc","/dev/hpet", "/dev/vfio/vfio"<br class="gmail_msg">
+#    "/dev/rtc","/dev/hpet"<br class="gmail_msg">
 #]<br class="gmail_msg">
 #<br class="gmail_msg">
 # RDMA migration requires the following extra files to be added to the list:<br class="gmail_msg">
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c<br class="gmail_msg">
index 19832c209..944e8dc87 100644<br class="gmail_msg">
--- a/src/qemu/qemu_cgroup.c<br class="gmail_msg">
+++ b/src/qemu/qemu_cgroup.c<br class="gmail_msg">
@@ -46,12 +46,13 @@ const char *const defaultDeviceACL[] = {<br class="gmail_msg">
     "/dev/null", "/dev/full", "/dev/zero",<br class="gmail_msg">
     "/dev/random", "/dev/urandom",<br class="gmail_msg">
     "/dev/ptmx", "/dev/kvm", "/dev/kqemu",<br class="gmail_msg">
-    "/dev/rtc", "/dev/hpet", "/dev/vfio/vfio",<br class="gmail_msg">
+    "/dev/rtc", "/dev/hpet",<br class="gmail_msg">
     NULL,<br class="gmail_msg">
 };<br class="gmail_msg">
 #define DEVICE_PTY_MAJOR 136<br class="gmail_msg">
 #define DEVICE_SND_MAJOR 116<br class="gmail_msg">
<br class="gmail_msg">
+#define DEV_VFIO "/dev/vfio/vfio"<br class="gmail_msg">
<br class="gmail_msg">
 static int<br class="gmail_msg">
 qemuSetupImagePathCgroup(virDomainObjPtr vm,<br class="gmail_msg">
@@ -265,26 +266,31 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm,<br class="gmail_msg">
                        virDomainHostdevDefPtr dev)<br class="gmail_msg">
 {<br class="gmail_msg">
     qemuDomainObjPrivatePtr priv = vm->privateData;<br class="gmail_msg">
-    char *path = NULL;<br class="gmail_msg">
-    int perms;<br class="gmail_msg">
-    int ret = -1;<br class="gmail_msg">
+    char **path = NULL;<br class="gmail_msg">
+    int *perms = NULL;<br class="gmail_msg">
+    size_t i, npaths = 0;<br class="gmail_msg">
+    int rv, ret = -1;<br class="gmail_msg">
<br class="gmail_msg">
-    if (qemuDomainGetHostdevPath(dev, &path, &perms) < 0)<br class="gmail_msg">
+    if (qemuDomainGetHostdevPath(dev, &npaths, &path, &perms) < 0)<br class="gmail_msg">
         goto cleanup;<br class="gmail_msg">
<br class="gmail_msg">
-    if (!path) {<br class="gmail_msg">
-        /* There's no path that we need to allow. Claim success. */<br class="gmail_msg">
-        ret = 0;<br class="gmail_msg">
-        goto cleanup;<br class="gmail_msg">
+    for (i = 0; i < npaths; i++) {<br class="gmail_msg">
+        VIR_DEBUG("Cgroup allow %s perms=%d", path[i], perms[i]);<br class="gmail_msg">
+        rv = virCgroupAllowDevicePath(priv->cgroup, path[i], perms[i], false);<br class="gmail_msg">
+        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path[i],<br class="gmail_msg">
+                                 virCgroupGetDevicePermsString(perms[i]),<br class="gmail_msg">
+                                 ret == 0);<br class="gmail_msg">
+        if (rv < 0)<br class="gmail_msg">
+            goto cleanup;<br class="gmail_msg">
     }<br class="gmail_msg">
<br class="gmail_msg">
-    VIR_DEBUG("Cgroup allow %s perms=%d", path, perms);<br class="gmail_msg">
-    ret = virCgroupAllowDevicePath(priv->cgroup, path, perms, false);<br class="gmail_msg">
-    virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path,<br class="gmail_msg">
-                             virCgroupGetDevicePermsString(perms), ret == 0);<br class="gmail_msg">
+    ret = 0;<br class="gmail_msg">
<br class="gmail_msg">
  cleanup:<br class="gmail_msg">
+    for (i = 0; i < npaths; i++)<br class="gmail_msg">
+        VIR_FREE(path[i]);<br class="gmail_msg">
     VIR_FREE(path);<br class="gmail_msg">
+    VIR_FREE(perms);<br class="gmail_msg">
     return ret;<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
@@ -312,6 +318,7 @@ qemuTeardownHostdevCgroup(virDomainObjPtr vm,<br class="gmail_msg">
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:<br class="gmail_msg">
             if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {<br class="gmail_msg">
                 int rv;<br class="gmail_msg">
+                size_t i, vfios = 0;<br class="gmail_msg">
<br class="gmail_msg">
                 pci = virPCIDeviceNew(pcisrc->addr.domain,<br class="gmail_msg">
                                       pcisrc->addr.bus,<br class="gmail_msg">
@@ -330,6 +337,26 @@ qemuTeardownHostdevCgroup(virDomainObjPtr vm,<br class="gmail_msg">
                                          "deny", path, "rwm", rv == 0);<br class="gmail_msg">
                 if (rv < 0)<br class="gmail_msg">
                     goto cleanup;<br class="gmail_msg">
+<br class="gmail_msg">
+                /* If this is the last hostdev with VFIO backend deny<br class="gmail_msg">
+                 * /dev/vfio/vfio too. */<br class="gmail_msg">
+                for (i = 0; i < vm->def->nhostdevs; i++) {<br class="gmail_msg">
+                    virDomainHostdevDefPtr tmp = vm->def->hostdevs[i];<br class="gmail_msg">
+                    if (tmp->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&<br class="gmail_msg">
+                        tmp->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&<br class="gmail_msg">
+                        tmp->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO)<br class="gmail_msg">
+                        vfios++;<br class="gmail_msg">
+                }<br class="gmail_msg">
+<br class="gmail_msg">
+                if (vfios == 0) {<br class="gmail_msg">
+                    VIR_DEBUG("Cgroup deny " DEV_VFIO " for PCI device assignment");<br class="gmail_msg">
+                    rv = virCgroupDenyDevicePath(priv->cgroup, DEV_VFIO,<br class="gmail_msg">
+                                                 VIR_CGROUP_DEVICE_RWM, false);<br class="gmail_msg">
+                    virDomainAuditCgroupPath(vm, priv->cgroup,<br class="gmail_msg">
+                                             "deny", DEV_VFIO, "rwm", rv == 0);<br class="gmail_msg">
+                    if (rv < 0)<br class="gmail_msg">
+                        goto cleanup;<br class="gmail_msg">
+                }<br class="gmail_msg">
             }<br class="gmail_msg">
             break;<br class="gmail_msg">
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:<br class="gmail_msg">
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c<br class="gmail_msg">
index c6d32525f..530eced33 100644<br class="gmail_msg">
--- a/src/qemu/qemu_domain.c<br class="gmail_msg">
+++ b/src/qemu/qemu_domain.c<br class="gmail_msg">
@@ -107,6 +107,7 @@ VIR_ENUM_IMPL(qemuDomainNamespace, QEMU_DOMAIN_NS_LAST,<br class="gmail_msg">
<br class="gmail_msg">
 #define PROC_MOUNTS "/proc/mounts"<br class="gmail_msg">
 #define DEVPREFIX "/dev/"<br class="gmail_msg">
+#define DEV_VFIO "/dev/vfio/vfio"<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
 struct _qemuDomainLogContext {<br class="gmail_msg">
@@ -6834,18 +6835,24 @@ qemuDomainSupportsVideoVga(virDomainVideoDefPtr video,<br class="gmail_msg">
 /**<br class="gmail_msg">
  * qemuDomainGetHostdevPath:<br class="gmail_msg">
  * @dev: host device definition<br class="gmail_msg">
+ * @npaths: number of items in @path and @perms arrays<br class="gmail_msg">
  * @path: resulting path to @dev<br class="gmail_msg">
  * @perms: Optional pointer to VIR_CGROUP_DEVICE_* perms<br class="gmail_msg">
  *<br class="gmail_msg">
- * For given device @dev fetch its host path and store it at @path. Optionally,<br class="gmail_msg">
- * caller can get @perms on the path (e.g. rw/ro).<br class="gmail_msg">
+ * For given device @dev fetch its host path and store it at<br class="gmail_msg">
+ * @path. If a device requires other paths to be present/allowed<br class="gmail_msg">
+ * they are stored in the @path array after the actual path.<br class="gmail_msg">
+ * Optionally, caller can get @perms on the path (e.g. rw/ro).<br class="gmail_msg">
+ *<br class="gmail_msg">
+ * The caller is responsible for freeing the memory.<br class="gmail_msg">
  *<br class="gmail_msg">
  * Returns 0 on success, -1 otherwise.<br class="gmail_msg">
  */<br class="gmail_msg">
 int<br class="gmail_msg">
 qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
-                         char **path,<br class="gmail_msg">
-                         int *perms)<br class="gmail_msg">
+                         size_t *npaths,<br class="gmail_msg">
+                         char ***path,<br class="gmail_msg">
+                         int **perms)<br class="gmail_msg">
 {<br class="gmail_msg">
     int ret = -1;<br class="gmail_msg">
     virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;<br class="gmail_msg">
@@ -6858,8 +6865,13 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
     virSCSIVHostDevicePtr host = NULL;<br class="gmail_msg">
     char *tmpPath = NULL;<br class="gmail_msg">
     bool freeTmpPath = false;<br class="gmail_msg">
+    bool includeVFIO = false;<br class="gmail_msg">
+    char **tmpPaths = NULL;<br class="gmail_msg">
+    int *tmpPerms = NULL;<br class="gmail_msg">
+    size_t i, tmpNpaths = 0;<br class="gmail_msg">
+    int perm = 0;<br class="gmail_msg">
<br class="gmail_msg">
-    *path = NULL;<br class="gmail_msg">
+    *npaths = 0;<br class="gmail_msg">
<br class="gmail_msg">
     switch ((virDomainHostdevMode) dev->mode) {<br class="gmail_msg">
     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:<br class="gmail_msg">
@@ -6876,8 +6888,9 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
                 if (!(tmpPath = virPCIDeviceGetIOMMUGroupDev(pci)))<br class="gmail_msg">
                     goto cleanup;<br class="gmail_msg">
                 freeTmpPath = true;<br class="gmail_msg">
-                if (perms)<br class="gmail_msg">
-                    *perms = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
+<br class="gmail_msg">
+                perm = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
+                includeVFIO = true;<br class="gmail_msg">
             }<br class="gmail_msg">
             break;<br class="gmail_msg">
<br class="gmail_msg">
@@ -6892,8 +6905,7 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
<br class="gmail_msg">
             if (!(tmpPath = (char *) virUSBDeviceGetPath(usb)))<br class="gmail_msg">
                 goto cleanup;<br class="gmail_msg">
-            if (perms)<br class="gmail_msg">
-                *perms = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
+            perm = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
             break;<br class="gmail_msg">
<br class="gmail_msg">
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:<br class="gmail_msg">
@@ -6918,9 +6930,8 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
<br class="gmail_msg">
                 if (!(tmpPath = (char *) virSCSIDeviceGetPath(scsi)))<br class="gmail_msg">
                     goto cleanup;<br class="gmail_msg">
-                if (perms)<br class="gmail_msg">
-                    *perms = virSCSIDeviceGetReadonly(scsi) ?<br class="gmail_msg">
-                        VIR_CGROUP_DEVICE_READ :VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
+                perm = virSCSIDeviceGetReadonly(scsi) ?<br class="gmail_msg">
+                    VIR_CGROUP_DEVICE_READ :VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
             }<br class="gmail_msg">
             break;<br class="gmail_msg">
<br class="gmail_msg">
@@ -6932,8 +6943,7 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
<br class="gmail_msg">
                 if (!(tmpPath = (char *) virSCSIVHostDeviceGetPath(host)))<br class="gmail_msg">
                     goto cleanup;<br class="gmail_msg">
-                if (perms)<br class="gmail_msg">
-                    *perms = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
+                perm = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
             }<br class="gmail_msg">
             break;<br class="gmail_msg">
         }<br class="gmail_msg">
@@ -6949,11 +6959,40 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
         break;<br class="gmail_msg">
     }<br class="gmail_msg">
<br class="gmail_msg">
-    if (VIR_STRDUP(*path, tmpPath) < 0)<br class="gmail_msg">
-        goto cleanup;<br class="gmail_msg">
+    if (tmpPath) {<br class="gmail_msg">
+        size_t toAlloc = 1;<br class="gmail_msg">
<br class="gmail_msg">
+        if (includeVFIO)<br class="gmail_msg">
+            toAlloc = 2;<br class="gmail_msg">
+<br class="gmail_msg">
+        if (VIR_ALLOC_N(tmpPaths, toAlloc) < 0 ||<br class="gmail_msg">
+            VIR_ALLOC_N(tmpPerms, toAlloc) < 0 ||<br class="gmail_msg">
+            VIR_STRDUP(tmpPaths[0], tmpPath) < 0)<br class="gmail_msg">
+            goto cleanup;<br class="gmail_msg">
+        tmpNpaths = toAlloc;<br class="gmail_msg">
+        tmpPerms[0] = perm;<br class="gmail_msg">
+<br class="gmail_msg">
+        if (includeVFIO) {<br class="gmail_msg">
+            if (VIR_STRDUP(tmpPaths[1], DEV_VFIO) < 0)<br class="gmail_msg">
+                goto cleanup;<br class="gmail_msg">
+            tmpPerms[1] = VIR_CGROUP_DEVICE_RW;<br class="gmail_msg">
+        }<br class="gmail_msg">
+    }<br class="gmail_msg">
+<br class="gmail_msg">
+    *npaths = tmpNpaths;<br class="gmail_msg">
+    tmpNpaths = 0;<br class="gmail_msg">
+    *path = tmpPaths;<br class="gmail_msg">
+    tmpPaths = NULL;<br class="gmail_msg">
+    if (perms) {<br class="gmail_msg">
+        *perms = tmpPerms;<br class="gmail_msg">
+        tmpPerms = NULL;<br class="gmail_msg">
+    }<br class="gmail_msg">
     ret = 0;<br class="gmail_msg">
  cleanup:<br class="gmail_msg">
+    for (i = 0; i < tmpNpaths; i++)<br class="gmail_msg">
+        VIR_FREE(tmpPaths[i]);<br class="gmail_msg">
+    VIR_FREE(tmpPaths);<br class="gmail_msg">
+    VIR_FREE(tmpPerms);<br class="gmail_msg">
     virPCIDeviceFree(pci);<br class="gmail_msg">
     virUSBDeviceFree(usb);<br class="gmail_msg">
     virSCSIDeviceFree(scsi);<br class="gmail_msg">
@@ -7347,22 +7386,21 @@ qemuDomainSetupHostdev(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,<br class="gmail_msg">
                        const char *devPath)<br class="gmail_msg">
 {<br class="gmail_msg">
     int ret = -1;<br class="gmail_msg">
-    char *path = NULL;<br class="gmail_msg">
+    char **path = NULL;<br class="gmail_msg">
+    size_t i, npaths = 0;<br class="gmail_msg">
<br class="gmail_msg">
-    if (qemuDomainGetHostdevPath(dev, &path, NULL) < 0)<br class="gmail_msg">
+    if (qemuDomainGetHostdevPath(dev, &npaths, &path, NULL) < 0)<br class="gmail_msg">
         goto cleanup;<br class="gmail_msg">
<br class="gmail_msg">
-    if (!path) {<br class="gmail_msg">
-        /* There's no /dev device that we need to create. Claim success. */<br class="gmail_msg">
-        ret = 0;<br class="gmail_msg">
-        goto cleanup;<br class="gmail_msg">
+    for (i = 0; i < npaths; i++) {<br class="gmail_msg">
+        if (qemuDomainCreateDevice(path[i], devPath, false) < 0)<br class="gmail_msg">
+            goto cleanup;<br class="gmail_msg">
     }<br class="gmail_msg">
<br class="gmail_msg">
-    if (qemuDomainCreateDevice(path, devPath, false) < 0)<br class="gmail_msg">
-        goto cleanup;<br class="gmail_msg">
-<br class="gmail_msg">
     ret = 0;<br class="gmail_msg">
  cleanup:<br class="gmail_msg">
+    for (i = 0; i < npaths; i++)<br class="gmail_msg">
+        VIR_FREE(path[i]);<br class="gmail_msg">
     VIR_FREE(path);<br class="gmail_msg">
     return ret;<br class="gmail_msg">
 }<br class="gmail_msg">
@@ -7980,26 +8018,26 @@ qemuDomainNamespaceSetupHostdev(virQEMUDriverPtr driver,<br class="gmail_msg">
                                 virDomainHostdevDefPtr hostdev)<br class="gmail_msg">
 {<br class="gmail_msg">
     int ret = -1;<br class="gmail_msg">
-    char *path = NULL;<br class="gmail_msg">
+    char **path = NULL;<br class="gmail_msg">
+    size_t i, npaths = 0;<br class="gmail_msg">
<br class="gmail_msg">
     if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))<br class="gmail_msg">
         return 0;<br class="gmail_msg">
<br class="gmail_msg">
-    if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)<br class="gmail_msg">
+    if (qemuDomainGetHostdevPath(hostdev, &npaths, &path, NULL) < 0)<br class="gmail_msg">
         goto cleanup;<br class="gmail_msg">
<br class="gmail_msg">
-    if (!path) {<br class="gmail_msg">
-        /* There's no /dev device that we need to create. Claim success. */<br class="gmail_msg">
-        ret = 0;<br class="gmail_msg">
+    for (i = 0; i < npaths; i++) {<br class="gmail_msg">
+        if (qemuDomainAttachDeviceMknod(driver,<br class="gmail_msg">
+                                        vm,<br class="gmail_msg">
+                                        path[i]) < 0)<br class="gmail_msg">
         goto cleanup;<br class="gmail_msg">
     }<br class="gmail_msg">
<br class="gmail_msg">
-    if (qemuDomainAttachDeviceMknod(driver,<br class="gmail_msg">
-                                    vm,<br class="gmail_msg">
-                                    path) < 0)<br class="gmail_msg">
-        goto cleanup;<br class="gmail_msg">
     ret = 0;<br class="gmail_msg">
  cleanup:<br class="gmail_msg">
+    for (i = 0; i < npaths; i++)<br class="gmail_msg">
+        VIR_FREE(path[i]);<br class="gmail_msg">
     VIR_FREE(path);<br class="gmail_msg">
     return ret;<br class="gmail_msg">
 }<br class="gmail_msg">
@@ -8011,25 +8049,25 @@ qemuDomainNamespaceTeardownHostdev(virQEMUDriverPtr driver,<br class="gmail_msg">
                                    virDomainHostdevDefPtr hostdev)<br class="gmail_msg">
 {<br class="gmail_msg">
     int ret = -1;<br class="gmail_msg">
-    char *path = NULL;<br class="gmail_msg">
+    char **path = NULL;<br class="gmail_msg">
+    size_t i, npaths = 0;<br class="gmail_msg">
<br class="gmail_msg">
     if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))<br class="gmail_msg">
         return 0;<br class="gmail_msg">
<br class="gmail_msg">
-    if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)<br class="gmail_msg">
+    if (qemuDomainGetHostdevPath(hostdev, &npaths, &path, NULL) < 0)<br class="gmail_msg">
         goto cleanup;<br class="gmail_msg">
<br class="gmail_msg">
-    if (!path) {<br class="gmail_msg">
-        /* There's no /dev device that we need to create. Claim success. */<br class="gmail_msg">
-        ret = 0;<br class="gmail_msg">
-        goto cleanup;<br class="gmail_msg">
-    }<br class="gmail_msg">
-<br class="gmail_msg">
-    if (qemuDomainDetachDeviceUnlink(driver, vm, path) < 0)<br class="gmail_msg">
+    /* Don't remove other paths than for the @hostdev itself.<br class="gmail_msg">
+     * They might be still in use by other devices. */<br class="gmail_msg">
+    if (npaths > 0 &&<br class="gmail_msg">
+        qemuDomainDetachDeviceUnlink(driver, vm, path[0]) < 0)<br class="gmail_msg">
         goto cleanup;<br class="gmail_msg">
<br class="gmail_msg">
     ret = 0;<br class="gmail_msg">
  cleanup:<br class="gmail_msg">
+    for (i = 0; i < npaths; i++)<br class="gmail_msg">
+        VIR_FREE(path[i]);<br class="gmail_msg">
     VIR_FREE(path);<br class="gmail_msg">
     return ret;<br class="gmail_msg">
 }<br class="gmail_msg">
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h<br class="gmail_msg">
index f81550e2f..e64aa25ba 100644<br class="gmail_msg">
--- a/src/qemu/qemu_domain.h<br class="gmail_msg">
+++ b/src/qemu/qemu_domain.h<br class="gmail_msg">
@@ -803,8 +803,9 @@ bool qemuDomainSupportsVideoVga(virDomainVideoDefPtr video,<br class="gmail_msg">
                                 virQEMUCapsPtr qemuCaps);<br class="gmail_msg">
<br class="gmail_msg">
 int qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,<br class="gmail_msg">
-                             char **path,<br class="gmail_msg">
-                             int *perms);<br class="gmail_msg">
+                             size_t *npaths,<br class="gmail_msg">
+                             char ***path,<br class="gmail_msg">
+                             int **perms);<br class="gmail_msg">
<br class="gmail_msg">
 int qemuDomainBuildNamespace(virQEMUDriverPtr driver,<br class="gmail_msg">
                              virDomainObjPtr vm);<br class="gmail_msg">
diff --git a/src/qemu/<a href="http://test_libvirtd_qemu.aug.in" rel="noreferrer" class="gmail_msg" target="_blank">test_libvirtd_qemu.aug.in</a> b/src/qemu/<a href="http://test_libvirtd_qemu.aug.in" rel="noreferrer" class="gmail_msg" target="_blank">test_libvirtd_qemu.aug.in</a><br class="gmail_msg">
index bd25235d3..6f03898c0 100644<br class="gmail_msg">
--- a/src/qemu/<a href="http://test_libvirtd_qemu.aug.in" rel="noreferrer" class="gmail_msg" target="_blank">test_libvirtd_qemu.aug.in</a><br class="gmail_msg">
+++ b/src/qemu/<a href="http://test_libvirtd_qemu.aug.in" rel="noreferrer" class="gmail_msg" target="_blank">test_libvirtd_qemu.aug.in</a><br class="gmail_msg">
@@ -55,7 +55,6 @@ module Test_libvirtd_qemu =<br class="gmail_msg">
     { "8" = "/dev/kqemu" }<br class="gmail_msg">
     { "9" = "/dev/rtc" }<br class="gmail_msg">
     { "10" = "/dev/hpet" }<br class="gmail_msg">
-    { "11" = "/dev/vfio/vfio" }<br class="gmail_msg">
 }<br class="gmail_msg">
 { "save_image_format" = "raw" }<br class="gmail_msg">
 { "dump_image_format" = "raw" }<br class="gmail_msg">
--<br class="gmail_msg">
2.11.0<br class="gmail_msg">
<br class="gmail_msg">
--<br class="gmail_msg">
libvir-list mailing list<br class="gmail_msg">
<a href="mailto:libvir-list@redhat.com" class="gmail_msg" target="_blank">libvir-list@redhat.com</a><br class="gmail_msg">
<a href="https://www.redhat.com/mailman/listinfo/libvir-list" rel="noreferrer" class="gmail_msg" target="_blank">https://www.redhat.com/mailman/listinfo/libvir-list</a><br class="gmail_msg">
</blockquote></div></div></div><div dir="ltr">-- <br></div><div data-smartmail="gmail_signature"><div dir="ltr">Marc-André Lureau<br></div></div>