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@xxxxxxxxxx> --- 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@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list