[libvirt] [PATCH 7/7] qemu: Allow /dev/dri/render* for virgl domains

Michal Privoznik mprivozn at redhat.com
Fri Feb 10 14:56:55 UTC 2017


When enabling virgl, qemu opens /dev/dri/render*. So far, we are
not allowing that in devices cgroup nor creating the file in
domain's namespace and thus requiring users to set the paths in
qemu.conf. This, however, is suboptimal as it allows access to
ALL qemu processes even those which don't have virgl configured.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_cgroup.c | 51 ++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_domain.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)

diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 209cbc275..c667dc12b 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -335,6 +335,52 @@ qemuTeardownHostdevCgroup(virDomainObjPtr vm,
     return ret;
 }
 
+
+static int
+qemuSetupVideoCgroup(virDomainObjPtr vm,
+                     virDomainVideoDefPtr video)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    const char *dripath = "/dev/dri";
+    char *devpath = NULL;
+    struct dirent *ent;
+    DIR *dir;
+    int rv, rc, ret = -1;
+
+    if (!video->accel ||
+        !video->accel->accel3d)
+        return 0;
+
+    if (virDirOpen(&dir, dripath) < 0)
+        return ret;
+
+    while ((rv = virDirRead(dir, &ent, dripath)) > 0) {
+        if (!STRPREFIX(ent->d_name, "render"))
+            continue;
+
+        VIR_FREE(devpath);
+        if (virAsprintf(&devpath, "%s/%s", dripath, ent->d_name) < 0)
+            goto cleanup;
+
+        rc = virCgroupAllowDevicePath(priv->cgroup, devpath,
+                                      VIR_CGROUP_DEVICE_RW, false);
+        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", devpath,
+                                 "rw", rc == 0);
+        if (rv < 0)
+            goto cleanup;
+    }
+
+    if (rv < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(devpath);
+    VIR_DIR_CLOSE(dir);
+    return ret;
+}
+
+
 static int
 qemuSetupBlkioCgroup(virDomainObjPtr vm)
 {
@@ -604,6 +650,11 @@ qemuSetupDevicesCgroup(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
+    for (i = 0; i < vm->def->nvideos; i++) {
+        if (qemuSetupVideoCgroup(vm, vm->def->videos[i]) < 0)
+            goto cleanup;
+    }
+
     for (i = 0; i < vm->def->ninputs; i++) {
         if (qemuSetupInputCgroup(vm, vm->def->inputs[i]) < 0)
             goto cleanup;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 515e0052e..06ba1cf00 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -7504,6 +7504,67 @@ qemuDomainSetupTPM(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
 }
 
 
+static int
+qemuDomainSetupVideo(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
+                     virDomainVideoDefPtr video,
+                     const char *devPath)
+{
+    const char *dripath = "/dev/dri";
+    char *dridevpath = NULL;
+    struct dirent *ent;
+    DIR *dir;
+    int rv, ret = -1;
+
+    if (!video->accel ||
+        !video->accel->accel3d)
+        return 0;
+
+    if (virDirOpen(&dir, dripath) < 0)
+        return ret;
+
+    while ((rv = virDirRead(dir, &ent, dripath)) > 0) {
+        if (!STRPREFIX(ent->d_name, "render"))
+            continue;
+
+        VIR_FREE(dridevpath);
+        if (virAsprintf(&dridevpath, "%s/%s", dripath, ent->d_name) < 0)
+            goto cleanup;
+
+        if (qemuDomainCreateDevice(dridevpath, devPath, false) < 0)
+            goto cleanup;
+    }
+
+    if (rv < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(dridevpath);
+    VIR_DIR_CLOSE(dir);
+    return ret;
+}
+
+
+static int
+qemuDomainSetupAllVideos(virQEMUDriverPtr driver,
+                         virDomainObjPtr vm,
+                         const char *devPath)
+{
+    size_t i;
+
+    VIR_DEBUG("Setting up videos");
+    for (i = 0; i < vm->def->nvideos; i++) {
+        if (qemuDomainSetupVideo(driver,
+                                 vm->def->videos[i],
+                                 devPath) < 0)
+            return -1;
+    }
+
+    VIR_DEBUG("Setup all videos");
+    return 0;
+}
+
+
 static int
 qemuDomainSetupInput(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
                      virDomainInputDefPtr input,
@@ -7657,6 +7718,9 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
     if (qemuDomainSetupTPM(driver, vm, devPath) < 0)
         goto cleanup;
 
+    if (qemuDomainSetupAllVideos(driver, vm, devPath) < 0)
+        goto cleanup;
+
     if (qemuDomainSetupAllInputs(driver, vm, devPath) < 0)
         goto cleanup;
 
-- 
2.11.0




More information about the libvir-list mailing list