[libvirt] [PATCH 4/4] Fix QEMU domain save to block devices with cgroups enabled

Daniel P. Berrange berrange at redhat.com
Thu Apr 22 11:43:29 UTC 2010


When cgroups is enabled, access to block devices is likely to be
restricted to a whitelist. Prior to saving a guest to a block device,
it is necessary to add the block device to the whitelist. This is
not required upon restore, since QEMU reads from stdin

* src/qemu/qemu_driver.c: Add block device to cgroups whitelist
  if neccessary during domain save.
---
 src/qemu/qemu_driver.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 09b6493..3bea7e7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4790,6 +4790,7 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
     struct stat sb;
     int is_reg = 0;
     unsigned long long offset;
+    virCgroupPtr cgroup = NULL;
 
     memset(&header, 0, sizeof(header));
     memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@@ -4997,6 +4998,23 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
     }
 
 
+    if (!is_reg &&
+        qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
+        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unable to find cgroup for %s\n"),
+                            vm->def->name);
+            goto endjob;
+        }
+        rc = virCgroupAllowDevicePath(cgroup, path);
+        if (rc != 0) {
+            virReportSystemError(-rc,
+                                 _("Unable to allow device %s for %s"),
+                                 path, vm->def->name);
+            goto endjob;
+        }
+    }
+
     if ((!bypassSecurityDriver) &&
         driver->securityDriver &&
         driver->securityDriver->domainSetSavedStateLabel &&
@@ -5034,6 +5052,16 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
         driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
         goto endjob;
 
+    if (cgroup != NULL) {
+        rc = virCgroupDenyDevicePath(cgroup, path);
+        if (rc != 0) {
+            virReportSystemError(-rc,
+                                 _("Unable to deny device %s for %s"),
+                                 path, vm->def->name);
+            goto endjob;
+        }
+    }
+
     ret = 0;
 
     /* Shut it down */
@@ -5060,6 +5088,16 @@ endjob:
                 vm->state = VIR_DOMAIN_RUNNING;
         }
 
+        if (ret != 0 && cgroup != NULL) {
+            rc = virCgroupDenyDevicePath(cgroup, path);
+            if (rc != 0) {
+                virReportSystemError(-rc,
+                                     _("Unable to deny device %s for %s"),
+                                     path, vm->def->name);
+                goto endjob;
+            }
+        }
+
         if (qemuDomainObjEndJob(vm) == 0)
             vm = NULL;
     }
@@ -5072,6 +5110,7 @@ cleanup:
         virDomainObjUnlock(vm);
     if (event)
         qemuDomainEventQueue(driver, event);
+    virCgroupFree(&cgroup);
     qemuDriverUnlock(driver);
     return ret;
 }
-- 
1.6.5.2




More information about the libvir-list mailing list