[PATCH v2 4/5] qemu: Update Cgroup, namespace, and seclabel for iommufd

Nathan Chen via Devel posted 5 patches 2 weeks, 6 days ago
[PATCH v2 4/5] qemu: Update Cgroup, namespace, and seclabel for iommufd
Posted by Nathan Chen via Devel 2 weeks, 6 days ago
When launching a qemu VM with the iommufd feature enabled for VFIO
hostdevs:
- Do not allow access to /dev/vfio/vfio and /dev/vfio/<iommugroup>
used by VFIO without iommufd enabled
- Allow access to /dev/iommu and /dev/vfio/devices/vfio*

Signed-off-by: Nathan Chen <nathanc@nvidia.com>
---
 src/qemu/qemu_cgroup.c           | 26 ++++++++++++++------------
 src/qemu/qemu_namespace.c        | 16 +++++++++-------
 src/security/security_apparmor.c | 18 +++++++++++-------
 src/security/security_dac.c      | 28 ++++++++++++++++++----------
 src/security/security_selinux.c  | 28 ++++++++++++++++++----------
 src/security/virt-aa-helper.c    | 11 +++++++++--
 6 files changed, 79 insertions(+), 48 deletions(-)

diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 46a7dc1d8b..b3610b31ca 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -479,21 +479,23 @@ qemuSetupHostdevCgroup(virDomainObj *vm,
     g_autofree char *path = NULL;
     int perms;
 
-    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
-        return 0;
+    if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
+            return 0;
 
-    if (qemuDomainGetHostdevPath(dev, &path, &perms) < 0)
-        return -1;
+        if (qemuDomainGetHostdevPath(dev, &path, &perms) < 0)
+            return -1;
 
-    if (path &&
-        qemuCgroupAllowDevicePath(vm, path, perms, false) < 0) {
-        return -1;
-    }
+        if (path &&
+            qemuCgroupAllowDevicePath(vm, path, perms, false) < 0) {
+            return -1;
+        }
 
-    if (virHostdevNeedsVFIO(dev) &&
-        qemuCgroupAllowDevicePath(vm, QEMU_DEV_VFIO,
-                                  VIR_CGROUP_DEVICE_RW, false) < 0) {
-        return -1;
+        if (virHostdevNeedsVFIO(dev) &&
+            qemuCgroupAllowDevicePath(vm, QEMU_DEV_VFIO,
+                                      VIR_CGROUP_DEVICE_RW, false) < 0) {
+            return -1;
+        }
     }
 
     return 0;
diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
index 932777505b..489b13261b 100644
--- a/src/qemu/qemu_namespace.c
+++ b/src/qemu/qemu_namespace.c
@@ -343,15 +343,17 @@ qemuDomainSetupHostdev(virDomainObj *vm,
 {
     g_autofree char *path = NULL;
 
-    if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
-        return -1;
+    if (hostdev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+        if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
+            return -1;
 
-    if (path)
-        *paths = g_slist_prepend(*paths, g_steal_pointer(&path));
+        if (path)
+            *paths = g_slist_prepend(*paths, g_steal_pointer(&path));
 
-    if (virHostdevNeedsVFIO(hostdev) &&
-        (!hotplug || !qemuDomainNeedsVFIO(vm->def)))
-        *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_VFIO));
+        if (virHostdevNeedsVFIO(hostdev) &&
+            (!hotplug || !qemuDomainNeedsVFIO(vm->def)))
+            *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_VFIO));
+    }
 
     return 0;
 }
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index 68ac39611f..d66f035e52 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -848,14 +848,18 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr,
             goto done;
 
         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
-            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
-
-            if (!vfioGroupDev) {
-                virPCIDeviceFree(pci);
-                goto done;
+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+                char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+
+                if (!vfioGroupDev) {
+                    virPCIDeviceFree(pci);
+                    goto done;
+                }
+                ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
+                VIR_FREE(vfioGroupDev);
+            } else {
+                ret = 0;
             }
-            ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
-            VIR_FREE(vfioGroupDev);
         } else {
             ret = virPCIDeviceFileIterate(pci, AppArmorSetSecurityPCILabel, ptr);
         }
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 2f788b872a..93a9268389 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1282,14 +1282,18 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr,
             return -1;
 
         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
 
-            if (!vfioGroupDev)
-                return -1;
+                if (!vfioGroupDev)
+                    return -1;
 
-            ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
-                                                      false,
-                                                      &cbdata);
+                ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
+                                                          false,
+                                                          &cbdata);
+            } else {
+                ret = 0;
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci,
                                           virSecurityDACSetPCILabel,
@@ -1443,13 +1447,17 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr,
             return -1;
 
         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
 
-            if (!vfioGroupDev)
-                return -1;
+                if (!vfioGroupDev)
+                    return -1;
 
-            ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
+                ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
                                                          vfioGroupDev, false);
+            } else {
+                ret = 0;
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci, virSecurityDACRestorePCILabel, mgr);
         }
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 2f3cc274a5..af6b938641 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2256,14 +2256,18 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr,
             return -1;
 
         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
 
-            if (!vfioGroupDev)
-                return -1;
+                if (!vfioGroupDev)
+                    return -1;
 
-            ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
-                                                          false,
-                                                          &data);
+                ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
+                                                              false,
+                                                              &data);
+            } else {
+                ret = 0;
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCILabel, &data);
         }
@@ -2491,12 +2495,16 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr,
             return -1;
 
         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
 
-            if (!vfioGroupDev)
-                return -1;
+                if (!vfioGroupDev)
+                    return -1;
 
-            ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
+                ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
+            } else {
+                ret = 0;
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxRestorePCILabel, mgr);
         }
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index de0a826063..ea05f2c5f7 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -878,7 +878,7 @@ get_files(vahControl * ctl)
     size_t i;
     g_autofree char *uuid = NULL;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
-    bool needsVfio = false, needsvhost = false, needsgl = false;
+    bool needsVfio = false, needsvhost = false, needsgl = false, needsIommufd = false;
 
     /* verify uuid is same as what we were given on the command line */
     virUUIDFormat(ctl->def->uuid, uuidstr);
@@ -1119,6 +1119,9 @@ get_files(vahControl * ctl)
                 needsVfio = true;
             }
 
+            if (dev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES)
+                needsIommufd = true;
+
             if (pci == NULL)
                 continue;
 
@@ -1344,10 +1347,14 @@ get_files(vahControl * ctl)
     if (needsvhost)
         virBufferAddLit(&buf, "  \"/dev/vhost-net\" rw,\n");
 
-    if (needsVfio) {
+    if (needsIommufd) {
+        virBufferAddLit(&buf, "  \"/dev/iommu\" rwm,\n");
+        virBufferAddLit(&buf, "  \"/dev/vfio/devices/vfio[0-9]*\" rwm,\n");
+    } else if (needsVfio) {
         virBufferAddLit(&buf, "  \"/dev/vfio/vfio\" rw,\n");
         virBufferAddLit(&buf, "  \"/dev/vfio/[0-9]*\" rw,\n");
     }
+
     if (needsgl) {
         /* if using gl all sorts of further dri related paths will be needed */
         virBufferAddLit(&buf, "  # DRI/Mesa/(e)GL config and driver paths\n");
-- 
2.43.0
Re: [PATCH v2 4/5] qemu: Update Cgroup, namespace, and seclabel for iommufd
Posted by Ján Tomko via Devel 3 days, 18 hours ago
On a Friday in 2025, Nathan Chen via Devel wrote:
>When launching a qemu VM with the iommufd feature enabled for VFIO
>hostdevs:
>- Do not allow access to /dev/vfio/vfio and /dev/vfio/<iommugroup>
>used by VFIO without iommufd enabled
>- Allow access to /dev/iommu and /dev/vfio/devices/vfio*
>

The commit summary mentions cgroups, namespaces and seclabels,
however I can only see this patch not allowing stuff needed for legacy
VFIO, but I don't see it allowing the new paths.

I see you add the paths to apparmor - presumably you're using
a Debian-based distro that doesn't have SELinux.

But are cgroups not used either?

Possibly namespaces aren't necessary if we're passing the FDs and I'll
look into the SELinux stuff.

Jano

>Signed-off-by: Nathan Chen <nathanc@nvidia.com>
>---
> src/qemu/qemu_cgroup.c           | 26 ++++++++++++++------------
> src/qemu/qemu_namespace.c        | 16 +++++++++-------
> src/security/security_apparmor.c | 18 +++++++++++-------
> src/security/security_dac.c      | 28 ++++++++++++++++++----------
> src/security/security_selinux.c  | 28 ++++++++++++++++++----------
> src/security/virt-aa-helper.c    | 11 +++++++++--
> 6 files changed, 79 insertions(+), 48 deletions(-)
>
>diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
>index 46a7dc1d8b..b3610b31ca 100644
>--- a/src/qemu/qemu_cgroup.c
>+++ b/src/qemu/qemu_cgroup.c
>@@ -479,21 +479,23 @@ qemuSetupHostdevCgroup(virDomainObj *vm,
>     g_autofree char *path = NULL;
>     int perms;
>
>-    if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
>-        return 0;
>+    if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+        if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
>+            return 0;
>
>-    if (qemuDomainGetHostdevPath(dev, &path, &perms) < 0)
>-        return -1;
>+        if (qemuDomainGetHostdevPath(dev, &path, &perms) < 0)
>+            return -1;
>
>-    if (path &&
>-        qemuCgroupAllowDevicePath(vm, path, perms, false) < 0) {
>-        return -1;
>-    }
>+        if (path &&
>+            qemuCgroupAllowDevicePath(vm, path, perms, false) < 0) {
>+            return -1;
>+        }
>
>-    if (virHostdevNeedsVFIO(dev) &&
>-        qemuCgroupAllowDevicePath(vm, QEMU_DEV_VFIO,
>-                                  VIR_CGROUP_DEVICE_RW, false) < 0) {
>-        return -1;
>+        if (virHostdevNeedsVFIO(dev) &&
>+            qemuCgroupAllowDevicePath(vm, QEMU_DEV_VFIO,
>+                                      VIR_CGROUP_DEVICE_RW, false) < 0) {
>+            return -1;
>+        }
>     }
>
>     return 0;
>diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
>index 932777505b..489b13261b 100644
>--- a/src/qemu/qemu_namespace.c
>+++ b/src/qemu/qemu_namespace.c
>@@ -343,15 +343,17 @@ qemuDomainSetupHostdev(virDomainObj *vm,
> {
>     g_autofree char *path = NULL;
>
>-    if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
>-        return -1;
>+    if (hostdev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+        if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
>+            return -1;
>
>-    if (path)
>-        *paths = g_slist_prepend(*paths, g_steal_pointer(&path));
>+        if (path)
>+            *paths = g_slist_prepend(*paths, g_steal_pointer(&path));
>
>-    if (virHostdevNeedsVFIO(hostdev) &&
>-        (!hotplug || !qemuDomainNeedsVFIO(vm->def)))
>-        *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_VFIO));
>+        if (virHostdevNeedsVFIO(hostdev) &&
>+            (!hotplug || !qemuDomainNeedsVFIO(vm->def)))
>+            *paths = g_slist_prepend(*paths, g_strdup(QEMU_DEV_VFIO));
>+    }
>
>     return 0;
> }
>diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
>index 68ac39611f..d66f035e52 100644
>--- a/src/security/security_apparmor.c
>+++ b/src/security/security_apparmor.c
>@@ -848,14 +848,18 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr,
>             goto done;
>
>         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
>-            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>-
>-            if (!vfioGroupDev) {
>-                virPCIDeviceFree(pci);
>-                goto done;
>+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+                char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>+
>+                if (!vfioGroupDev) {
>+                    virPCIDeviceFree(pci);
>+                    goto done;
>+                }
>+                ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
>+                VIR_FREE(vfioGroupDev);
>+            } else {
>+                ret = 0;
>             }
>-            ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
>-            VIR_FREE(vfioGroupDev);
>         } else {
>             ret = virPCIDeviceFileIterate(pci, AppArmorSetSecurityPCILabel, ptr);
>         }
>diff --git a/src/security/security_dac.c b/src/security/security_dac.c
>index 2f788b872a..93a9268389 100644
>--- a/src/security/security_dac.c
>+++ b/src/security/security_dac.c
>@@ -1282,14 +1282,18 @@ virSecurityDACSetHostdevLabel(virSecurityManager *mgr,
>             return -1;
>
>         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
>-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>
>-            if (!vfioGroupDev)
>-                return -1;
>+                if (!vfioGroupDev)
>+                    return -1;
>
>-            ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
>-                                                      false,
>-                                                      &cbdata);
>+                ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
>+                                                          false,
>+                                                          &cbdata);
>+            } else {
>+                ret = 0;
>+            }
>         } else {
>             ret = virPCIDeviceFileIterate(pci,
>                                           virSecurityDACSetPCILabel,
>@@ -1443,13 +1447,17 @@ virSecurityDACRestoreHostdevLabel(virSecurityManager *mgr,
>             return -1;
>
>         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
>-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>
>-            if (!vfioGroupDev)
>-                return -1;
>+                if (!vfioGroupDev)
>+                    return -1;
>
>-            ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
>+                ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
>                                                          vfioGroupDev, false);
>+            } else {
>+                ret = 0;
>+            }
>         } else {
>             ret = virPCIDeviceFileIterate(pci, virSecurityDACRestorePCILabel, mgr);
>         }
>diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
>index 2f3cc274a5..af6b938641 100644
>--- a/src/security/security_selinux.c
>+++ b/src/security/security_selinux.c
>@@ -2256,14 +2256,18 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr,
>             return -1;
>
>         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
>-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>
>-            if (!vfioGroupDev)
>-                return -1;
>+                if (!vfioGroupDev)
>+                    return -1;
>
>-            ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
>-                                                          false,
>-                                                          &data);
>+                ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
>+                                                              false,
>+                                                              &data);
>+            } else {
>+                ret = 0;
>+            }
>         } else {
>             ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCILabel, &data);
>         }
>@@ -2491,12 +2495,16 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr,
>             return -1;
>
>         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
>-            g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
>+                g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
>
>-            if (!vfioGroupDev)
>-                return -1;
>+                if (!vfioGroupDev)
>+                    return -1;
>
>-            ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
>+                ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
>+            } else {
>+                ret = 0;
>+            }
>         } else {
>             ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxRestorePCILabel, mgr);
>         }
>diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
>index de0a826063..ea05f2c5f7 100644
>--- a/src/security/virt-aa-helper.c
>+++ b/src/security/virt-aa-helper.c
>@@ -878,7 +878,7 @@ get_files(vahControl * ctl)
>     size_t i;
>     g_autofree char *uuid = NULL;
>     char uuidstr[VIR_UUID_STRING_BUFLEN];
>-    bool needsVfio = false, needsvhost = false, needsgl = false;
>+    bool needsVfio = false, needsvhost = false, needsgl = false, needsIommufd = false;
>
>     /* verify uuid is same as what we were given on the command line */
>     virUUIDFormat(ctl->def->uuid, uuidstr);
>@@ -1119,6 +1119,9 @@ get_files(vahControl * ctl)
>                 needsVfio = true;
>             }
>
>+            if (dev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES)
>+                needsIommufd = true;
>+
>             if (pci == NULL)
>                 continue;
>
>@@ -1344,10 +1347,14 @@ get_files(vahControl * ctl)
>     if (needsvhost)
>         virBufferAddLit(&buf, "  \"/dev/vhost-net\" rw,\n");
>
>-    if (needsVfio) {
>+    if (needsIommufd) {
>+        virBufferAddLit(&buf, "  \"/dev/iommu\" rwm,\n");
>+        virBufferAddLit(&buf, "  \"/dev/vfio/devices/vfio[0-9]*\" rwm,\n");
>+    } else if (needsVfio) {
>         virBufferAddLit(&buf, "  \"/dev/vfio/vfio\" rw,\n");
>         virBufferAddLit(&buf, "  \"/dev/vfio/[0-9]*\" rw,\n");
>     }
>+
>     if (needsgl) {
>         /* if using gl all sorts of further dri related paths will be needed */
>         virBufferAddLit(&buf, "  # DRI/Mesa/(e)GL config and driver paths\n");
>-- 
>2.43.0
>