|
|
03cc27 |
From ff8c9ca6d8b5e74d59013d063cc12323622d8fb1 Mon Sep 17 00:00:00 2001
|
|
|
03cc27 |
Message-Id: <ff8c9ca6d8b5e74d59013d063cc12323622d8fb1@dist-git>
|
|
|
03cc27 |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
03cc27 |
Date: Fri, 1 May 2020 16:53:41 -0500
|
|
|
03cc27 |
Subject: [PATCH] qemu: remove qemuDomainObjBegin/EndJobWithAgent()
|
|
|
03cc27 |
|
|
|
03cc27 |
This function potentially grabs both a monitor job and an agent job at
|
|
|
03cc27 |
the same time. This is problematic because it means that a malicious (or
|
|
|
03cc27 |
just buggy) guest agent can cause a denial of service on the host. The
|
|
|
03cc27 |
presence of this function makes it easy to do the wrong thing and hold
|
|
|
03cc27 |
both jobs at the same time. All existing uses have already been removed
|
|
|
03cc27 |
by previous commits.
|
|
|
03cc27 |
|
|
|
03cc27 |
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
03cc27 |
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
03cc27 |
(cherry picked from commit 3c436c22a4f94c85c2b5e7b5fb84af48219d78e3)
|
|
|
03cc27 |
|
|
|
03cc27 |
CVE-2019-20485
|
|
|
03cc27 |
|
|
|
03cc27 |
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
03cc27 |
Message-Id: <20200501215341.27683-6-jjongsma@redhat.com>
|
|
|
03cc27 |
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
03cc27 |
---
|
|
|
03cc27 |
src/qemu/THREADS.txt | 58 +++++-------------------------------------
|
|
|
03cc27 |
src/qemu/qemu_domain.c | 56 ++++------------------------------------
|
|
|
03cc27 |
src/qemu/qemu_domain.h | 7 -----
|
|
|
03cc27 |
3 files changed, 11 insertions(+), 110 deletions(-)
|
|
|
03cc27 |
|
|
|
03cc27 |
diff --git a/src/qemu/THREADS.txt b/src/qemu/THREADS.txt
|
|
|
03cc27 |
index d17f3f4e0c..b34235075a 100644
|
|
|
03cc27 |
--- a/src/qemu/THREADS.txt
|
|
|
03cc27 |
+++ b/src/qemu/THREADS.txt
|
|
|
03cc27 |
@@ -71,11 +71,12 @@ There are a number of locks on various objects
|
|
|
03cc27 |
|
|
|
03cc27 |
Agent job condition is then used when thread wishes to talk to qemu
|
|
|
03cc27 |
agent monitor. It is possible to acquire just agent job
|
|
|
03cc27 |
- (qemuDomainObjBeginAgentJob), or only normal job
|
|
|
03cc27 |
- (qemuDomainObjBeginJob) or both at the same time
|
|
|
03cc27 |
- (qemuDomainObjBeginJobWithAgent). Which type of job to grab depends
|
|
|
03cc27 |
- whether caller wishes to communicate only with agent socket, or only
|
|
|
03cc27 |
- with qemu monitor socket or both, respectively.
|
|
|
03cc27 |
+ (qemuDomainObjBeginAgentJob), or only normal job (qemuDomainObjBeginJob)
|
|
|
03cc27 |
+ but not both at the same time. Holding an agent job and a normal job would
|
|
|
03cc27 |
+ allow an unresponsive or malicious agent to block normal libvirt API and
|
|
|
03cc27 |
+ potentially result in a denial of service. Which type of job to grab
|
|
|
03cc27 |
+ depends whether caller wishes to communicate only with agent socket, or
|
|
|
03cc27 |
+ only with qemu monitor socket.
|
|
|
03cc27 |
|
|
|
03cc27 |
Immediately after acquiring the virDomainObjPtr lock, any method
|
|
|
03cc27 |
which intends to update state must acquire asynchronous, normal or
|
|
|
03cc27 |
@@ -151,18 +152,6 @@ To acquire the agent job condition
|
|
|
03cc27 |
|
|
|
03cc27 |
|
|
|
03cc27 |
|
|
|
03cc27 |
-To acquire both normal and agent job condition
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- qemuDomainObjBeginJobWithAgent()
|
|
|
03cc27 |
- - Waits until there is no normal and no agent job set
|
|
|
03cc27 |
- - Sets both job.active and job.agentActive with required job types
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- qemuDomainObjEndJobWithAgent()
|
|
|
03cc27 |
- - Sets both job.active and job.agentActive to 0
|
|
|
03cc27 |
- - Signals on job.cond condition
|
|
|
03cc27 |
-
|
|
|
03cc27 |
-
|
|
|
03cc27 |
-
|
|
|
03cc27 |
To acquire the asynchronous job condition
|
|
|
03cc27 |
|
|
|
03cc27 |
qemuDomainObjBeginAsyncJob()
|
|
|
03cc27 |
@@ -302,41 +291,6 @@ Design patterns
|
|
|
03cc27 |
virDomainObjEndAPI(&obj);
|
|
|
03cc27 |
|
|
|
03cc27 |
|
|
|
03cc27 |
- * Invoking both monitor and agent commands on a virDomainObjPtr
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- virDomainObjPtr obj;
|
|
|
03cc27 |
- qemuAgentPtr agent;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- obj = qemuDomObjFromDomain(dom);
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- qemuDomainObjBeginJobWithAgent(obj, QEMU_JOB_TYPE, QEMU_AGENT_JOB_TYPE);
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- if (!virDomainObjIsActive(dom))
|
|
|
03cc27 |
- goto cleanup;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- ...do prep work...
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- if (!qemuDomainAgentAvailable(obj, true))
|
|
|
03cc27 |
- goto cleanup;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- agent = qemuDomainObjEnterAgent(obj);
|
|
|
03cc27 |
- qemuAgentXXXX(agent, ..);
|
|
|
03cc27 |
- qemuDomainObjExitAgent(obj, agent);
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- ...
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- qemuDomainObjEnterMonitor(obj);
|
|
|
03cc27 |
- qemuMonitorXXXX(priv->mon);
|
|
|
03cc27 |
- qemuDomainObjExitMonitor(obj);
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- /* Alternatively, talk to the monitor first and then talk to the agent. */
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- ...do final work...
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- qemuDomainObjEndJobWithAgent(obj);
|
|
|
03cc27 |
- virDomainObjEndAPI(&obj);
|
|
|
03cc27 |
-
|
|
|
03cc27 |
-
|
|
|
03cc27 |
* Running asynchronous job
|
|
|
03cc27 |
|
|
|
03cc27 |
virDomainObjPtr obj;
|
|
|
03cc27 |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
03cc27 |
index 3c67769771..b4792c9476 100644
|
|
|
03cc27 |
--- a/src/qemu/qemu_domain.c
|
|
|
03cc27 |
+++ b/src/qemu/qemu_domain.c
|
|
|
03cc27 |
@@ -6905,26 +6905,6 @@ qemuDomainObjBeginAgentJob(virQEMUDriverPtr driver,
|
|
|
03cc27 |
QEMU_ASYNC_JOB_NONE, false);
|
|
|
03cc27 |
}
|
|
|
03cc27 |
|
|
|
03cc27 |
-/**
|
|
|
03cc27 |
- * qemuDomainObjBeginJobWithAgent:
|
|
|
03cc27 |
- *
|
|
|
03cc27 |
- * Grabs both monitor and agent types of job. Use if caller talks to
|
|
|
03cc27 |
- * both monitor and guest agent. However, if @job (or @agentJob) is
|
|
|
03cc27 |
- * QEMU_JOB_NONE (or QEMU_AGENT_JOB_NONE) only agent job is acquired (or
|
|
|
03cc27 |
- * monitor job).
|
|
|
03cc27 |
- *
|
|
|
03cc27 |
- * To end job call qemuDomainObjEndJobWithAgent.
|
|
|
03cc27 |
- */
|
|
|
03cc27 |
-int
|
|
|
03cc27 |
-qemuDomainObjBeginJobWithAgent(virQEMUDriverPtr driver,
|
|
|
03cc27 |
- virDomainObjPtr obj,
|
|
|
03cc27 |
- qemuDomainJob job,
|
|
|
03cc27 |
- qemuDomainAgentJob agentJob)
|
|
|
03cc27 |
-{
|
|
|
03cc27 |
- return qemuDomainObjBeginJobInternal(driver, obj, job, agentJob,
|
|
|
03cc27 |
- QEMU_ASYNC_JOB_NONE, false);
|
|
|
03cc27 |
-}
|
|
|
03cc27 |
-
|
|
|
03cc27 |
int qemuDomainObjBeginAsyncJob(virQEMUDriverPtr driver,
|
|
|
03cc27 |
virDomainObjPtr obj,
|
|
|
03cc27 |
qemuDomainAsyncJob asyncJob,
|
|
|
03cc27 |
@@ -7039,31 +7019,6 @@ qemuDomainObjEndAgentJob(virDomainObjPtr obj)
|
|
|
03cc27 |
virCondBroadcast(&priv->job.cond);
|
|
|
03cc27 |
}
|
|
|
03cc27 |
|
|
|
03cc27 |
-void
|
|
|
03cc27 |
-qemuDomainObjEndJobWithAgent(virQEMUDriverPtr driver,
|
|
|
03cc27 |
- virDomainObjPtr obj)
|
|
|
03cc27 |
-{
|
|
|
03cc27 |
- qemuDomainObjPrivatePtr priv = obj->privateData;
|
|
|
03cc27 |
- qemuDomainJob job = priv->job.active;
|
|
|
03cc27 |
- qemuDomainAgentJob agentJob = priv->job.agentActive;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- priv->jobs_queued--;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- VIR_DEBUG("Stopping both jobs: %s %s (async=%s vm=%p name=%s)",
|
|
|
03cc27 |
- qemuDomainJobTypeToString(job),
|
|
|
03cc27 |
- qemuDomainAgentJobTypeToString(agentJob),
|
|
|
03cc27 |
- qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
|
|
|
03cc27 |
- obj, obj->def->name);
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- qemuDomainObjResetJob(priv);
|
|
|
03cc27 |
- qemuDomainObjResetAgentJob(priv);
|
|
|
03cc27 |
- if (qemuDomainTrackJob(job))
|
|
|
03cc27 |
- qemuDomainObjSaveJob(driver, obj);
|
|
|
03cc27 |
- /* We indeed need to wake up ALL threads waiting because
|
|
|
03cc27 |
- * grabbing a job requires checking more variables. */
|
|
|
03cc27 |
- virCondBroadcast(&priv->job.cond);
|
|
|
03cc27 |
-}
|
|
|
03cc27 |
-
|
|
|
03cc27 |
void
|
|
|
03cc27 |
qemuDomainObjEndAsyncJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
|
|
|
03cc27 |
{
|
|
|
03cc27 |
@@ -7097,9 +7052,9 @@ qemuDomainObjAbortAsyncJob(virDomainObjPtr obj)
|
|
|
03cc27 |
* obj must be locked before calling
|
|
|
03cc27 |
*
|
|
|
03cc27 |
* To be called immediately before any QEMU monitor API call
|
|
|
03cc27 |
- * Must have already either called qemuDomainObjBeginJob() or
|
|
|
03cc27 |
- * qemuDomainObjBeginJobWithAgent() and checked that the VM is
|
|
|
03cc27 |
- * still active; may not be used for nested async jobs.
|
|
|
03cc27 |
+ * Must have already called qemuDomainObjBeginJob() and checked
|
|
|
03cc27 |
+ * that the VM is still active; may not be used for nested async
|
|
|
03cc27 |
+ * jobs.
|
|
|
03cc27 |
*
|
|
|
03cc27 |
* To be followed with qemuDomainObjExitMonitor() once complete
|
|
|
03cc27 |
*/
|
|
|
03cc27 |
@@ -7216,9 +7171,8 @@ qemuDomainObjEnterMonitorAsync(virQEMUDriverPtr driver,
|
|
|
03cc27 |
* obj must be locked before calling
|
|
|
03cc27 |
*
|
|
|
03cc27 |
* To be called immediately before any QEMU agent API call.
|
|
|
03cc27 |
- * Must have already called qemuDomainObjBeginAgentJob() or
|
|
|
03cc27 |
- * qemuDomainObjBeginJobWithAgent() and checked that the VM is
|
|
|
03cc27 |
- * still active.
|
|
|
03cc27 |
+ * Must have already called qemuDomainObjBeginAgentJob() and
|
|
|
03cc27 |
+ * checked that the VM is still active.
|
|
|
03cc27 |
*
|
|
|
03cc27 |
* To be followed with qemuDomainObjExitAgent() once complete
|
|
|
03cc27 |
*/
|
|
|
03cc27 |
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
|
03cc27 |
index daed69e856..e4cc65c4cc 100644
|
|
|
03cc27 |
--- a/src/qemu/qemu_domain.h
|
|
|
03cc27 |
+++ b/src/qemu/qemu_domain.h
|
|
|
03cc27 |
@@ -527,11 +527,6 @@ int qemuDomainObjBeginAgentJob(virQEMUDriverPtr driver,
|
|
|
03cc27 |
virDomainObjPtr obj,
|
|
|
03cc27 |
qemuDomainAgentJob agentJob)
|
|
|
03cc27 |
ATTRIBUTE_RETURN_CHECK;
|
|
|
03cc27 |
-int qemuDomainObjBeginJobWithAgent(virQEMUDriverPtr driver,
|
|
|
03cc27 |
- virDomainObjPtr obj,
|
|
|
03cc27 |
- qemuDomainJob job,
|
|
|
03cc27 |
- qemuDomainAgentJob agentJob)
|
|
|
03cc27 |
- ATTRIBUTE_RETURN_CHECK;
|
|
|
03cc27 |
int qemuDomainObjBeginAsyncJob(virQEMUDriverPtr driver,
|
|
|
03cc27 |
virDomainObjPtr obj,
|
|
|
03cc27 |
qemuDomainAsyncJob asyncJob,
|
|
|
03cc27 |
@@ -550,8 +545,6 @@ int qemuDomainObjBeginJobNowait(virQEMUDriverPtr driver,
|
|
|
03cc27 |
void qemuDomainObjEndJob(virQEMUDriverPtr driver,
|
|
|
03cc27 |
virDomainObjPtr obj);
|
|
|
03cc27 |
void qemuDomainObjEndAgentJob(virDomainObjPtr obj);
|
|
|
03cc27 |
-void qemuDomainObjEndJobWithAgent(virQEMUDriverPtr driver,
|
|
|
03cc27 |
- virDomainObjPtr obj);
|
|
|
03cc27 |
void qemuDomainObjEndAsyncJob(virQEMUDriverPtr driver,
|
|
|
03cc27 |
virDomainObjPtr obj);
|
|
|
03cc27 |
void qemuDomainObjAbortAsyncJob(virDomainObjPtr obj);
|
|
|
03cc27 |
--
|
|
|
03cc27 |
2.26.2
|
|
|
03cc27 |
|