Daniel P. Berrange 427ed2
From 076fffe1514b72ffc9a041f7f68348f5487ee8ba Mon Sep 17 00:00:00 2001
Daniel P. Berrange 427ed2
From: Daniel P. Berrange <berrange@redhat.com>
Daniel P. Berrange 427ed2
Date: Wed, 11 Nov 2009 12:07:00 +0000
Daniel P. Berrange 427ed2
Subject: [PATCH] Fix save and restore with non-privileged guests and SELinux
Daniel P. Berrange 427ed2
Daniel P. Berrange 427ed2
When running qemu:///system instance, libvirtd runs as root,
Daniel P. Berrange 427ed2
but QEMU may optionally be configured to run non-root. When
Daniel P. Berrange 427ed2
then saving a guest to a state file, the file is initially
Daniel P. Berrange 427ed2
created as root, and thus QEMU cannot write to it. It is also
Daniel P. Berrange 427ed2
missing labelling required to allow access via SELinux.
Daniel P. Berrange 427ed2
Daniel P. Berrange 427ed2
* src/qemu/qemu_driver.c: Set ownership on save image before
Daniel P. Berrange 427ed2
  running migrate command in virDomainSave impl. Call out to
Daniel P. Berrange 427ed2
  security driver to set save image labelling
Daniel P. Berrange 427ed2
* src/security/security_driver.h: Add driver APIs for setting
Daniel P. Berrange 427ed2
  and restoring saved state file labelling
Daniel P. Berrange 427ed2
* src/security/security_selinux.c: Implement saved state file
Daniel P. Berrange 427ed2
  labelling for SELinux
Daniel P. Berrange 427ed2
Daniel P. Berrange 427ed2
(cherry picked from commit bc0010b3d149df00406b82c37eb59874d8525af4)
Daniel P. Berrange 427ed2
Daniel P. Berrange 427ed2
Fedora-patch: libvirt-qemu-save-restore.patch
Daniel P. Berrange 427ed2
---
Daniel P. Berrange 427ed2
 src/qemu/qemu_driver.c          |   35 ++++++++++++++++++++++++++++++++---
Daniel P. Berrange 427ed2
 src/security/security_driver.h  |    7 +++++++
Daniel P. Berrange 427ed2
 src/security/security_selinux.c |   23 +++++++++++++++++++++++
Daniel P. Berrange 427ed2
 3 files changed, 62 insertions(+), 3 deletions(-)
Daniel P. Berrange 427ed2
Daniel P. Berrange 427ed2
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
Daniel P. Berrange 427ed2
index c544c4b..171ac8f 100644
Daniel P. Berrange 427ed2
--- a/src/qemu/qemu_driver.c
Daniel P. Berrange 427ed2
+++ b/src/qemu/qemu_driver.c
Daniel P. Berrange 427ed2
@@ -3146,6 +3146,7 @@ static int qemudDomainSave(virDomainPtr dom,
Daniel P. Berrange 427ed2
     char *xml = NULL;
Daniel P. Berrange 427ed2
     struct qemud_save_header header;
Daniel P. Berrange 427ed2
     int ret = -1;
Daniel P. Berrange 427ed2
+    int rc;
Daniel P. Berrange 427ed2
     virDomainEventPtr event = NULL;
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
     memset(&header, 0, sizeof(header));
Daniel P. Berrange 427ed2
@@ -3226,9 +3227,22 @@ static int qemudDomainSave(virDomainPtr dom,
Daniel P. Berrange 427ed2
     }
Daniel P. Berrange 427ed2
     fd = -1;
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
+    if (driver->privileged &&
Daniel P. Berrange 427ed2
+        chown(path, driver->user, driver->group) < 0) {
Daniel P. Berrange 427ed2
+        virReportSystemError(NULL, errno,
Daniel P. Berrange 427ed2
+                             _("unable to set ownership of '%s' to user %d:%d"),
Daniel P. Berrange 427ed2
+                             path, driver->user, driver->group);
Daniel P. Berrange 427ed2
+        goto cleanup;
Daniel P. Berrange 427ed2
+    }
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+    if (driver->securityDriver &&
Daniel P. Berrange 427ed2
+        driver->securityDriver->domainSetSavedStateLabel &&
Daniel P. Berrange 427ed2
+        driver->securityDriver->domainSetSavedStateLabel(dom->conn, vm, path) == -1)
Daniel P. Berrange 427ed2
+        goto cleanup;
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
     if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
Daniel P. Berrange 427ed2
         const char *args[] = { "cat", NULL };
Daniel P. Berrange 427ed2
-        ret = qemuMonitorMigrateToCommand(vm, 0, args, path);
Daniel P. Berrange 427ed2
+        rc = qemuMonitorMigrateToCommand(vm, 0, args, path);
Daniel P. Berrange 427ed2
     } else {
Daniel P. Berrange 427ed2
         const char *prog = qemudSaveCompressionTypeToString(header.compressed);
Daniel P. Berrange 427ed2
         const char *args[] = {
Daniel P. Berrange 427ed2
@@ -3236,12 +3250,27 @@ static int qemudDomainSave(virDomainPtr dom,
Daniel P. Berrange 427ed2
             "-c",
Daniel P. Berrange 427ed2
             NULL
Daniel P. Berrange 427ed2
         };
Daniel P. Berrange 427ed2
-        ret = qemuMonitorMigrateToCommand(vm, 0, args, path);
Daniel P. Berrange 427ed2
+        rc = qemuMonitorMigrateToCommand(vm, 0, args, path);
Daniel P. Berrange 427ed2
     }
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
-    if (ret < 0)
Daniel P. Berrange 427ed2
+    if (rc < 0)
Daniel P. Berrange 427ed2
         goto cleanup;
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
+    if (driver->privileged &&
Daniel P. Berrange 427ed2
+        chown(path, 0, 0) < 0) {
Daniel P. Berrange 427ed2
+        virReportSystemError(NULL, errno,
Daniel P. Berrange 427ed2
+                             _("unable to set ownership of '%s' to user %d:%d"),
Daniel P. Berrange 427ed2
+                             path, 0, 0);
Daniel P. Berrange 427ed2
+        goto cleanup;
Daniel P. Berrange 427ed2
+    }
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+    if (driver->securityDriver &&
Daniel P. Berrange 427ed2
+        driver->securityDriver->domainRestoreSavedStateLabel &&
Daniel P. Berrange 427ed2
+        driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, path) == -1)
Daniel P. Berrange 427ed2
+        goto cleanup;
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+    ret = 0;
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
     /* Shut it down */
Daniel P. Berrange 427ed2
     qemudShutdownVMDaemon(dom->conn, driver, vm);
Daniel P. Berrange 427ed2
     event = virDomainEventNewFromObj(vm,
Daniel P. Berrange 427ed2
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
Daniel P. Berrange 427ed2
index fde2978..5514962 100644
Daniel P. Berrange 427ed2
--- a/src/security/security_driver.h
Daniel P. Berrange 427ed2
+++ b/src/security/security_driver.h
Daniel P. Berrange 427ed2
@@ -42,6 +42,11 @@ typedef int (*virSecurityDomainRestoreHostdevLabel) (virConnectPtr conn,
Daniel P. Berrange 427ed2
 typedef int (*virSecurityDomainSetHostdevLabel) (virConnectPtr conn,
Daniel P. Berrange 427ed2
                                                  virDomainObjPtr vm,
Daniel P. Berrange 427ed2
                                                  virDomainHostdevDefPtr dev);
Daniel P. Berrange 427ed2
+typedef int (*virSecurityDomainSetSavedStateLabel) (virConnectPtr conn,
Daniel P. Berrange 427ed2
+                                                    virDomainObjPtr vm,
Daniel P. Berrange 427ed2
+                                                    const char *savefile);
Daniel P. Berrange 427ed2
+typedef int (*virSecurityDomainRestoreSavedStateLabel) (virConnectPtr conn,
Daniel P. Berrange 427ed2
+                                                        const char *savefile);
Daniel P. Berrange 427ed2
 typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
Daniel P. Berrange 427ed2
                                           virDomainObjPtr sec);
Daniel P. Berrange 427ed2
 typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn,
Daniel P. Berrange 427ed2
@@ -71,6 +76,8 @@ struct _virSecurityDriver {
Daniel P. Berrange 427ed2
     virSecurityDomainRestoreLabel domainRestoreSecurityLabel;
Daniel P. Berrange 427ed2
     virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel;
Daniel P. Berrange 427ed2
     virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel;
Daniel P. Berrange 427ed2
+    virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel;
Daniel P. Berrange 427ed2
+    virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
     /*
Daniel P. Berrange 427ed2
      * This is internally managed driver state and should only be accessed
Daniel P. Berrange 427ed2
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
Daniel P. Berrange 427ed2
index 7e0f71a..4f2d1d3 100644
Daniel P. Berrange 427ed2
--- a/src/security/security_selinux.c
Daniel P. Berrange 427ed2
+++ b/src/security/security_selinux.c
Daniel P. Berrange 427ed2
@@ -525,6 +525,7 @@ done:
Daniel P. Berrange 427ed2
     return ret;
Daniel P. Berrange 427ed2
 }
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
 static int
Daniel P. Berrange 427ed2
 SELinuxRestoreSecurityPCILabel(virConnectPtr conn,
Daniel P. Berrange 427ed2
                                pciDevice *dev ATTRIBUTE_UNUSED,
Daniel P. Berrange 427ed2
@@ -625,6 +626,26 @@ SELinuxRestoreSecurityLabel(virConnectPtr conn,
Daniel P. Berrange 427ed2
     return rc;
Daniel P. Berrange 427ed2
 }
Daniel P. Berrange 427ed2
 
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+static int
Daniel P. Berrange 427ed2
+SELinuxSetSavedStateLabel(virConnectPtr conn,
Daniel P. Berrange 427ed2
+                          virDomainObjPtr vm,
Daniel P. Berrange 427ed2
+                          const char *savefile)
Daniel P. Berrange 427ed2
+{
Daniel P. Berrange 427ed2
+    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+    return SELinuxSetFilecon(conn, savefile, secdef->imagelabel);
Daniel P. Berrange 427ed2
+}
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+static int
Daniel P. Berrange 427ed2
+SELinuxRestoreSavedStateLabel(virConnectPtr conn,
Daniel P. Berrange 427ed2
+                              const char *savefile)
Daniel P. Berrange 427ed2
+{
Daniel P. Berrange 427ed2
+    return SELinuxRestoreSecurityFileLabel(conn, savefile);
Daniel P. Berrange 427ed2
+}
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
+
Daniel P. Berrange 427ed2
 static int
Daniel P. Berrange 427ed2
 SELinuxSecurityVerify(virConnectPtr conn, virDomainDefPtr def)
Daniel P. Berrange 427ed2
 {
Daniel P. Berrange 427ed2
@@ -694,4 +715,6 @@ virSecurityDriver virSELinuxSecurityDriver = {
Daniel P. Berrange 427ed2
     .domainSetSecurityLabel     = SELinuxSetSecurityLabel,
Daniel P. Berrange 427ed2
     .domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel,
Daniel P. Berrange 427ed2
     .domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel,
Daniel P. Berrange 427ed2
+    .domainSetSavedStateLabel = SELinuxSetSavedStateLabel,
Daniel P. Berrange 427ed2
+    .domainRestoreSavedStateLabel = SELinuxRestoreSavedStateLabel,
Daniel P. Berrange 427ed2
 };
Daniel P. Berrange 427ed2
-- 
Daniel P. Berrange 427ed2
1.6.2.5
Daniel P. Berrange 427ed2