[libvirt] [PATCHv5 14/23] blockjob: allow mirroring under SELinux

Eric Blake eblake at redhat.com
Tue Apr 17 05:06:05 UTC 2012


This copies heavily from qemuDomainSnapshotCreateSingleDiskActive(),
in order to set the SELinux label, obtain locking manager lease, and
audit the fact that we hand a new file over to qemu.  Alas, releasing
the lease and label on failure or at the end of the mirroring is a
trickier prospect (we would have to know the backing chain of both
source and destination, and be sure not to revoke rights to any part
of the chain that is shared), so for now, virDomainBlockJobAbort
still leaves things locked and labeled.

* src/qemu/qemu_driver.c (qemuDomainBlockCopy): Set up labeling.
---

was 14/18 in v4
v5: remove label on failure of 'drive-mirror'

 src/qemu/qemu_driver.c |   69 +++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3e8418b..f197627 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11931,6 +11931,11 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
     int ret = -1;
     int idx;
     struct stat st;
+    bool need_unlink = false;
+    char *mirror = NULL;
+    char *mirrorFormat = NULL;
+    char *origsrc = NULL;
+    char *origdriver = NULL;

     /* Preliminaries: find the disk we are editing, sanity checks */
     virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
@@ -12017,19 +12022,41 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
         goto endjob;
     }

-    /* XXX We also need to add security labeling, lock manager lease,
-     * and auditing of those events.  */
-    if (!format && !(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT))
-        format = disk->driverType;
-    if ((format && !(disk->mirrorFormat = strdup(format))) ||
-        !(disk->mirror = strdup(dest))) {
+    if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
+        int fd = qemuOpenFile(driver, dest, O_WRONLY | O_TRUNC | O_CREAT,
+                              &need_unlink, NULL);
+        if (fd < 0)
+            goto endjob;
+        VIR_FORCE_CLOSE(fd);
+        if (!format)
+            format = disk->driverType;
+    }
+    if ((format && !(mirrorFormat = strdup(format))) ||
+        !(mirror = strdup(dest))) {
         virReportOOMError();
         goto endjob;
     }

+    /* Manipulate disk in place, in a way that can be reverted on
+     * failure, in order to set up labeling and locking.  */
+    origsrc = disk->src;
+    disk->src = (char *) dest;
+    origdriver = disk->driverType;
+    disk->driverType = (char *) "raw"; /* Don't want to probe backing files */
+
+    if (virDomainLockDiskAttach(driver->lockManager, vm, disk) < 0)
+        goto endjob;
+    if (virSecurityManagerSetImageLabel(driver->securityManager, vm->def,
+                                        disk) < 0) {
+        if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
+            VIR_WARN("Unable to release lock on %s", dest);
+        goto endjob;
+    }
+
     /* Actually start the mirroring */
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorDriveMirror(priv->mon, device, dest, format, flags);
+    virDomainAuditDisk(vm, NULL, dest, "mirror", ret >= 0);
     if (ret == 0 && bandwidth != 0) {
         /* Setting speed now is best-effort.  */
         if (qemuMonitorBlockJob(priv->mon, device, NULL, bandwidth, NULL,
@@ -12037,12 +12064,36 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path,
             VIR_WARN("failed to set bandwidth for disk %s", disk->dst);
     }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
+    if (ret < 0) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm->def, disk) < 0)
+            VIR_WARN("Unable to restore security label on %s", dest);
+        if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
+            VIR_WARN("Unable to release lock on %s", dest);
+        goto endjob;
+    }
+
+    disk->src = origsrc;
+    origsrc = NULL;
+    disk->driverType = origdriver;
+    origdriver = NULL;
+
+    /* Update vm in place to match changes.  */
+    need_unlink = false;
+    disk->mirror = mirror;
+    disk->mirrorFormat = mirrorFormat;
+    mirror = NULL;
+    mirrorFormat = NULL;

 endjob:
-    if (ret < 0) {
-        VIR_FREE(disk->mirror);
-        VIR_FREE(disk->mirrorFormat);
+    if (origsrc) {
+        disk->src = origsrc;
+        disk->driverType = origdriver;
     }
+    if (need_unlink && unlink(dest))
+        VIR_WARN("unable to unlink just-created %s", dest);
+    VIR_FREE(mirror);
+    VIR_FREE(mirrorFormat);
     if (qemuDomainObjEndJob(driver, vm) == 0) {
         vm = NULL;
         goto cleanup;
-- 
1.7.7.6




More information about the libvir-list mailing list