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
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
>
© 2016 - 2025 Red Hat, Inc.