]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Update cgroup on RNG hotplug
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 18 Nov 2016 10:17:51 +0000 (11:17 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 23 Nov 2016 15:37:57 +0000 (16:37 +0100)
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>
src/qemu/qemu_cgroup.c
src/qemu/qemu_cgroup.h
src/qemu/qemu_hotplug.c

index 1443f7e3fa8efd631a7eaeb8450ad9b3fc7f26a8..8d3ae4009aa0962b36316770cb5df08879bf6955 100644 (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;
index 623823e7b67b242e0995dd37bf51091e300560f0..1c3b7fffdbf6799f3cd4bb4f470aa01aaee6c720 100644 (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,
index 6b3a068200c615b3d5caf5c7f2ebd1f2abee0e70..b43d9ddd1c15bc66fb3feaa9f0fe38963cad4c94 100644 (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);