]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Update Cgroup, namespace, and seclabel for iommufd
authorNathan Chen <nathanc@nvidia.com>
Fri, 30 Jan 2026 18:59:17 +0000 (10:59 -0800)
committerPavel Hrdina <phrdina@redhat.com>
Mon, 2 Feb 2026 13:12:52 +0000 (14:12 +0100)
When launching a qemu VM with the iommufd feature enabled for VFIO
hostdevs:
- Do not allow cgroup, namespace, and seclabel access to VFIO
paths (/dev/vfio/vfio and /dev/vfio/<iommugroup>)
- Allow access to iommufd paths (/dev/iommu and
/dev/vfio/devices/vfio*) for AppArmor, SELinux, and DAC

Signed-off-by: Nathan Chen <nathanc@nvidia.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
src/qemu/qemu_cgroup.c
src/qemu/qemu_namespace.c
src/security/security_apparmor.c
src/security/security_dac.c
src/security/security_selinux.c
src/security/virt-aa-helper.c

index 7dadef0739cbe4699a9633423d7787c7a5bdb9b4..6148990f1904af106d382d8981aeaf4e8aa52581 100644 (file)
@@ -479,6 +479,9 @@ qemuSetupHostdevCgroup(virDomainObj *vm,
     g_autofree char *path = NULL;
     int perms;
 
+    if (dev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES)
+        return 0;
+
     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
         return 0;
 
index c689cc3e40e876fb39ab828378299436bf83d72b..fb0734193da1f200afc61fe71b0cc331a5463407 100644 (file)
@@ -345,6 +345,9 @@ qemuDomainSetupHostdev(virDomainObj *vm,
 {
     g_autofree char *path = NULL;
 
+    if (hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES)
+        return 0;
+
     if (qemuDomainGetHostdevPath(hostdev, &path, NULL) < 0)
         return -1;
 
index 68ac39611f2fcdca064c5231edf9b412389acf63..934acfb46198401d84d47cc6266a9403eda5a3b0 100644 (file)
@@ -45,6 +45,7 @@
 #include "virstring.h"
 #include "virscsi.h"
 #include "virmdev.h"
+#include "viriommufd.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
 
@@ -841,25 +842,36 @@ AppArmorSetSecurityHostdevLabel(virSecurityManager *mgr,
     }
 
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
-        virPCIDevice *pci =
+        g_autoptr(virPCIDevice) pci =
             virPCIDeviceNew(&pcisrc->addr);
 
         if (!pci)
             goto done;
 
         if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) {
-            char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+            if (dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
+                char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
 
-            if (!vfioGroupDev) {
-                virPCIDeviceFree(pci);
-                goto done;
+                if (!vfioGroupDev) {
+                    goto done;
+                }
+                ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
+                VIR_FREE(vfioGroupDev);
+            } else {
+                g_autofree char *vfiofdDev = NULL;
+
+                if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+                    goto done;
+
+                ret = AppArmorSetSecurityPCILabel(pci, vfiofdDev, ptr);
+                if (ret < 0)
+                    goto done;
+
+                ret = AppArmorSetSecurityPCILabel(pci, VIR_IOMMU_DEV_PATH, ptr);
             }
-            ret = AppArmorSetSecurityPCILabel(pci, vfioGroupDev, ptr);
-            VIR_FREE(vfioGroupDev);
         } else {
             ret = virPCIDeviceFileIterate(pci, AppArmorSetSecurityPCILabel, ptr);
         }
-        virPCIDeviceFree(pci);
         break;
     }
 
index 2f788b872ae03dd5a35f43d3fff651ee57330be2..d0ed22db2d24c6739fff2e88b0953bd242b71ed1 100644 (file)
@@ -41,6 +41,7 @@
 #include "virscsivhost.h"
 #include "virstring.h"
 #include "virutil.h"
+#include "viriommufd.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
 
@@ -1282,14 +1283,27 @@ 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);
+            } else {
+                g_autofree char *vfiofdDev = NULL;
+
+                if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+                    return -1;
 
-            ret = virSecurityDACSetHostdevLabelHelper(vfioGroupDev,
-                                                      false,
-                                                      &cbdata);
+                ret = virSecurityDACSetHostdevLabelHelper(vfiofdDev, false, &cbdata);
+                if (ret < 0)
+                    break;
+
+                ret = virSecurityDACSetHostdevLabelHelper(VIR_IOMMU_DEV_PATH, false, &cbdata);
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci,
                                           virSecurityDACSetPCILabel,
@@ -1443,13 +1457,28 @@ 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 {
+                g_autofree char *vfiofdDev = NULL;
+
+                if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+                    return -1;
+
+                ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
+                                                             vfiofdDev, false);
+                if (ret < 0)
+                    break;
+
+                ret = virSecurityDACRestoreFileLabelInternal(mgr, NULL,
+                                                             VIR_IOMMU_DEV_PATH, false);
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci, virSecurityDACRestorePCILabel, mgr);
         }
index 2f3cc274a5d901dc82d73107b2c7b3e945cf2346..834383a7de1920f79b1f15761fee522a6ea43235 100644 (file)
@@ -41,6 +41,7 @@
 #include "virconf.h"
 #include "virtpm.h"
 #include "virstring.h"
+#include "viriommufd.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
 
@@ -2256,14 +2257,27 @@ 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);
+            } else {
+                g_autofree char *vfiofdDev = NULL;
+
+                if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+                    return -1;
 
-            ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
-                                                          false,
-                                                          &data);
+                ret = virSecuritySELinuxSetHostdevLabelHelper(vfiofdDev, false, &data);
+                if (ret)
+                    break;
+
+                ret = virSecuritySELinuxSetHostdevLabelHelper(VIR_IOMMU_DEV_PATH, false, &data);
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCILabel, &data);
         }
@@ -2491,12 +2505,25 @@ 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);
+            } else {
+                g_autofree char *vfiofdDev = NULL;
+
+                if (virPCIDeviceGetVfioPath(&dev->source.subsys.u.pci.addr, &vfiofdDev) < 0)
+                    return -1;
 
-            ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false, false);
+                ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiofdDev, false, false);
+                if (ret < 0)
+                    break;
+
+                ret = virSecuritySELinuxRestoreFileLabel(mgr, VIR_IOMMU_DEV_PATH, false, false);
+            }
         } else {
             ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxRestorePCILabel, mgr);
         }
index 211c34f92637e17e876be91566af7e9821d5f601..f4ec6b7826ba532f0dbac2dcd4ed89f7f98e6be6 100644 (file)
@@ -50,6 +50,7 @@
 #include "virstring.h"
 #include "virgettext.h"
 #include "virhostdev.h"
+#include "viriommufd.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
 
@@ -1114,8 +1115,9 @@ get_files(vahControl * ctl)
 
             virDeviceHostdevPCIDriverName driverName = dev->source.subsys.u.pci.driver.name;
 
-            if (driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO ||
-                driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) {
+            if ((driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO ||
+                driverName == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT) &&
+                dev->source.subsys.u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES) {
                 needsVfio = true;
             }
 
@@ -1385,9 +1387,18 @@ get_files(vahControl * ctl)
         }
     }
 
-    if (ctl->newfile &&
-        vah_add_file(&buf, ctl->newfile, "rwk") != 0) {
-        return -1;
+    if (ctl->newfile) {
+        const char *perms = "rwk";
+
+        /* VFIO and iommufd devices need mmap permission */
+        if (STRPREFIX(ctl->newfile, "/dev/vfio/devices/vfio") ||
+            STREQ(ctl->newfile, VIR_IOMMU_DEV_PATH)) {
+            perms = "rwm";
+        }
+
+        if (vah_add_file(&buf, ctl->newfile, perms) != 0) {
+            return -1;
+        }
     }
 
     ctl->files = virBufferContentAndReset(&buf);
@@ -1561,8 +1572,15 @@ main(int argc, char **argv)
                 }
         }
         if (ctl->append && ctl->newfile) {
-            if (vah_add_file(&buf, ctl->newfile, "rwk") != 0)
-                goto cleanup;
+            const char *perms = "rwk";
+
+            if (STRPREFIX(ctl->newfile, "/dev/vfio/devices/vfio") ||
+                STREQ(ctl->newfile, VIR_IOMMU_DEV_PATH)) {
+                perms = "rwm";
+            }
+
+            if (vah_add_file(&buf, ctl->newfile, perms) != 0)
+                return -1;
         } else {
             if (ctl->def->virtType == VIR_DOMAIN_VIRT_QEMU ||
                 ctl->def->virtType == VIR_DOMAIN_VIRT_KQEMU ||