]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
CVE-2014-8131: Fix possible deadlock and segfault in qemuConnectGetAllDomainStats()
authorMartin Kletzander <mkletzan@redhat.com>
Thu, 27 Nov 2014 14:47:52 +0000 (15:47 +0100)
committerMartin Kletzander <mkletzan@redhat.com>
Wed, 10 Dec 2014 08:33:27 +0000 (09:33 +0100)
When user doesn't have read access on one of the domains he requested,
the for loop could exit abruptly or continue and override pointer which
pointed to locked object.

This patch fixed two issues at once.  One is that domflags might have
had QEMU_DOMAIN_STATS_HAVE_JOB even when there was no job started (this
is fixed by doing domflags |= QEMU_DOMAIN_STATS_HAVE_JOB only when the
job was acquired and cleaning domflags on every start of the loop.
Second one is that the domain is kept locked when
virConnectGetAllDomainStatsCheckACL() fails and continues the loop when
it didn't end.  Adding a simple virObjectUnlock() and clearing the
pointer ought to do.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
(cherry picked from commit 57023c0a3af4af1c547189c1f6712ed5edeb0c0b)
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
src/qemu/qemu_driver.c

index 2eaf77d0b29f7509fa891e5468674c436a8cacb8..2d0bc85cf2a57c80433bfc9c9f7c99db48898b11 100644 (file)
@@ -18514,20 +18514,23 @@ qemuConnectGetAllDomainStats(virConnectPtr conn,
         privflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
 
     for (i = 0; i < ndoms; i++) {
-        domflags = privflags;
         virDomainStatsRecordPtr tmp = NULL;
+        domflags = 0;
 
         if (!(dom = qemuDomObjFromDomain(doms[i])))
             continue;
 
         if (doms != domlist &&
-            !virConnectGetAllDomainStatsCheckACL(conn, dom->def))
+            !virConnectGetAllDomainStatsCheckACL(conn, dom->def)) {
+            virObjectUnlock(dom);
+            dom = NULL;
             continue;
+        }
 
-        if (HAVE_JOB(domflags) &&
+        if (HAVE_JOB(privflags) &&
             qemuDomainObjBeginJob(driver, dom, QEMU_JOB_QUERY) < 0)
             /* As it was never requested. Gather as much as possible anyway. */
-            domflags &= ~QEMU_DOMAIN_STATS_HAVE_JOB;
+            domflags |= QEMU_DOMAIN_STATS_HAVE_JOB;
 
         if (qemuDomainGetStats(conn, dom, stats, &tmp, domflags) < 0)
             goto endjob;
@@ -18535,9 +18538,12 @@ qemuConnectGetAllDomainStats(virConnectPtr conn,
         if (tmp)
             tmpstats[nstats++] = tmp;
 
-        if (HAVE_JOB(domflags) && !qemuDomainObjEndJob(driver, dom)) {
-            dom = NULL;
-            continue;
+        if (HAVE_JOB(domflags)) {
+            domflags = 0;
+            if (!qemuDomainObjEndJob(driver, dom)) {
+                dom = NULL;
+                continue;
+            }
         }
 
         virObjectUnlock(dom);