[libvirt] [PATCH 1/2] qemu: Update cgroup on RNG hotplug

Michal Privoznik mprivozn at redhat.com
Fri Nov 18 11:30:12 UTC 2016


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 at redhat.com>
---
 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




More information about the libvir-list mailing list