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