render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
03cc27
From b54ac47536056f26c724c7997e2aa96009b79ebd Mon Sep 17 00:00:00 2001
03cc27
Message-Id: <b54ac47536056f26c724c7997e2aa96009b79ebd@dist-git>
03cc27
From: Jonathon Jongsma <jjongsma@redhat.com>
03cc27
Date: Fri, 1 May 2020 16:53:38 -0500
03cc27
Subject: [PATCH] qemu: don't hold a monitor and agent job for reboot
03cc27
03cc27
We have to assume that the guest agent may be malicious so we don't want
03cc27
to allow any agent queries to block any other libvirt API. By holding
03cc27
a monitor job while we're querying the agent, we open ourselves up to a
03cc27
DoS.
03cc27
03cc27
Split the function so that we only hold the appropriate type of job
03cc27
while rebooting.
03cc27
03cc27
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
03cc27
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
03cc27
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
03cc27
(cherry picked from commit 0a9893121187c0c3f9807e9164366e1f6977619c)
03cc27
03cc27
CVE-2019-20485
03cc27
03cc27
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
03cc27
Message-Id: <20200501215341.27683-3-jjongsma@redhat.com>
03cc27
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
03cc27
---
03cc27
 src/qemu/qemu_driver.c | 112 +++++++++++++++++++++++++----------------
03cc27
 1 file changed, 70 insertions(+), 42 deletions(-)
03cc27
03cc27
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
03cc27
index bdc955e1fa..888c586a79 100644
03cc27
--- a/src/qemu/qemu_driver.c
03cc27
+++ b/src/qemu/qemu_driver.c
03cc27
@@ -2049,6 +2049,72 @@ static int qemuDomainShutdown(virDomainPtr dom)
03cc27
 }
03cc27
 
03cc27
 
03cc27
+static int
03cc27
+qemuDomainRebootAgent(virQEMUDriverPtr driver,
03cc27
+                      virDomainObjPtr vm,
03cc27
+                      bool isReboot,
03cc27
+                      bool agentForced)
03cc27
+{
03cc27
+    qemuAgentPtr agent;
03cc27
+    int ret = -1;
03cc27
+    int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
03cc27
+
03cc27
+    if (!isReboot)
03cc27
+        agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
03cc27
+
03cc27
+    if (qemuDomainObjBeginAgentJob(driver, vm,
03cc27
+                                   QEMU_AGENT_JOB_MODIFY) < 0)
03cc27
+        return -1;
03cc27
+
03cc27
+    if (!qemuDomainAgentAvailable(vm, agentForced))
03cc27
+        goto endjob;
03cc27
+
03cc27
+    if (virDomainObjCheckActive(vm) < 0)
03cc27
+        goto endjob;
03cc27
+
03cc27
+    qemuDomainSetFakeReboot(driver, vm, false);
03cc27
+    agent = qemuDomainObjEnterAgent(vm);
03cc27
+    ret = qemuAgentShutdown(agent, agentFlag);
03cc27
+    qemuDomainObjExitAgent(vm, agent);
03cc27
+
03cc27
+ endjob:
03cc27
+    qemuDomainObjEndAgentJob(vm);
03cc27
+    return ret;
03cc27
+}
03cc27
+
03cc27
+
03cc27
+static int
03cc27
+qemuDomainRebootMonitor(virQEMUDriverPtr driver,
03cc27
+                        virDomainObjPtr vm,
03cc27
+                        bool isReboot)
03cc27
+{
03cc27
+    qemuDomainObjPrivatePtr priv = vm->privateData;
03cc27
+    int ret = -1;
03cc27
+
03cc27
+    if (qemuDomainObjBeginJob(driver, vm,
03cc27
+                              QEMU_JOB_MODIFY) < 0)
03cc27
+        return -1;
03cc27
+
03cc27
+    if (virDomainObjCheckActive(vm) < 0)
03cc27
+        goto endjob;
03cc27
+
03cc27
+#if !WITH_YAJL
03cc27
+    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
03cc27
+                   _("ACPI reboot is not supported without the JSON monitor"));
03cc27
+    goto endjob;
03cc27
+#endif
03cc27
+    qemuDomainSetFakeReboot(driver, vm, isReboot);
03cc27
+    qemuDomainObjEnterMonitor(driver, vm);
03cc27
+    ret = qemuMonitorSystemPowerdown(priv->mon);
03cc27
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
03cc27
+        ret = -1;
03cc27
+
03cc27
+ endjob:
03cc27
+    qemuDomainObjEndJob(driver, vm);
03cc27
+    return ret;
03cc27
+}
03cc27
+
03cc27
+
03cc27
 static int
03cc27
 qemuDomainReboot(virDomainPtr dom, unsigned int flags)
03cc27
 {
03cc27
@@ -2059,8 +2125,6 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
03cc27
     bool useAgent = false, agentRequested, acpiRequested;
03cc27
     bool isReboot = true;
03cc27
     bool agentForced;
03cc27
-    qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
03cc27
-    int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
03cc27
 
03cc27
     virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
03cc27
                   VIR_DOMAIN_REBOOT_GUEST_AGENT, -1);
03cc27
@@ -2070,7 +2134,6 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
03cc27
 
03cc27
     if (vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY ||
03cc27
         vm->def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE) {
03cc27
-        agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
03cc27
         isReboot = false;
03cc27
         VIR_INFO("Domain on_reboot setting overridden, shutting down");
03cc27
     }
03cc27
@@ -2086,56 +2149,21 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
03cc27
     if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
03cc27
         goto cleanup;
03cc27
 
03cc27
+    agentForced = agentRequested && !acpiRequested;
03cc27
     if (useAgent)
03cc27
-        agentJob = QEMU_AGENT_JOB_MODIFY;
03cc27
+        ret = qemuDomainRebootAgent(driver, vm, isReboot, agentForced);
03cc27
 
03cc27
-    if (qemuDomainObjBeginJobWithAgent(driver, vm,
03cc27
-                                       QEMU_JOB_MODIFY,
03cc27
-                                       agentJob) < 0)
03cc27
+    if (ret < 0 && agentForced)
03cc27
         goto cleanup;
03cc27
 
03cc27
-    agentForced = agentRequested && !acpiRequested;
03cc27
-    if (!qemuDomainAgentAvailable(vm, agentForced)) {
03cc27
-        if (agentForced)
03cc27
-            goto endjob;
03cc27
-        useAgent = false;
03cc27
-    }
03cc27
-
03cc27
-    if (virDomainObjCheckActive(vm) < 0)
03cc27
-        goto endjob;
03cc27
-
03cc27
-    if (useAgent) {
03cc27
-        qemuAgentPtr agent;
03cc27
-
03cc27
-        qemuDomainSetFakeReboot(driver, vm, false);
03cc27
-        agent = qemuDomainObjEnterAgent(vm);
03cc27
-        ret = qemuAgentShutdown(agent, agentFlag);
03cc27
-        qemuDomainObjExitAgent(vm, agent);
03cc27
-    }
03cc27
-
03cc27
     /* If we are not enforced to use just an agent, try ACPI
03cc27
      * shutdown as well in case agent did not succeed.
03cc27
      */
03cc27
     if ((!useAgent) ||
03cc27
         (ret < 0 && (acpiRequested || !flags))) {
03cc27
-#if !WITH_YAJL
03cc27
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
03cc27
-                       _("ACPI reboot is not supported without the JSON monitor"));
03cc27
-        goto endjob;
03cc27
-#endif
03cc27
-        qemuDomainSetFakeReboot(driver, vm, isReboot);
03cc27
-        qemuDomainObjEnterMonitor(driver, vm);
03cc27
-        ret = qemuMonitorSystemPowerdown(priv->mon);
03cc27
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
03cc27
-            ret = -1;
03cc27
+        ret = qemuDomainRebootMonitor(driver, vm, isReboot);
03cc27
     }
03cc27
 
03cc27
- endjob:
03cc27
-    if (agentJob)
03cc27
-        qemuDomainObjEndJobWithAgent(driver, vm);
03cc27
-    else
03cc27
-        qemuDomainObjEndJob(driver, vm);
03cc27
-
03cc27
  cleanup:
03cc27
     virDomainObjEndAPI(&vm;;
03cc27
     return ret;
03cc27
-- 
03cc27
2.26.2
03cc27