Fix QEMU domain save to block devices with cgroups enabled

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.
This commit is contained in:
Daniel P. Berrange 2010-04-21 16:44:40 +01:00
parent 93e0b3c8d6
commit 712048bd9a

View File

@ -4716,6 +4716,7 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
struct stat sb; struct stat sb;
int is_reg = 0; int is_reg = 0;
unsigned long long offset; unsigned long long offset;
virCgroupPtr cgroup = NULL;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@ -4923,6 +4924,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) && if ((!bypassSecurityDriver) &&
driver->securityDriver && driver->securityDriver &&
driver->securityDriver->domainSetSavedStateLabel && driver->securityDriver->domainSetSavedStateLabel &&
@ -4960,6 +4978,16 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1) driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
goto endjob; 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; ret = 0;
/* Shut it down */ /* Shut it down */
@ -4986,6 +5014,16 @@ endjob:
vm->state = VIR_DOMAIN_RUNNING; 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) if (qemuDomainObjEndJob(vm) == 0)
vm = NULL; vm = NULL;
} }
@ -4998,6 +5036,7 @@ cleanup:
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event) if (event)
qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, event);
virCgroupFree(&cgroup);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }