|
|
fbe740 |
From bac1c96fbf2bd9d6ef728a813fda793ce1e99267 Mon Sep 17 00:00:00 2001
|
|
|
fbe740 |
Message-Id: <bac1c96fbf2bd9d6ef728a813fda793ce1e99267@dist-git>
|
|
|
fbe740 |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
fbe740 |
Date: Thu, 20 Feb 2020 10:52:27 -0600
|
|
|
fbe740 |
Subject: [PATCH] qemu: remove qemuDomainObjBegin/EndJobWithAgent()
|
|
|
fbe740 |
MIME-Version: 1.0
|
|
|
fbe740 |
Content-Type: text/plain; charset=UTF-8
|
|
|
fbe740 |
Content-Transfer-Encoding: 8bit
|
|
|
fbe740 |
|
|
|
fbe740 |
This function potentially grabs both a monitor job and an agent job at
|
|
|
fbe740 |
the same time. This is problematic because it means that a malicious (or
|
|
|
fbe740 |
just buggy) guest agent can cause a denial of service on the host. The
|
|
|
fbe740 |
presence of this function makes it easy to do the wrong thing and hold
|
|
|
fbe740 |
both jobs at the same time. All existing uses have already been removed
|
|
|
fbe740 |
by previous commits.
|
|
|
fbe740 |
|
|
|
fbe740 |
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
fbe740 |
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
fbe740 |
(cherry picked from commit 3c436c22a4f94c85c2b5e7b5fb84af48219d78e3)
|
|
|
fbe740 |
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
fbe740 |
https://bugzilla.redhat.com/show_bug.cgi?id=1759566
|
|
|
fbe740 |
Message-Id: <20200220165227.11491-6-jjongsma@redhat.com>
|
|
|
fbe740 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
fbe740 |
---
|
|
|
fbe740 |
src/qemu/THREADS.txt | 58 +++++-------------------------------------
|
|
|
fbe740 |
src/qemu/qemu_domain.c | 56 ++++------------------------------------
|
|
|
fbe740 |
src/qemu/qemu_domain.h | 7 -----
|
|
|
fbe740 |
3 files changed, 11 insertions(+), 110 deletions(-)
|
|
|
fbe740 |
|
|
|
fbe740 |
diff --git a/src/qemu/THREADS.txt b/src/qemu/THREADS.txt
|
|
|
fbe740 |
index aa428fda6a..a7d8709a43 100644
|
|
|
fbe740 |
--- a/src/qemu/THREADS.txt
|
|
|
fbe740 |
+++ b/src/qemu/THREADS.txt
|
|
|
fbe740 |
@@ -61,11 +61,12 @@ There are a number of locks on various objects
|
|
|
fbe740 |
|
|
|
fbe740 |
Agent job condition is then used when thread wishes to talk to qemu
|
|
|
fbe740 |
agent monitor. It is possible to acquire just agent job
|
|
|
fbe740 |
- (qemuDomainObjBeginAgentJob), or only normal job
|
|
|
fbe740 |
- (qemuDomainObjBeginJob) or both at the same time
|
|
|
fbe740 |
- (qemuDomainObjBeginJobWithAgent). Which type of job to grab depends
|
|
|
fbe740 |
- whether caller wishes to communicate only with agent socket, or only
|
|
|
fbe740 |
- with qemu monitor socket or both, respectively.
|
|
|
fbe740 |
+ (qemuDomainObjBeginAgentJob), or only normal job (qemuDomainObjBeginJob)
|
|
|
fbe740 |
+ but not both at the same time. Holding an agent job and a normal job would
|
|
|
fbe740 |
+ allow an unresponsive or malicious agent to block normal libvirt API and
|
|
|
fbe740 |
+ potentially result in a denial of service. Which type of job to grab
|
|
|
fbe740 |
+ depends whether caller wishes to communicate only with agent socket, or
|
|
|
fbe740 |
+ only with qemu monitor socket.
|
|
|
fbe740 |
|
|
|
fbe740 |
Immediately after acquiring the virDomainObjPtr lock, any method
|
|
|
fbe740 |
which intends to update state must acquire asynchronous, normal or
|
|
|
fbe740 |
@@ -141,18 +142,6 @@ To acquire the agent job condition
|
|
|
fbe740 |
|
|
|
fbe740 |
|
|
|
fbe740 |
|
|
|
fbe740 |
-To acquire both normal and agent job condition
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- qemuDomainObjBeginJobWithAgent()
|
|
|
fbe740 |
- - Waits until there is no normal and no agent job set
|
|
|
fbe740 |
- - Sets both job.active and job.agentActive with required job types
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- qemuDomainObjEndJobWithAgent()
|
|
|
fbe740 |
- - Sets both job.active and job.agentActive to 0
|
|
|
fbe740 |
- - Signals on job.cond condition
|
|
|
fbe740 |
-
|
|
|
fbe740 |
-
|
|
|
fbe740 |
-
|
|
|
fbe740 |
To acquire the asynchronous job condition
|
|
|
fbe740 |
|
|
|
fbe740 |
qemuDomainObjBeginAsyncJob()
|
|
|
fbe740 |
@@ -292,41 +281,6 @@ Design patterns
|
|
|
fbe740 |
virDomainObjEndAPI(&obj);
|
|
|
fbe740 |
|
|
|
fbe740 |
|
|
|
fbe740 |
- * Invoking both monitor and agent commands on a virDomainObjPtr
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- virDomainObjPtr obj;
|
|
|
fbe740 |
- qemuAgentPtr agent;
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- obj = qemuDomObjFromDomain(dom);
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- qemuDomainObjBeginJobWithAgent(obj, QEMU_JOB_TYPE, QEMU_AGENT_JOB_TYPE);
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- if (!virDomainObjIsActive(dom))
|
|
|
fbe740 |
- goto cleanup;
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- ...do prep work...
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- if (!qemuDomainAgentAvailable(obj, true))
|
|
|
fbe740 |
- goto cleanup;
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- agent = qemuDomainObjEnterAgent(obj);
|
|
|
fbe740 |
- qemuAgentXXXX(agent, ..);
|
|
|
fbe740 |
- qemuDomainObjExitAgent(obj, agent);
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- ...
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- qemuDomainObjEnterMonitor(obj);
|
|
|
fbe740 |
- qemuMonitorXXXX(priv->mon);
|
|
|
fbe740 |
- qemuDomainObjExitMonitor(obj);
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- /* Alternatively, talk to the monitor first and then talk to the agent. */
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- ...do final work...
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- qemuDomainObjEndJobWithAgent(obj);
|
|
|
fbe740 |
- virDomainObjEndAPI(&obj);
|
|
|
fbe740 |
-
|
|
|
fbe740 |
-
|
|
|
fbe740 |
* Running asynchronous job
|
|
|
fbe740 |
|
|
|
fbe740 |
virDomainObjPtr obj;
|
|
|
fbe740 |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
fbe740 |
index 0baa80582c..f037f0812e 100644
|
|
|
fbe740 |
--- a/src/qemu/qemu_domain.c
|
|
|
fbe740 |
+++ b/src/qemu/qemu_domain.c
|
|
|
fbe740 |
@@ -9734,26 +9734,6 @@ qemuDomainObjBeginAgentJob(virQEMUDriverPtr driver,
|
|
|
fbe740 |
QEMU_ASYNC_JOB_NONE, false);
|
|
|
fbe740 |
}
|
|
|
fbe740 |
|
|
|
fbe740 |
-/**
|
|
|
fbe740 |
- * qemuDomainObjBeginJobWithAgent:
|
|
|
fbe740 |
- *
|
|
|
fbe740 |
- * Grabs both monitor and agent types of job. Use if caller talks to
|
|
|
fbe740 |
- * both monitor and guest agent. However, if @job (or @agentJob) is
|
|
|
fbe740 |
- * QEMU_JOB_NONE (or QEMU_AGENT_JOB_NONE) only agent job is acquired (or
|
|
|
fbe740 |
- * monitor job).
|
|
|
fbe740 |
- *
|
|
|
fbe740 |
- * To end job call qemuDomainObjEndJobWithAgent.
|
|
|
fbe740 |
- */
|
|
|
fbe740 |
-int
|
|
|
fbe740 |
-qemuDomainObjBeginJobWithAgent(virQEMUDriverPtr driver,
|
|
|
fbe740 |
- virDomainObjPtr obj,
|
|
|
fbe740 |
- qemuDomainJob job,
|
|
|
fbe740 |
- qemuDomainAgentJob agentJob)
|
|
|
fbe740 |
-{
|
|
|
fbe740 |
- return qemuDomainObjBeginJobInternal(driver, obj, job, agentJob,
|
|
|
fbe740 |
- QEMU_ASYNC_JOB_NONE, false);
|
|
|
fbe740 |
-}
|
|
|
fbe740 |
-
|
|
|
fbe740 |
int qemuDomainObjBeginAsyncJob(virQEMUDriverPtr driver,
|
|
|
fbe740 |
virDomainObjPtr obj,
|
|
|
fbe740 |
qemuDomainAsyncJob asyncJob,
|
|
|
fbe740 |
@@ -9868,31 +9848,6 @@ qemuDomainObjEndAgentJob(virDomainObjPtr obj)
|
|
|
fbe740 |
virCondBroadcast(&priv->job.cond);
|
|
|
fbe740 |
}
|
|
|
fbe740 |
|
|
|
fbe740 |
-void
|
|
|
fbe740 |
-qemuDomainObjEndJobWithAgent(virQEMUDriverPtr driver,
|
|
|
fbe740 |
- virDomainObjPtr obj)
|
|
|
fbe740 |
-{
|
|
|
fbe740 |
- qemuDomainObjPrivatePtr priv = obj->privateData;
|
|
|
fbe740 |
- qemuDomainJob job = priv->job.active;
|
|
|
fbe740 |
- qemuDomainAgentJob agentJob = priv->job.agentActive;
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- priv->jobs_queued--;
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- VIR_DEBUG("Stopping both jobs: %s %s (async=%s vm=%p name=%s)",
|
|
|
fbe740 |
- qemuDomainJobTypeToString(job),
|
|
|
fbe740 |
- qemuDomainAgentJobTypeToString(agentJob),
|
|
|
fbe740 |
- qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
|
|
|
fbe740 |
- obj, obj->def->name);
|
|
|
fbe740 |
-
|
|
|
fbe740 |
- qemuDomainObjResetJob(priv);
|
|
|
fbe740 |
- qemuDomainObjResetAgentJob(priv);
|
|
|
fbe740 |
- if (qemuDomainTrackJob(job))
|
|
|
fbe740 |
- qemuDomainObjSaveStatus(driver, obj);
|
|
|
fbe740 |
- /* We indeed need to wake up ALL threads waiting because
|
|
|
fbe740 |
- * grabbing a job requires checking more variables. */
|
|
|
fbe740 |
- virCondBroadcast(&priv->job.cond);
|
|
|
fbe740 |
-}
|
|
|
fbe740 |
-
|
|
|
fbe740 |
void
|
|
|
fbe740 |
qemuDomainObjEndAsyncJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
|
|
|
fbe740 |
{
|
|
|
fbe740 |
@@ -9926,9 +9881,9 @@ qemuDomainObjAbortAsyncJob(virDomainObjPtr obj)
|
|
|
fbe740 |
* obj must be locked before calling
|
|
|
fbe740 |
*
|
|
|
fbe740 |
* To be called immediately before any QEMU monitor API call
|
|
|
fbe740 |
- * Must have already either called qemuDomainObjBeginJob() or
|
|
|
fbe740 |
- * qemuDomainObjBeginJobWithAgent() and checked that the VM is
|
|
|
fbe740 |
- * still active; may not be used for nested async jobs.
|
|
|
fbe740 |
+ * Must have already called qemuDomainObjBeginJob() and checked
|
|
|
fbe740 |
+ * that the VM is still active; may not be used for nested async
|
|
|
fbe740 |
+ * jobs.
|
|
|
fbe740 |
*
|
|
|
fbe740 |
* To be followed with qemuDomainObjExitMonitor() once complete
|
|
|
fbe740 |
*/
|
|
|
fbe740 |
@@ -10050,9 +10005,8 @@ qemuDomainObjEnterMonitorAsync(virQEMUDriverPtr driver,
|
|
|
fbe740 |
* obj must be locked before calling
|
|
|
fbe740 |
*
|
|
|
fbe740 |
* To be called immediately before any QEMU agent API call.
|
|
|
fbe740 |
- * Must have already called qemuDomainObjBeginAgentJob() or
|
|
|
fbe740 |
- * qemuDomainObjBeginJobWithAgent() and checked that the VM is
|
|
|
fbe740 |
- * still active.
|
|
|
fbe740 |
+ * Must have already called qemuDomainObjBeginAgentJob() and
|
|
|
fbe740 |
+ * checked that the VM is still active.
|
|
|
fbe740 |
*
|
|
|
fbe740 |
* To be followed with qemuDomainObjExitAgent() once complete
|
|
|
fbe740 |
*/
|
|
|
fbe740 |
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
|
fbe740 |
index cdcb6ecc7a..c581b3a162 100644
|
|
|
fbe740 |
--- a/src/qemu/qemu_domain.h
|
|
|
fbe740 |
+++ b/src/qemu/qemu_domain.h
|
|
|
fbe740 |
@@ -651,11 +651,6 @@ int qemuDomainObjBeginAgentJob(virQEMUDriverPtr driver,
|
|
|
fbe740 |
virDomainObjPtr obj,
|
|
|
fbe740 |
qemuDomainAgentJob agentJob)
|
|
|
fbe740 |
G_GNUC_WARN_UNUSED_RESULT;
|
|
|
fbe740 |
-int qemuDomainObjBeginJobWithAgent(virQEMUDriverPtr driver,
|
|
|
fbe740 |
- virDomainObjPtr obj,
|
|
|
fbe740 |
- qemuDomainJob job,
|
|
|
fbe740 |
- qemuDomainAgentJob agentJob)
|
|
|
fbe740 |
- G_GNUC_WARN_UNUSED_RESULT;
|
|
|
fbe740 |
int qemuDomainObjBeginAsyncJob(virQEMUDriverPtr driver,
|
|
|
fbe740 |
virDomainObjPtr obj,
|
|
|
fbe740 |
qemuDomainAsyncJob asyncJob,
|
|
|
fbe740 |
@@ -674,8 +669,6 @@ int qemuDomainObjBeginJobNowait(virQEMUDriverPtr driver,
|
|
|
fbe740 |
void qemuDomainObjEndJob(virQEMUDriverPtr driver,
|
|
|
fbe740 |
virDomainObjPtr obj);
|
|
|
fbe740 |
void qemuDomainObjEndAgentJob(virDomainObjPtr obj);
|
|
|
fbe740 |
-void qemuDomainObjEndJobWithAgent(virQEMUDriverPtr driver,
|
|
|
fbe740 |
- virDomainObjPtr obj);
|
|
|
fbe740 |
void qemuDomainObjEndAsyncJob(virQEMUDriverPtr driver,
|
|
|
fbe740 |
virDomainObjPtr obj);
|
|
|
fbe740 |
void qemuDomainObjAbortAsyncJob(virDomainObjPtr obj);
|
|
|
fbe740 |
--
|
|
|
fbe740 |
2.25.0
|
|
|
fbe740 |
|