render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
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