Hi

On Fri, Feb 10, 2017 at 6:57 PM Michal Privoznik <mprivozn@redhat.com> wrote:
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@redhat.com>


Thanks, but that doesn't work :)

You should loop over the spice/gl graphics nodes (virtio accel3d is not actually using 3d, as of today, if the graphics configuration/layer doesn't provide it)

See also Ján Tomko "qemu_cgroup: allow access to /dev/dri/render*" patch, which use to work.

After my series "[PATCH 0/5] Add rendernode selection support", it will further have to narrow the path allowed to the specified rendernode. This can be done in my series or yours, depending on applied order.

thanks

 
---
 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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
--
Marc-André Lureau