With this, it is now possible to create external snapshots even when SELinux is enforcing, and to protect the new file with a lock manager. * src/qemu/qemu_driver.c (qemuDomainSnapshotCreateSingleDiskActive): Create and register new file with proper permissions and locks. (qemuDomainSnapshotCreateDiskActive): Update caller. --- I ran out of time to thoroughly test this today, but wanted to at least get it posted. Once I test it, I'll post the v3 of my series. Oh, and it looks like I don't have any way to conditionally unlink() a just-created file; maybe I should revisit 42/26 to pass yet another bool * parameter that gets updated based on whether a file was created vs. a block device reused. src/qemu/qemu_driver.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c11f08e..cba5929 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -87,6 +87,7 @@ #include "configmake.h" #include "threadpool.h" #include "locking/lock_manager.h" +#include "locking/domain_lock.h" #include "virkeycode.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -8808,7 +8809,8 @@ cleanup: /* The domain is expected to hold monitor lock. */ static int -qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm, +qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver, + virDomainObjPtr vm, virDomainSnapshotDiskDefPtr snap, virDomainDiskDefPtr disk) { @@ -8817,6 +8819,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm, char *source = NULL; char *driverType = NULL; int ret = -1; + int fd = -1; + char *origsrc = NULL; + char *origdriver = NULL; if (snap->snapshot != VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL) { VIR_ERROR("unexpected code path"); @@ -8831,7 +8836,33 @@ qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm, goto cleanup; } - /* XXX create new file and set selinux labels */ + /* create the stub file and set selinux labels; manipulate disk in + * place, in a way that can be reverted on failure. */ + fd = qemuOpenFile(driver, source, NULL, NULL, false); + if (fd < 0) + goto cleanup; + VIR_FORCE_CLOSE(fd); + + origsrc = disk->src; + disk->src = source; + origdriver = disk->driverType; + disk->driverType = driverType; + + if (virDomainLockDiskAttach(driver->lockManager, vm, disk) < 0) + goto cleanup; + if (virSecurityManagerSetImageLabel(driver->securityManager, vm, + disk) < 0) { + if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0) + VIR_WARN("Unable to release lock on %s", source); + goto cleanup; + } + + disk->src = origsrc; + origsrc = NULL; + disk->driverType = driverType; + origdriver = NULL; + + /* create the actual snapshot */ ret = qemuMonitorDiskSnapshot(priv->mon, device, source); virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0); if (ret < 0) @@ -8851,6 +8882,10 @@ qemuDomainSnapshotCreateSingleDiskActive(virDomainObjPtr vm, * configuration changes awaiting the next boot? */ cleanup: + if (origsrc) { + disk->src = origsrc; + disk->driverType = driverType; + } VIR_FREE(device); VIR_FREE(source); VIR_FREE(driverType); @@ -8902,7 +8937,7 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn, if (snap->def->disks[i].snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO) continue; - ret = qemuDomainSnapshotCreateSingleDiskActive(vm, + ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm, &snap->def->disks[i], vm->def->disks[i]); if (ret < 0) -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list