aboutsummaryrefslogtreecommitdiffstats
path: root/main/libvirt/CVE-2019-20485.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/libvirt/CVE-2019-20485.patch')
-rw-r--r--main/libvirt/CVE-2019-20485.patch171
1 files changed, 171 insertions, 0 deletions
diff --git a/main/libvirt/CVE-2019-20485.patch b/main/libvirt/CVE-2019-20485.patch
new file mode 100644
index 00000000000..69e1a285737
--- /dev/null
+++ b/main/libvirt/CVE-2019-20485.patch
@@ -0,0 +1,171 @@
+From a663a860819287e041c3de672aad1d8543098ecc Mon Sep 17 00:00:00 2001
+From: Jonathon Jongsma <jjongsma@redhat.com>
+Date: Thu, 5 Dec 2019 10:08:52 -0600
+Subject: [PATCH] qemu: don't hold both jobs for suspend
+
+We have to assume that the guest agent may be malicious so we don't want
+to allow any agent queries to block any other libvirt API. By holding a
+monitor job while we're querying the agent, we open ourselves up to a
+DoS.
+
+So split the function up a bit to only hold the monitor job while
+querying qemu for whether the domain supports suspend. Then acquire only
+an agent job while issuing the agent suspend command.
+
+Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_driver.c | 94 ++++++++++++++++++++++++++++++------------------
+ 1 files changed, 59 insertions(+), 35 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 2891faf..52cf27f 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -19759,6 +19759,59 @@ qemuDomainProbeQMPCurrentMachine(virQEMUDriverPtr driver,
+ }
+
+
++/* returns -1 on error, or if query is not supported, 0 if query was successful */
++static int
++qemuDomainQueryWakeupSuspendSupport(virQEMUDriverPtr driver,
++ virDomainObjPtr vm,
++ bool *wakeupSupported)
++{
++ qemuDomainObjPrivatePtr priv = vm->privateData;
++ int ret = -1;
++
++ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CURRENT_MACHINE))
++ return -1;
++
++ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
++ return -1;
++
++ if ((ret = virDomainObjCheckActive(vm)) < 0)
++ goto endjob;
++
++ ret = qemuDomainProbeQMPCurrentMachine(driver, vm, wakeupSupported);
++
++ endjob:
++ qemuDomainObjEndJob(driver, vm);
++ return ret;
++}
++
++
++static int
++qemuDomainPMSuspendAgent(virQEMUDriverPtr driver,
++ virDomainObjPtr vm,
++ unsigned int target)
++{
++ qemuAgentPtr agent;
++ int ret = -1;
++
++ if (qemuDomainObjBeginAgentJob(driver, vm, QEMU_AGENT_JOB_MODIFY) < 0)
++ return -1;
++
++ if ((ret = virDomainObjCheckActive(vm)) < 0)
++ goto endjob;
++
++ if (!qemuDomainAgentAvailable(vm, true))
++ goto endjob;
++
++ agent = qemuDomainObjEnterAgent(vm);
++ ret = qemuAgentSuspend(agent, target);
++ qemuDomainObjExitAgent(vm, agent);
++
++ endjob:
++ qemuDomainObjEndAgentJob(vm);
++ return ret;
++}
++
++
+ static int
+ qemuDomainPMSuspendForDuration(virDomainPtr dom,
+ unsigned int target,
+@@ -19766,11 +19819,9 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
+ unsigned int flags)
+ {
+ virQEMUDriverPtr driver = dom->conn->privateData;
+- qemuDomainObjPrivatePtr priv;
+ virDomainObjPtr vm;
+- qemuAgentPtr agent;
+- qemuDomainJob job = QEMU_JOB_NONE;
+ int ret = -1;
++ bool wakeupSupported;
+
+ virCheckFlags(0, -1);
+
+@@ -19795,17 +19846,6 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
+ if (virDomainPMSuspendForDurationEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+- priv = vm->privateData;
+-
+- if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CURRENT_MACHINE))
+- job = QEMU_JOB_MODIFY;
+-
+- if (qemuDomainObjBeginJobWithAgent(driver, vm, job, QEMU_AGENT_JOB_MODIFY) < 0)
+- goto cleanup;
+-
+- if (virDomainObjCheckActive(vm) < 0)
+- goto endjob;
+-
+ /*
+ * The case we want to handle here is when QEMU has the API (i.e.
+ * QEMU_CAPS_QUERY_CURRENT_MACHINE is set). Otherwise, do not interfere
+@@ -19813,16 +19853,11 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
+ * that don't know about this cap, will keep their old behavior of
+ * suspending 'in the dark'.
+ */
+- if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CURRENT_MACHINE)) {
+- bool wakeupSupported;
+-
+- if (qemuDomainProbeQMPCurrentMachine(driver, vm, &wakeupSupported) < 0)
+- goto endjob;
+-
++ if (qemuDomainQueryWakeupSuspendSupport(driver, vm, &wakeupSupported) == 0) {
+ if (!wakeupSupported) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("Domain does not have suspend support"));
+- goto endjob;
++ goto cleanup;
+ }
+ }
+
+@@ -19832,29 +19867,18 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom,
+ target == VIR_NODE_SUSPEND_TARGET_HYBRID)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("S3 state is disabled for this domain"));
+- goto endjob;
++ goto cleanup;
+ }
+
+ if (vm->def->pm.s4 == VIR_TRISTATE_BOOL_NO &&
+ target == VIR_NODE_SUSPEND_TARGET_DISK) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("S4 state is disabled for this domain"));
+- goto endjob;
++ goto cleanup;
+ }
+ }
+
+- if (!qemuDomainAgentAvailable(vm, true))
+- goto endjob;
+-
+- agent = qemuDomainObjEnterAgent(vm);
+- ret = qemuAgentSuspend(agent, target);
+- qemuDomainObjExitAgent(vm, agent);
+-
+- endjob:
+- if (job)
+- qemuDomainObjEndJobWithAgent(driver, vm);
+- else
+- qemuDomainObjEndAgentJob(vm);
++ ret = qemuDomainPMSuspendAgent(driver, vm, target);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+--
+1.7.1
+