From 427ed20801cf33eaebdacebd7ae5668c12d2fc79 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Nov 11 2009 15:33:52 +0000 Subject: Fix QEMU save/restore permissions / labelling --- diff --git a/libvirt-qemu-save-restore.patch b/libvirt-qemu-save-restore.patch new file mode 100644 index 0000000..366252e --- /dev/null +++ b/libvirt-qemu-save-restore.patch @@ -0,0 +1,168 @@ +From 076fffe1514b72ffc9a041f7f68348f5487ee8ba Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +Date: Wed, 11 Nov 2009 12:07:00 +0000 +Subject: [PATCH] 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 +--- + src/qemu/qemu_driver.c | 35 ++++++++++++++++++++++++++++++++--- + src/security/security_driver.h | 7 +++++++ + src/security/security_selinux.c | 23 +++++++++++++++++++++++ + 3 files changed, 62 insertions(+), 3 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index c544c4b..171ac8f 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -3146,6 +3146,7 @@ static int qemudDomainSave(virDomainPtr dom, + char *xml = NULL; + struct qemud_save_header header; + int ret = -1; ++ int rc; + virDomainEventPtr event = NULL; + + memset(&header, 0, sizeof(header)); +@@ -3226,9 +3227,22 @@ static int qemudDomainSave(virDomainPtr dom, + } + fd = -1; + ++ if (driver->privileged && ++ chown(path, driver->user, driver->group) < 0) { ++ virReportSystemError(NULL, errno, ++ _("unable to set ownership of '%s' to user %d:%d"), ++ path, driver->user, driver->group); ++ goto cleanup; ++ } ++ ++ if (driver->securityDriver && ++ driver->securityDriver->domainSetSavedStateLabel && ++ driver->securityDriver->domainSetSavedStateLabel(dom->conn, vm, path) == -1) ++ goto cleanup; ++ + if (header.compressed == QEMUD_SAVE_FORMAT_RAW) { + const char *args[] = { "cat", NULL }; +- ret = qemuMonitorMigrateToCommand(vm, 0, args, path); ++ rc = qemuMonitorMigrateToCommand(vm, 0, args, path); + } else { + const char *prog = qemudSaveCompressionTypeToString(header.compressed); + const char *args[] = { +@@ -3236,12 +3250,27 @@ static int qemudDomainSave(virDomainPtr dom, + "-c", + NULL + }; +- ret = qemuMonitorMigrateToCommand(vm, 0, args, path); ++ rc = qemuMonitorMigrateToCommand(vm, 0, args, path); + } + +- if (ret < 0) ++ if (rc < 0) + goto cleanup; + ++ if (driver->privileged && ++ chown(path, 0, 0) < 0) { ++ virReportSystemError(NULL, errno, ++ _("unable to set ownership of '%s' to user %d:%d"), ++ path, 0, 0); ++ goto cleanup; ++ } ++ ++ if (driver->securityDriver && ++ driver->securityDriver->domainRestoreSavedStateLabel && ++ driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, path) == -1) ++ goto cleanup; ++ ++ ret = 0; ++ + /* Shut it down */ + qemudShutdownVMDaemon(dom->conn, driver, vm); + event = virDomainEventNewFromObj(vm, +diff --git a/src/security/security_driver.h b/src/security/security_driver.h +index fde2978..5514962 100644 +--- a/src/security/security_driver.h ++++ b/src/security/security_driver.h +@@ -42,6 +42,11 @@ typedef int (*virSecurityDomainRestoreHostdevLabel) (virConnectPtr conn, + typedef int (*virSecurityDomainSetHostdevLabel) (virConnectPtr conn, + virDomainObjPtr vm, + virDomainHostdevDefPtr dev); ++typedef int (*virSecurityDomainSetSavedStateLabel) (virConnectPtr conn, ++ virDomainObjPtr vm, ++ const char *savefile); ++typedef int (*virSecurityDomainRestoreSavedStateLabel) (virConnectPtr conn, ++ const char *savefile); + typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn, + virDomainObjPtr sec); + typedef int (*virSecurityDomainReserveLabel) (virConnectPtr conn, +@@ -71,6 +76,8 @@ struct _virSecurityDriver { + virSecurityDomainRestoreLabel domainRestoreSecurityLabel; + virSecurityDomainRestoreHostdevLabel domainRestoreSecurityHostdevLabel; + virSecurityDomainSetHostdevLabel domainSetSecurityHostdevLabel; ++ virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel; ++ virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel; + + /* + * This is internally managed driver state and should only be accessed +diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c +index 7e0f71a..4f2d1d3 100644 +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -525,6 +525,7 @@ done: + return ret; + } + ++ + static int + SELinuxRestoreSecurityPCILabel(virConnectPtr conn, + pciDevice *dev ATTRIBUTE_UNUSED, +@@ -625,6 +626,26 @@ SELinuxRestoreSecurityLabel(virConnectPtr conn, + return rc; + } + ++ ++static int ++SELinuxSetSavedStateLabel(virConnectPtr conn, ++ virDomainObjPtr vm, ++ const char *savefile) ++{ ++ const virSecurityLabelDefPtr secdef = &vm->def->seclabel; ++ ++ return SELinuxSetFilecon(conn, savefile, secdef->imagelabel); ++} ++ ++ ++static int ++SELinuxRestoreSavedStateLabel(virConnectPtr conn, ++ const char *savefile) ++{ ++ return SELinuxRestoreSecurityFileLabel(conn, savefile); ++} ++ ++ + static int + SELinuxSecurityVerify(virConnectPtr conn, virDomainDefPtr def) + { +@@ -694,4 +715,6 @@ virSecurityDriver virSELinuxSecurityDriver = { + .domainSetSecurityLabel = SELinuxSetSecurityLabel, + .domainSetSecurityHostdevLabel = SELinuxSetSecurityHostdevLabel, + .domainRestoreSecurityHostdevLabel = SELinuxRestoreSecurityHostdevLabel, ++ .domainSetSavedStateLabel = SELinuxSetSavedStateLabel, ++ .domainRestoreSavedStateLabel = SELinuxRestoreSavedStateLabel, + }; +-- +1.6.2.5 + diff --git a/libvirt.spec b/libvirt.spec index f30eb71..50cb9e8 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -151,7 +151,7 @@ Summary: Library providing a simple API virtualization Name: libvirt Version: 0.7.2 -Release: 3%{?dist}%{?extra_release} +Release: 4%{?dist}%{?extra_release} License: LGPLv2+ Group: Development/Libraries Source: http://libvirt.org/sources/libvirt-%{version}.tar.gz @@ -162,6 +162,9 @@ Patch01: libvirt-qemu-machine-type-fixes2.patch # Avoid compressing small log files (#531030) Patch02: libvirt-logrotate-avoid-compressing-small-logs.patch +# Fix QEMU save/restore permissions / labelling +Patch03: libvirt-qemu-save-restore.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root URL: http://libvirt.org/ BuildRequires: python-devel @@ -376,6 +379,7 @@ of recent versions of Linux (and other OSes). %patch01 -p1 %patch02 -p1 +%patch03 -p1 %build %if ! %{with_xen} @@ -788,6 +792,9 @@ fi %endif %changelog +* Wed Nov 11 2009 Daniel P. Berrange - 0.7.2-4 +- Fix QEMU save/restore permissions / labelling + * Thu Oct 29 2009 Mark McLoughlin - 0.7.2-3 - Avoid compressing small log files (#531030)