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 neccessary 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 dmoain 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 1f1e703..d5fc4d1 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_bdev = 0;
unsigned long long offset;
+ virCgroupPtr cgroup = NULL;
memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@@ -4979,6 +4980,23 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
}
+ if (is_bdev &&
+ 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 &&
@@ -5016,6 +5034,16 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
goto endjob;
+ if (is_bdev && 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 */
@@ -5042,6 +5070,16 @@ endjob:
vm->state = VIR_DOMAIN_RUNNING;
}
+ if (ret != 0 && is_bdev && 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;
}
@@ -5054,6 +5092,7 @@ cleanup:
virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
+ virCgroupFree(&cgroup);
qemuDriverUnlock(driver);
return ret;
}
--
1.6.5.2