|
|
9f9eae |
From 9617e31b5349b193469874706abcbcb013e6a6fd Mon Sep 17 00:00:00 2001
|
|
|
9f9eae |
Message-Id: <9617e31b5349b193469874706abcbcb013e6a6fd.1407860168.git.crobinso@redhat.com>
|
|
|
9f9eae |
In-Reply-To: <2151695a5119a8d7f44d416c730df50a1e42695a.1407860168.git.crobinso@redhat.com>
|
|
|
9f9eae |
References: <2151695a5119a8d7f44d416c730df50a1e42695a.1407860168.git.crobinso@redhat.com>
|
|
|
9f9eae |
From: Eric Blake <eblake@redhat.com>
|
|
|
9f9eae |
Date: Wed, 6 Aug 2014 14:06:23 -0600
|
|
|
9f9eae |
Subject: [PATCH 3/3] blockjob: fix use-after-free in blockcopy
|
|
|
9f9eae |
|
|
|
9f9eae |
Commit febf84c2 tried to delay in-memory modification of the actual
|
|
|
9f9eae |
domain disk structure until after the qemu event was received.
|
|
|
9f9eae |
However, I missed that the code for block pivot had been temporarily
|
|
|
9f9eae |
setting disk->src = disk->mirror prior to the qemu command, in order
|
|
|
9f9eae |
to label the backing chain of a reused external blockcopy disk;
|
|
|
9f9eae |
and calls into qemu while still in that state before finally undoing
|
|
|
9f9eae |
things at the cleanup label. Since the qemu event handler then does:
|
|
|
9f9eae |
virStorageSourceFree(disk->src);
|
|
|
9f9eae |
disk->src = disk->mirror;
|
|
|
9f9eae |
we have the sad race that a fast enough qemu event can cause a leak of
|
|
|
9f9eae |
the original disk->src, as well as a use-after-free of the disk->mirror
|
|
|
9f9eae |
contents, bad enough to crash libvirtd in some of my test runs, even
|
|
|
9f9eae |
though the common case of the qemu event being much later won't trip
|
|
|
9f9eae |
the race.
|
|
|
9f9eae |
|
|
|
9f9eae |
I'll go wear the brown paper bag of shame, for introducing a crasher
|
|
|
9f9eae |
in between rc1 and rc2 of the freeze for 1.2.7 :( My only
|
|
|
9f9eae |
consolation is that virDomainBlockJobAbort requires the domain:write
|
|
|
9f9eae |
ACL, so it is not a CVE.
|
|
|
9f9eae |
|
|
|
9f9eae |
The valgrind report when the race occurs looks like:
|
|
|
9f9eae |
|
|
|
9f9eae |
==25612== Invalid read of size 4
|
|
|
9f9eae |
==25612== at 0x50E7C90: virStorageSourceGetActualType (virstoragefile.c:1948)
|
|
|
9f9eae |
==25612== by 0x209C0B18: qemuDomainDetermineDiskChain (qemu_domain.c:2473)
|
|
|
9f9eae |
==25612== by 0x209D7F6A: qemuProcessHandleBlockJob (qemu_process.c:1087)
|
|
|
9f9eae |
==25612== by 0x209F40C9: qemuMonitorEmitBlockJob (qemu_monitor.c:1357)
|
|
|
9f9eae |
...
|
|
|
9f9eae |
==25612== Address 0xe4b5610 is 0 bytes inside a block of size 200 free'd
|
|
|
9f9eae |
==25612== at 0x4A07577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
|
|
|
9f9eae |
==25612== by 0x50839E9: virFree (viralloc.c:582)
|
|
|
9f9eae |
==25612== by 0x50E7E51: virStorageSourceFree (virstoragefile.c:2015)
|
|
|
9f9eae |
==25612== by 0x209D7EFF: qemuProcessHandleBlockJob (qemu_process.c:1073)
|
|
|
9f9eae |
==25612== by 0x209F40C9: qemuMonitorEmitBlockJob (qemu_monitor.c:1357)
|
|
|
9f9eae |
|
|
|
9f9eae |
* src/qemu/qemu_driver.c (qemuDomainBlockPivot): Don't corrupt
|
|
|
9f9eae |
disk->src, and only label chain for blockcopy.
|
|
|
9f9eae |
|
|
|
9f9eae |
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
|
9f9eae |
(cherry picked from commit 265680c58ebbee30bb70369e7d9905a599afbd6a)
|
|
|
9f9eae |
---
|
|
|
9f9eae |
src/qemu/qemu_driver.c | 40 +++++++++++++++++++++++++---------------
|
|
|
9f9eae |
1 file changed, 25 insertions(+), 15 deletions(-)
|
|
|
9f9eae |
|
|
|
9f9eae |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
9f9eae |
index 57cc913..a050dbc 100644
|
|
|
9f9eae |
--- a/src/qemu/qemu_driver.c
|
|
|
9f9eae |
+++ b/src/qemu/qemu_driver.c
|
|
|
9f9eae |
@@ -14888,23 +14888,33 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|
|
9f9eae |
}
|
|
|
9f9eae |
}
|
|
|
9f9eae |
|
|
|
9f9eae |
- /* We previously labeled only the top-level image; but if the
|
|
|
9f9eae |
- * image includes a relative backing file, the pivot may result in
|
|
|
9f9eae |
- * qemu needing to open the entire backing chain, so we need to
|
|
|
9f9eae |
- * label the entire chain. This action is safe even if the
|
|
|
9f9eae |
- * backing chain has already been labeled; but only necessary when
|
|
|
9f9eae |
- * we know for sure that there is a backing chain. */
|
|
|
9f9eae |
- oldsrc = disk->src;
|
|
|
9f9eae |
- disk->src = disk->mirror;
|
|
|
9f9eae |
+ /* For active commit, the mirror is part of the already labeled
|
|
|
9f9eae |
+ * chain. For blockcopy, we previously labeled only the top-level
|
|
|
9f9eae |
+ * image; but if the user is reusing an external image that
|
|
|
9f9eae |
+ * includes a backing file, the pivot may result in qemu needing
|
|
|
9f9eae |
+ * to open the entire backing chain, so we need to label the
|
|
|
9f9eae |
+ * entire chain. This action is safe even if the backing chain
|
|
|
9f9eae |
+ * has already been labeled; but only necessary when we know for
|
|
|
9f9eae |
+ * sure that there is a backing chain. */
|
|
|
9f9eae |
+ if (disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
|
|
|
9f9eae |
+ oldsrc = disk->src;
|
|
|
9f9eae |
+ disk->src = disk->mirror;
|
|
|
9f9eae |
+
|
|
|
9f9eae |
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
|
|
|
9f9eae |
+ goto cleanup;
|
|
|
9f9eae |
|
|
|
9f9eae |
- if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
|
|
|
9f9eae |
- goto cleanup;
|
|
|
9f9eae |
+ if (disk->mirror->format &&
|
|
|
9f9eae |
+ disk->mirror->format != VIR_STORAGE_FILE_RAW &&
|
|
|
9f9eae |
+ (virDomainLockDiskAttach(driver->lockManager, cfg->uri, vm,
|
|
|
9f9eae |
+ disk) < 0 ||
|
|
|
9f9eae |
+ qemuSetupDiskCgroup(vm, disk) < 0 ||
|
|
|
9f9eae |
+ virSecurityManagerSetDiskLabel(driver->securityManager, vm->def,
|
|
|
9f9eae |
+ disk) < 0))
|
|
|
9f9eae |
+ goto cleanup;
|
|
|
9f9eae |
|
|
|
9f9eae |
- if (disk->mirror->format && disk->mirror->format != VIR_STORAGE_FILE_RAW &&
|
|
|
9f9eae |
- (virDomainLockDiskAttach(driver->lockManager, cfg->uri, vm, disk) < 0 ||
|
|
|
9f9eae |
- qemuSetupDiskCgroup(vm, disk) < 0 ||
|
|
|
9f9eae |
- virSecurityManagerSetDiskLabel(driver->securityManager, vm->def, disk) < 0))
|
|
|
9f9eae |
- goto cleanup;
|
|
|
9f9eae |
+ disk->src = oldsrc;
|
|
|
9f9eae |
+ oldsrc = NULL;
|
|
|
9f9eae |
+ }
|
|
|
9f9eae |
|
|
|
9f9eae |
/* Attempt the pivot. Record the attempt now, to prevent duplicate
|
|
|
9f9eae |
* attempts; but the actual disk change will be made when emitting
|
|
|
9f9eae |
--
|
|
|
9f9eae |
1.9.3
|
|
|
9f9eae |
|