If users try to hotplug RNG device with a backend different to /dev/random or /dev/urandom the whole operation fails as qemu is unable to access the device. The problem is we don't update device CGroups during the operation. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/qemu/qemu_cgroup.c | 62 +++++++++++++++++++++++++++++++++++++++---------- src/qemu/qemu_cgroup.h | 4 ++++ src/qemu/qemu_hotplug.c | 17 ++++++++++++-- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 1443f7e..e7ce032 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -569,6 +569,54 @@ qemuSetupFirmwareCgroup(virDomainObjPtr vm) } +int +qemuSetupRNGCgroup(virDomainObjPtr vm, + virDomainRNGDefPtr rng) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + int rv; + + if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM) { + VIR_DEBUG("Setting Cgroup ACL for RNG device"); + rv = virCgroupAllowDevicePath(priv->cgroup, + rng->source.file, + VIR_CGROUP_DEVICE_RW, false); + virDomainAuditCgroupPath(vm, priv->cgroup, "allow", + rng->source.file, + "rw", rv == 0); + if (rv < 0 && + !virLastErrorIsSystemErrno(ENOENT)) + return -1; + } + + return 0; +} + + +int +qemuTeardownRNGCgroup(virDomainObjPtr vm, + virDomainRNGDefPtr rng) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + int rv; + + if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM) { + VIR_DEBUG("Setting Cgroup ACL for RNG device"); + rv = virCgroupDenyDevicePath(priv->cgroup, + rng->source.file, + VIR_CGROUP_DEVICE_RW, false); + virDomainAuditCgroupPath(vm, priv->cgroup, "deny", + rng->source.file, + "rw", rv == 0); + if (rv < 0 && + !virLastErrorIsSystemErrno(ENOENT)) + return -1; + } + + return 0; +} + + static int qemuSetupDevicesCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm) @@ -663,18 +711,8 @@ qemuSetupDevicesCgroup(virQEMUDriverPtr driver, } for (i = 0; i < vm->def->nrngs; i++) { - if (vm->def->rngs[i]->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM) { - VIR_DEBUG("Setting Cgroup ACL for RNG device"); - rv = virCgroupAllowDevicePath(priv->cgroup, - vm->def->rngs[i]->source.file, - VIR_CGROUP_DEVICE_RW, false); - virDomainAuditCgroupPath(vm, priv->cgroup, "allow", - vm->def->rngs[i]->source.file, - "rw", rv == 0); - if (rv < 0 && - !virLastErrorIsSystemErrno(ENOENT)) - goto cleanup; - } + if (qemuSetupRNGCgroup(vm, vm->def->rngs[i]) < 0) + goto cleanup; } ret = 0; diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h index 623823e..1c3b7ff 100644 --- a/src/qemu/qemu_cgroup.h +++ b/src/qemu/qemu_cgroup.h @@ -43,6 +43,10 @@ int qemuSetupHostdevCgroup(virDomainObjPtr vm, int qemuTeardownHostdevCgroup(virDomainObjPtr vm, virDomainHostdevDefPtr dev) ATTRIBUTE_RETURN_CHECK; +int qemuSetupRNGCgroup(virDomainObjPtr vm, + virDomainRNGDefPtr rng); +int qemuTeardownRNGCgroup(virDomainObjPtr vm, + virDomainRNGDefPtr rng); int qemuConnectCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm); int qemuSetupCgroup(virQEMUDriverPtr driver, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6b3a068..b43d9dd 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1951,6 +1951,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn, char *tlsAlias = NULL; char *secAlias = NULL; bool releaseaddr = false; + bool teardowncgroup = false; bool chardevAdded = false; bool objAdded = false; bool tlsobjAdded = false; @@ -1996,6 +1997,10 @@ qemuDomainAttachRNGDevice(virConnectPtr conn, goto cleanup; } + if (qemuSetupRNGCgroup(vm, rng) < 0) + goto cleanup; + teardowncgroup = true; + if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) qemuDomainPrepareChardevSourceTLS(rng->source.chardev, cfg); @@ -2073,8 +2078,13 @@ qemuDomainAttachRNGDevice(virConnectPtr conn, virJSONValueFree(tlsProps); virJSONValueFree(secProps); virJSONValueFree(props); - if (ret < 0 && releaseaddr) - qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL); + if (ret < 0) { + if (releaseaddr) + qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL); + if (teardowncgroup && qemuTeardownRNGCgroup(vm, rng) < 0) + VIR_WARN("Unable to remove RNG device cgroup ACL on hotplug fail"); + } + VIR_FREE(tlsAlias); VIR_FREE(secAlias); VIR_FREE(charAlias); @@ -3912,6 +3922,9 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver, if (rc < 0) goto cleanup; + if (qemuTeardownRNGCgroup(vm, rng) < 0) + VIR_WARN("Failed to remove RNG device cgroup ACL"); + event = virDomainEventDeviceRemovedNewFromObj(vm, rng->info.alias); qemuDomainEventQueue(driver, event); -- 2.8.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list