From 410c5b18640b585a2cd6b56c40b8e8c75355725c Mon Sep 17 00:00:00 2001 Message-Id: <410c5b18640b585a2cd6b56c40b8e8c75355725c@dist-git> From: Martin Kletzander Date: Sat, 13 Dec 2014 10:10:01 +0100 Subject: [PATCH] CVE-2014-8131: Fix possible deadlock and segfault in qemuConnectGetAllDomainStats() https://bugzilla.redhat.com/show_bug.cgi?id=1172570 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 (cherry picked from commit 57023c0a3af4af1c547189c1f6712ed5edeb0c0b) Signed-off-by: Martin Kletzander Signed-off-by: Jiri Denemark --- src/qemu/qemu_driver.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index adf158a..1625ddd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18250,20 +18250,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; @@ -18271,9 +18274,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); -- 2.2.0