|
|
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 |
|