1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-01-26 14:03:49 +03:00

qemu: Update cgroup on RNG hotplug

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@redhat.com>
This commit is contained in:
Michal Privoznik 2016-11-18 11:17:51 +01:00
parent 2878d145fc
commit 085692c8bb
3 changed files with 69 additions and 14 deletions

View File

@ -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("Tearing down 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;

View File

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

View File

@ -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);