Commit 1151cdcad3f4b68478b076832843338256b94644

Fix save and restore with non-privileged guests and SELinux

When running qemu:///system instance, libvirtd runs as root,
but QEMU may optionally be configured to run non-root. When
then saving a guest to a state file, the file is initially
created as root, and thus QEMU cannot write to it. It is also
missing labelling required to allow access via SELinux.

* src/qemu/qemu_driver.c: Set ownership on save image before
  running migrate command in virDomainSave impl. Call out to
  security driver to set save image labelling
* src/security/security_driver.h: Add driver APIs for setting
  and restoring saved state file labelling
* src/security/security_selinux.c: Implement saved state file
  labelling for SELinux

(cherry picked from commit bc0010b3d149df00406b82c37eb59874d8525af4)

Fedora-patch: libvirt-qemu-save-restore.patch
  
31463146 char *xml = NULL;
31473147 struct qemud_save_header header;
31483148 int ret = -1;
3149 int rc;
31493150 virDomainEventPtr event = NULL;
31503151
31513152 memset(&header, 0, sizeof(header));
32273227 }
32283228 fd = -1;
32293229
3230 if (driver->privileged &&
3231 chown(path, driver->user, driver->group) < 0) {
3232 virReportSystemError(NULL, errno,
3233 _("unable to set ownership of '%s' to user %d:%d"),
3234 path, driver->user, driver->group);
3235 goto cleanup;
3236 }
3237
3238 if (driver->securityDriver &&
3239 driver->securityDriver->domainSetSavedStateLabel &&
3240 driver->securityDriver->domainSetSavedStateLabel(dom->conn, vm, path) == -1)
3241 goto cleanup;
3242
32303243 if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
32313244 const char *args[] = { "cat", NULL };
3232 ret = qemuMonitorMigrateToCommand(vm, 0, args, path);
3245 rc = qemuMonitorMigrateToCommand(vm, 0, args, path);
32333246 } else {
32343247 const char *prog = qemudSaveCompressionTypeToString(header.compressed);
32353248 const char *args[] = {
32503250 "-c",
32513251 NULL
32523252 };
3253 ret = qemuMonitorMigrateToCommand(vm, 0, args, path);
3253 rc = qemuMonitorMigrateToCommand(vm, 0, args, path);
32543254 }
32553255
3256 if (ret < 0)
3256 if (rc < 0)
32573257 goto cleanup;
3258
3259 if (driver->privileged &&
3260 chown(path, 0, 0) < 0) {
3261 virReportSystemError(NULL, errno,
3262 _("unable to set ownership of '%s' to user %d:%d"),
3263 path, 0, 0);
3264 goto cleanup;
3265 }
3266
3267 if (driver->securityDriver &&
3268 driver->securityDriver->domainRestoreSavedStateLabel &&
3269 driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, path) == -1)
3270 goto cleanup;
3271
3272 ret = 0;
32583273
32593274 /* Shut it down */
32603275 qemudShutdownVMDaemon(dom->conn, driver, vm);
  
4242typedef int (*virSecurityDomainSetHostdevLabel) (virConnectPtr conn,
4343 virDomainObjPtr vm,
4444 virDomainHostdevDefPtr dev);
45typedef int (*virSecurityDomainSetSavedStateLabel) (virConnectPtr conn,
46 virDomainObjPtr vm,
47 const char *savefile);
48typedef int (*virSecurityDomainRestoreSavedStateLabel) (virConnectPtr conn,
49 const char *savefile);
4550typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
4651 virDomainObjPtr sec);
4752typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn,
7676 virSecurityDomainRestoreLabel domainRestoreSecurityLabel;
7777 virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel;
7878 virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel;
79 virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel;
80 virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
7981
8082 /*
8183 * This is internally managed driver state and should only be accessed
  
525525 return ret;
526526}
527527
528
528529static int
529530SELinuxRestoreSecurityPCILabel(virConnectPtr conn,
530531 pciDevice *dev ATTRIBUTE_UNUSED,
626626 return rc;
627627}
628628
629
629630static int
631SELinuxSetSavedStateLabel(virConnectPtr conn,
632 virDomainObjPtr vm,
633 const char *savefile)
634{
635 const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
636
637 return SELinuxSetFilecon(conn, savefile, secdef->imagelabel);
638}
639
640
641static int
642SELinuxRestoreSavedStateLabel(virConnectPtr conn,
643 const char *savefile)
644{
645 return SELinuxRestoreSecurityFileLabel(conn, savefile);
646}
647
648
649static int
630650SELinuxSecurityVerify(virConnectPtr conn, virDomainDefPtr def)
631651{
632652 const virSecurityLabelDefPtr secdef = &def->seclabel;
715715 .domainSetSecurityLabel = SELinuxSetSecurityLabel,
716716 .domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel,
717717 .domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel,
718 .domainSetSavedStateLabel = SELinuxSetSavedStateLabel,
719 .domainRestoreSavedStateLabel = SELinuxRestoreSavedStateLabel,
718720};