|
|
03cc27 |
From 5975af3d23091c73737968cea32490bca31c0479 Mon Sep 17 00:00:00 2001
|
|
|
03cc27 |
Message-Id: <5975af3d23091c73737968cea32490bca31c0479@dist-git>
|
|
|
03cc27 |
From: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
03cc27 |
Date: Fri, 1 May 2020 16:53:37 -0500
|
|
|
03cc27 |
Subject: [PATCH] qemu: don't take agent and monitor job for shutdown
|
|
|
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. So split the function into separate parts: one that does the agent
|
|
|
03cc27 |
shutdown and one that does the monitor shutdown. Each part holds only a
|
|
|
03cc27 |
job of the appropriate type.
|
|
|
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 1cb8bc52c1035573a0c1a87f724a6c7dfee82f12)
|
|
|
03cc27 |
|
|
|
03cc27 |
CVE-2019-20485
|
|
|
03cc27 |
|
|
|
03cc27 |
Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
03cc27 |
Message-Id: <20200501215341.27683-2-jjongsma@redhat.com>
|
|
|
03cc27 |
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
03cc27 |
---
|
|
|
03cc27 |
src/qemu/qemu_driver.c | 121 ++++++++++++++++++++++++++---------------
|
|
|
03cc27 |
1 file changed, 77 insertions(+), 44 deletions(-)
|
|
|
03cc27 |
|
|
|
03cc27 |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
03cc27 |
index 2852b96edd..bdc955e1fa 100644
|
|
|
03cc27 |
--- a/src/qemu/qemu_driver.c
|
|
|
03cc27 |
+++ b/src/qemu/qemu_driver.c
|
|
|
03cc27 |
@@ -1913,6 +1913,77 @@ static int qemuDomainResume(virDomainPtr dom)
|
|
|
03cc27 |
return ret;
|
|
|
03cc27 |
}
|
|
|
03cc27 |
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+static int
|
|
|
03cc27 |
+qemuDomainShutdownFlagsAgent(virQEMUDriverPtr driver,
|
|
|
03cc27 |
+ virDomainObjPtr vm,
|
|
|
03cc27 |
+ bool isReboot,
|
|
|
03cc27 |
+ bool reportError)
|
|
|
03cc27 |
+{
|
|
|
03cc27 |
+ int ret = -1;
|
|
|
03cc27 |
+ qemuAgentPtr agent;
|
|
|
03cc27 |
+ int agentFlag = isReboot ? QEMU_AGENT_SHUTDOWN_REBOOT :
|
|
|
03cc27 |
+ QEMU_AGENT_SHUTDOWN_POWERDOWN;
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+ if (qemuDomainObjBeginAgentJob(driver, vm,
|
|
|
03cc27 |
+ QEMU_AGENT_JOB_MODIFY) < 0)
|
|
|
03cc27 |
+ goto cleanup;
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+ if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
|
|
|
03cc27 |
+ virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
03cc27 |
+ "%s", _("domain is not running"));
|
|
|
03cc27 |
+ goto endjob;
|
|
|
03cc27 |
+ }
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+ if (!qemuDomainAgentAvailable(vm, reportError))
|
|
|
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 |
+
|
|
|
03cc27 |
+ cleanup:
|
|
|
03cc27 |
+ return ret;
|
|
|
03cc27 |
+}
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+static int
|
|
|
03cc27 |
+qemuDomainShutdownFlagsMonitor(virQEMUDriverPtr driver,
|
|
|
03cc27 |
+ virDomainObjPtr vm,
|
|
|
03cc27 |
+ bool isReboot)
|
|
|
03cc27 |
+{
|
|
|
03cc27 |
+ int ret = -1;
|
|
|
03cc27 |
+ qemuDomainObjPrivatePtr priv;
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+ priv = vm->privateData;
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
|
|
03cc27 |
+ goto cleanup;
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+ if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
|
|
|
03cc27 |
+ virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
03cc27 |
+ "%s", _("domain is not running"));
|
|
|
03cc27 |
+ goto endjob;
|
|
|
03cc27 |
+ }
|
|
|
03cc27 |
+
|
|
|
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 |
+
|
|
|
03cc27 |
+ cleanup:
|
|
|
03cc27 |
+ return ret;
|
|
|
03cc27 |
+}
|
|
|
03cc27 |
+
|
|
|
03cc27 |
+
|
|
|
03cc27 |
static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
|
|
03cc27 |
{
|
|
|
03cc27 |
virQEMUDriverPtr driver = dom->conn->privateData;
|
|
|
03cc27 |
@@ -1922,8 +1993,6 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
|
|
03cc27 |
bool useAgent = false, agentRequested, acpiRequested;
|
|
|
03cc27 |
bool isReboot = false;
|
|
|
03cc27 |
bool agentForced;
|
|
|
03cc27 |
- qemuDomainAgentJob agentJob = QEMU_AGENT_JOB_NONE;
|
|
|
03cc27 |
- int agentFlag = QEMU_AGENT_SHUTDOWN_POWERDOWN;
|
|
|
03cc27 |
|
|
|
03cc27 |
virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
|
|
|
03cc27 |
VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
|
|
|
03cc27 |
@@ -1934,7 +2003,6 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
|
|
03cc27 |
if (vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART ||
|
|
|
03cc27 |
vm->def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME) {
|
|
|
03cc27 |
isReboot = true;
|
|
|
03cc27 |
- agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
|
|
|
03cc27 |
VIR_INFO("Domain on_poweroff setting overridden, attempting reboot");
|
|
|
03cc27 |
}
|
|
|
03cc27 |
|
|
|
03cc27 |
@@ -1949,62 +2017,27 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
|
|
03cc27 |
if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
03cc27 |
goto cleanup;
|
|
|
03cc27 |
|
|
|
03cc27 |
- if (useAgent)
|
|
|
03cc27 |
- agentJob = QEMU_AGENT_JOB_MODIFY;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- if (qemuDomainObjBeginJobWithAgent(driver, vm,
|
|
|
03cc27 |
- QEMU_JOB_MODIFY,
|
|
|
03cc27 |
- agentJob) < 0)
|
|
|
03cc27 |
- goto cleanup;
|
|
|
03cc27 |
-
|
|
|
03cc27 |
- if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
|
|
|
03cc27 |
- virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
03cc27 |
- "%s", _("domain is not running"));
|
|
|
03cc27 |
- goto endjob;
|
|
|
03cc27 |
- }
|
|
|
03cc27 |
-
|
|
|
03cc27 |
agentForced = agentRequested && !acpiRequested;
|
|
|
03cc27 |
- if (!qemuDomainAgentAvailable(vm, agentForced)) {
|
|
|
03cc27 |
- if (agentForced)
|
|
|
03cc27 |
- goto endjob;
|
|
|
03cc27 |
- useAgent = false;
|
|
|
03cc27 |
- }
|
|
|
03cc27 |
-
|
|
|
03cc27 |
-
|
|
|
03cc27 |
if (useAgent) {
|
|
|
03cc27 |
- qemuAgentPtr agent;
|
|
|
03cc27 |
- qemuDomainSetFakeReboot(driver, vm, false);
|
|
|
03cc27 |
- agent = qemuDomainObjEnterAgent(vm);
|
|
|
03cc27 |
- ret = qemuAgentShutdown(agent, agentFlag);
|
|
|
03cc27 |
- qemuDomainObjExitAgent(vm, agent);
|
|
|
03cc27 |
+ ret = qemuDomainShutdownFlagsAgent(driver, vm, isReboot, agentForced);
|
|
|
03cc27 |
+ if (ret < 0 && agentForced)
|
|
|
03cc27 |
+ goto cleanup;
|
|
|
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 |
-
|
|
|
03cc27 |
+ if (!useAgent || (ret < 0 && (acpiRequested || !flags))) {
|
|
|
03cc27 |
/* Even if agent failed, we have to check if guest went away
|
|
|
03cc27 |
* by itself while our locks were down. */
|
|
|
03cc27 |
if (useAgent && !virDomainObjIsActive(vm)) {
|
|
|
03cc27 |
ret = 0;
|
|
|
03cc27 |
- goto endjob;
|
|
|
03cc27 |
+ goto cleanup;
|
|
|
03cc27 |
}
|
|
|
03cc27 |
|
|
|
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 = qemuDomainShutdownFlagsMonitor(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 |
|