diff -Nru libvirt-4.0.0/debian/changelog libvirt-4.0.0/debian/changelog --- libvirt-4.0.0/debian/changelog 2021-11-23 06:25:36.000000000 +0000 +++ libvirt-4.0.0/debian/changelog 2022-05-03 04:30:16.000000000 +0000 @@ -1,8 +1,58 @@ -libvirt (4.0.0-1ubuntu8.20~cloud0) xenial-queens; urgency=medium +libvirt (4.0.0-1ubuntu8.21~cloud0) xenial-queens; urgency=medium * New update for the Ubuntu Cloud Archive. - -- Openstack Ubuntu Testing Bot Tue, 23 Nov 2021 06:25:36 +0000 + -- Openstack Ubuntu Testing Bot Tue, 03 May 2022 04:30:16 +0000 + +libvirt (4.0.0-1ubuntu8.21) bionic-security; urgency=medium + + * SECURITY UPDATE: crash via double-free memory issue + - debian/patches/CVE-2020-25637-1.patch: gendispatch: handle empty + flags in src/rpc/gendispatch.pl. + - debian/patches/CVE-2020-25637-2.patch: add support for filtering + @acls by uint params in src/remote/remote_protocol.x, + src/rpc/gendispatch.pl. + - debian/patches/CVE-2020-25637-3.patch: require write acl for guest + agent in src/libxl/libxl_driver.c, src/qemu/qemu_driver.c, + src/remote/remote_protocol.x. + - debian/patches/CVE-2020-25637-4.patch: set ifname to NULL after + freeing in src/qemu/qemu_agent.c. + - CVE-2020-25637 + * SECURITY UPDATE: sVirt SELinux confinement flaw + - debian/patches/CVE-2021-3631.patch: fix SELinux label generation + logic in src/security/security_selinux.c. + - CVE-2021-3631 + * SECURITY UPDATE: segmentation fault during VM shutdown + - debian/patches/CVE-2021-3975.patch: add missing lock in + qemuProcessHandleMonitorEOF in src/qemu/qemu_process.c. + - CVE-2021-3975 + * SECURITY UPDATE: DoS via libxl driver + - debian/patches/CVE-2021-4147-pre0.patch: handle external domain + destroy in src/libxl/libxl_domain.c, src/libxl/libxl_domain.h. + - debian/patches/CVE-2021-4147-pre1.patch: fix domain shutdown in + src/libxl/libxl_domain.c. + - debian/patches/CVE-2021-4147-1.patch: disable death events after + receiving a shutdown event in src/libxl/libxl_domain.c, + src/libxl/libxl_domain.h. + - debian/patches/CVE-2021-4147-2.patch: rename libxlShutdownThreadInfo + struct in src/libxl/libxl_domain.c. + - debian/patches/CVE-2021-4147-3.patch: modify name of shutdown thread + in src/libxl/libxl_domain.c. + - debian/patches/CVE-2021-4147-4.patch: handle domain death events in a + thread in src/libxl/libxl_domain.c. + - debian/patches/CVE-2021-4147-5.patch: search for virDomainObj in + event handler threads in src/libxl/libxl_domain.c. + - debian/patches/CVE-2021-4147-6pre1.patch: avoid virHashFree by + rearranging code in src/libxl/libxl_logger.c. + - debian/patches/CVE-2021-4147-6.patch: protect access to libxlLogger + files hash table in src/libxl/libxl_logger.c. + - CVE-2021-4147 + * SECURITY UPDATE: DoS via nwfilter driver + - debian/patches/CVE-2022-0897.patch: fix crash when counting number of + network filters in src/nwfilter/nwfilter_driver.c. + - CVE-2022-0897 + + -- Marc Deslauriers Wed, 20 Apr 2022 13:18:06 -0400 libvirt (4.0.0-1ubuntu8.20) bionic; urgency=medium diff -Nru libvirt-4.0.0/debian/patches/CVE-2020-25637-1.patch libvirt-4.0.0/debian/patches/CVE-2020-25637-1.patch --- libvirt-4.0.0/debian/patches/CVE-2020-25637-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2020-25637-1.patch 2022-04-20 16:58:38.000000000 +0000 @@ -0,0 +1,42 @@ +From 955029bd0ad7ef96000f529ac38204a8f4a96401 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 18 Sep 2020 17:44:56 +0200 +Subject: [PATCH] rpc: gendispatch: handle empty flags +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE-2020-25637 + +Prepare for omission of the in remote_protocol.x +@acl annotations: + @acl: :: +so that we can add more fields after, e.g.: + @acl: ::: + +Signed-off-by: Ján Tomko +Reviewed-by: Jiri Denemark +--- + src/rpc/gendispatch.pl | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -2056,7 +2056,7 @@ elsif ($mode eq "client") { + if ($acl[$i]->{object} ne $acl[0]->{object}) { + die "acl for '$call->{ProcName}' cannot check different objects"; + } +- if (defined $acl[$i]->{flags}) { ++ if (defined $acl[$i]->{flags} && length $acl[$i]->{flags}) { + $checkflags = 1; + } + } +@@ -2140,7 +2140,7 @@ elsif ($mode eq "client") { + my $method = "virAccessManagerCheck" . $object; + my $space = ' ' x length($method); + print " if ("; +- if (defined $acl->{flags}) { ++ if (defined $acl->{flags} && length $acl->{flags}) { + my $flags = $acl->{flags}; + if ($flags =~ /^\!/) { + $flags = substr $flags, 1; diff -Nru libvirt-4.0.0/debian/patches/CVE-2020-25637-2.patch libvirt-4.0.0/debian/patches/CVE-2020-25637-2.patch --- libvirt-4.0.0/debian/patches/CVE-2020-25637-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2020-25637-2.patch 2022-04-20 16:58:44.000000000 +0000 @@ -0,0 +1,93 @@ +From 50864dcda191eb35732dbd80fb6ca251a6bba923 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 18 Sep 2020 16:09:25 +0200 +Subject: [PATCH] rpc: add support for filtering @acls by uint params +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE-2020-25637 + +Add a new field to @acl annotations for filtering by +unsigned int parameters. + +Signed-off-by: Ján Tomko +Reviewed-by: Jiri Denemark +--- + src/remote/remote_protocol.x | 3 +++ + src/rpc/gendispatch.pl | 21 ++++++++++++++++++++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -3474,6 +3474,7 @@ enum remote_procedure { + * + * - @acl: : + * - @acl: :: ++ * - @acl: :::: + * + * Declare the access control requirements for the API. May be repeated + * multiple times, if multiple rules are required. +@@ -3483,6 +3484,8 @@ enum remote_procedure { + * is one of the permissions in access/viraccessperm.h + * indicates the rule only applies if the named flag + * is set in the API call ++ * and can be used to check an unsigned int parameter ++ * against value + * + * - @aclfilter: : + * +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -2048,10 +2048,12 @@ elsif ($mode eq "client") { + my @acl; + foreach (@{$acl}) { + my @bits = split /:/; +- push @acl, { object => $bits[0], perm => $bits[1], flags => $bits[2] } ++ push @acl, { object => $bits[0], perm => $bits[1], flags => $bits[2], ++ param => $bits[3], value => $bits[4] } + } + + my $checkflags = 0; ++ my $paramtocheck = undef; + for (my $i = 1 ; $i <= $#acl ; $i++) { + if ($acl[$i]->{object} ne $acl[0]->{object}) { + die "acl for '$call->{ProcName}' cannot check different objects"; +@@ -2059,6 +2061,9 @@ elsif ($mode eq "client") { + if (defined $acl[$i]->{flags} && length $acl[$i]->{flags}) { + $checkflags = 1; + } ++ if (defined $acl[$i]->{param}) { ++ $paramtocheck = $acl[$i]->{param}; ++ } + } + + my $apiname = $prefix . $call->{ProcName}; +@@ -2092,6 +2097,9 @@ elsif ($mode eq "client") { + if ($checkflags) { + push @argdecls, "unsigned int flags"; + } ++ if (defined $paramtocheck) { ++ push @argdecls, "unsigned int " . $paramtocheck; ++ } + + my $ret; + my $pass; +@@ -2150,6 +2158,17 @@ elsif ($mode eq "client") { + } + print " "; + } ++ if (defined $acl->{param}) { ++ my $param = $acl->{param}; ++ my $value = $acl->{value}; ++ if ($value =~ /^\!/) { ++ $value = substr $value, 1; ++ print "($param != ($value)) &&\n"; ++ } else { ++ print "($param == ($value)) &&\n"; ++ } ++ print " "; ++ } + print "(rv = $method(" . join(", ", @argvars, $perm) . ")) <= 0) {\n"; + print " virObjectUnref(mgr);\n"; + if ($action eq "Ensure") { diff -Nru libvirt-4.0.0/debian/patches/CVE-2020-25637-3.patch libvirt-4.0.0/debian/patches/CVE-2020-25637-3.patch --- libvirt-4.0.0/debian/patches/CVE-2020-25637-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2020-25637-3.patch 2022-04-20 16:58:58.000000000 +0000 @@ -0,0 +1,58 @@ +Backport of: + +From e4116eaa44cb366b59f7fe98f4b88d04c04970ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 18 Sep 2020 17:54:14 +0200 +Subject: [PATCH] rpc: require write acl for guest agent in + virDomainInterfaceAddresses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE-2020-25637 + +Add a requirement for domain:write if source is set to +VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT. + +Signed-off-by: Ján Tomko +Reported-by: Ilja Van Sprundel +Reviewed-by: Jiri Denemark +--- + src/libxl/libxl_driver.c | 2 +- + src/lxc/lxc_driver.c | 2 +- + src/qemu/qemu_driver.c | 2 +- + src/remote/remote_protocol.x | 1 + + 4 files changed, 4 insertions(+), 3 deletions(-) + +--- a/src/libxl/libxl_driver.c ++++ b/src/libxl/libxl_driver.c +@@ -6312,7 +6312,7 @@ libxlDomainInterfaceAddresses(virDomainP + if (!(vm = libxlDomObjFromDomain(dom))) + goto cleanup; + +- if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0) ++ if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def, source) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -20388,7 +20388,7 @@ qemuDomainInterfaceAddresses(virDomainPt + if (!(vm = qemuDomObjFromDomain(dom))) + goto cleanup; + +- if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0) ++ if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def, source) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -5880,6 +5880,7 @@ enum remote_procedure { + /** + * @generate: none + * @acl: domain:read ++ * @acl: domain:write::source:VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT + */ + REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES = 353, + diff -Nru libvirt-4.0.0/debian/patches/CVE-2020-25637-4.patch libvirt-4.0.0/debian/patches/CVE-2020-25637-4.patch --- libvirt-4.0.0/debian/patches/CVE-2020-25637-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2020-25637-4.patch 2022-04-20 16:59:33.000000000 +0000 @@ -0,0 +1,31 @@ +Backport of: + +From a63b48c5ecef077bf0f909a85f453a605600cf05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 18 Sep 2020 17:56:37 +0200 +Subject: [PATCH] qemu: agent: set ifname to NULL after freeing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE-2020-25637 + +Signed-off-by: Ján Tomko +Reported-by: Ilja Van Sprundel +Fixes: 0977b8aa071de550e1a013d35e2c72615e65d520 +Reviewed-by: Mauro Matteo Cascella +Reviewed-by: Jiri Denemark +--- + src/qemu/qemu_agent.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/src/qemu/qemu_agent.c ++++ b/src/qemu/qemu_agent.c +@@ -2136,6 +2136,7 @@ qemuAgentGetInterfaces(qemuAgentPtr mon, + + /* Has to be freed for each interface. */ + virStringListFree(ifname); ++ ifname = NULL; + + /* as well as IP address which - moreover - + * can be presented multiple times */ diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-3631.patch libvirt-4.0.0/debian/patches/CVE-2021-3631.patch --- libvirt-4.0.0/debian/patches/CVE-2021-3631.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-3631.patch 2022-04-20 17:01:23.000000000 +0000 @@ -0,0 +1,52 @@ +Backport of: + +From 15073504dbb624d3f6c911e85557019d3620fdb2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Mon, 28 Jun 2021 13:09:04 +0100 +Subject: [PATCH] security: fix SELinux label generation logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A process can access a file if the set of MCS categories +for the file is equal-to *or* a subset-of, the set of +MCS categories for the process. + +If there are two VMs: + + a) svirt_t:s0:c117 + b) svirt_t:s0:c117,c720 + +Then VM (b) is able to access files labelled for VM (a). + +IOW, we must discard case where the categories are equal +because that is a subset of many other valid category pairs. + +Fixes: https://gitlab.com/libvirt/libvirt/-/issues/153 +CVE-2021-3631 +Reviewed-by: Peter Krempa +Signed-off-by: Daniel P. Berrangé +--- + src/security/security_selinux.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -287,8 +287,15 @@ virSecuritySELinuxMCSFind(virSecurityMan + VIR_DEBUG("Try cat %s:c%d,c%d", sens, c1 + catMin, c2 + catMin); + + if (c1 == c2) { +- if (virAsprintf(&mcs, "%s:c%d", sens, catMin + c1) < 0) +- return NULL; ++ /* ++ * A process can access a file if the set of MCS categories ++ * for the file is equal-to *or* a subset-of, the set of ++ * MCS categories for the process. ++ * ++ * IOW, we must discard case where the categories are equal ++ * because that is a subset of other category pairs. ++ */ ++ continue; + } else { + if (c1 > c2) { + int t = c1; diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-3975.patch libvirt-4.0.0/debian/patches/CVE-2021-3975.patch --- libvirt-4.0.0/debian/patches/CVE-2021-3975.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-3975.patch 2022-04-20 17:01:38.000000000 +0000 @@ -0,0 +1,33 @@ +From 1ac703a7d0789e46833f4013a3876c2e3af18ec7 Mon Sep 17 00:00:00 2001 +From: Peng Liang +Date: Wed, 24 Feb 2021 19:28:23 +0800 +Subject: [PATCH] qemu: Add missing lock in qemuProcessHandleMonitorEOF + +qemuMonitorUnregister will be called in multiple threads (e.g. threads +in rpc worker pool and the vm event thread). In some cases, it isn't +protected by the monitor lock, which may lead to call g_source_unref +more than one time and a use-after-free problem eventually. + +Add the missing lock in qemuProcessHandleMonitorEOF (which is the only +position missing lock of monitor I found). + +Suggested-by: Michal Privoznik +Signed-off-by: Peng Liang +Signed-off-by: Michal Privoznik +Reviewed-by: Michal Privoznik +--- + src/qemu/qemu_process.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -310,7 +310,9 @@ qemuProcessHandleMonitorEOF(qemuMonitorP + /* We don't want this EOF handler to be called over and over while the + * thread is waiting for a job. + */ ++ virObjectLock(mon); + qemuMonitorUnregister(mon); ++ virObjectUnlock(mon); + + /* We don't want any cleanup from EOF handler (or any other + * thread) to enter qemu namespace. */ diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-1.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-1.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-1.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,109 @@ +Backport of: + +From 23b51d7b8ec885e97a9277cf0a6c2833db4636e8 Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Fri, 29 Oct 2021 14:16:33 -0600 +Subject: [PATCH] libxl: Disable death events after receiving a shutdown event +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The libxl driver will handle all domain destruction and cleanup +when receiving a domain shutdown event from libxl. Commit fa30ee04a2a +introduced the ignoreDeathEvent boolean in the DomainObjPrivate struct +to ignore subsequent death events from libxl. But libxl already provides +a mechanism to disable death events via libxl_evdisable_domain_death. + +This patch partially reverts commit fa30ee04a2a and instead uses +libxl_evdisable_domain_death to disable subsequent death events when +processing a shutdown event. + +Signed-off-by: Jim Fehlig +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Ján Tomko +--- + src/libxl/libxl_domain.c | 23 +++++------------------ + src/libxl/libxl_domain.h | 3 --- + 2 files changed, 5 insertions(+), 21 deletions(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -554,12 +554,6 @@ static void + libxlDomainHandleDeath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) + { + virObjectEventPtr dom_event = NULL; +- libxlDomainObjPrivatePtr priv = vm->privateData; +- +- if (priv->ignoreDeathEvent) { +- priv->ignoreDeathEvent = false; +- return; +- } + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + return; +@@ -608,7 +602,6 @@ libxlDomainEventHandler(void *data, VIR_ + } + + if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { +- libxlDomainObjPrivatePtr priv = vm->privateData; + struct libxlShutdownThreadInfo *shutdown_info = NULL; + virThread thread; + char *name = NULL; +@@ -627,12 +620,9 @@ libxlDomainEventHandler(void *data, VIR_ + goto cleanup; + /* + * Cleanup will be handled by the shutdown thread. +- * Ignore the forthcoming death event from libxl + */ +- priv->ignoreDeathEvent = true; + if (virThreadCreateFull(&thread, false, libxlDomainShutdownThread, + name, false, shutdown_info) < 0) { +- priv->ignoreDeathEvent = false; + /* + * Not much we can do on error here except log it. + */ +@@ -766,18 +756,17 @@ libxlDomainDestroyInternal(libxlDriverPr + libxlDomainObjPrivatePtr priv = vm->privateData; + int ret = -1; + +- /* Ignore next LIBXL_EVENT_TYPE_DOMAIN_DEATH as the caller will handle +- * domain death appropriately already (having more info, like the reason). +- */ +- priv->ignoreDeathEvent = true; ++ if (priv->deathW) { ++ libxl_evdisable_domain_death(cfg->ctx, priv->deathW); ++ priv->deathW = NULL; ++ } ++ + /* Unlock virDomainObj during destroy, which can take considerable + * time on large memory domains. + */ + virObjectUnlock(vm); + ret = libxl_domain_destroy(cfg->ctx, vm->def->id, NULL); + virObjectLock(vm); +- if (ret) +- priv->ignoreDeathEvent = false; + + virObjectUnref(cfg); + return ret; +@@ -829,8 +818,6 @@ libxlDomainCleanup(libxlDriverPrivatePtr + priv->deathW = NULL; + } + +- priv->ignoreDeathEvent = false; +- + if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback) + driver->inhibitCallback(false, driver->inhibitOpaque); + +--- a/src/libxl/libxl_domain.h ++++ b/src/libxl/libxl_domain.h +@@ -65,9 +65,6 @@ struct _libxlDomainObjPrivate { + /* console */ + virChrdevsPtr devs; + libxl_evgen_domain_death *deathW; +- /* Flag to indicate the upcoming LIBXL_EVENT_TYPE_DOMAIN_DEATH is caused +- * by libvirt and should not be handled separately */ +- bool ignoreDeathEvent; + unsigned short migrationPort; + char *lockState; + diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-2.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-2.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-2.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,57 @@ +From a4e6fba069c0809b8b5dde5e9db62d2efd91b4a0 Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Wed, 24 Nov 2021 11:10:19 -0700 +Subject: [PATCH] libxl: Rename libxlShutdownThreadInfo struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +An upcoming change will use the struct in a thread created to process +death events. Rename libxlShutdownThreadInfo to libxlEventHandlerThreadInfo +to reflect the more generic usage. + +Signed-off-by: Jim Fehlig +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Ján Tomko +--- + src/libxl/libxl_domain.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -424,7 +424,7 @@ virDomainDefParserConfig libxlDomainDefP + }; + + +-struct libxlShutdownThreadInfo ++struct libxlEventHandlerThreadInfo + { + libxlDriverPrivatePtr driver; + virDomainObjPtr vm; +@@ -435,7 +435,7 @@ struct libxlShutdownThreadInfo + static void + libxlDomainShutdownThread(void *opaque) + { +- struct libxlShutdownThreadInfo *shutdown_info = opaque; ++ struct libxlEventHandlerThreadInfo *shutdown_info = opaque; + virDomainObjPtr vm = shutdown_info->vm; + libxl_event *ev = shutdown_info->event; + libxlDriverPrivatePtr driver = shutdown_info->driver; +@@ -602,7 +602,7 @@ libxlDomainEventHandler(void *data, VIR_ + } + + if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { +- struct libxlShutdownThreadInfo *shutdown_info = NULL; ++ struct libxlEventHandlerThreadInfo *shutdown_info = NULL; + virThread thread; + char *name = NULL; + +@@ -633,7 +633,7 @@ libxlDomainEventHandler(void *data, VIR_ + } + /* + * virDomainObjEndAPI is called in the shutdown thread, where +- * libxlShutdownThreadInfo and libxl_event are also freed. ++ * libxlEventHandlerThreadInfo and libxl_event are also freed. + */ + return; + } else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) { diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-3.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-3.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-3.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,32 @@ +Backport of: + +From e4f7589a3ec285489618ca04c8c0230cc31f3d99 Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Wed, 24 Nov 2021 11:16:38 -0700 +Subject: [PATCH] libxl: Modify name of shutdown thread +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The current thread name 'ev-' is a bit terse. Change the name +to 'shutdown-event-', allowing it to be distinguished between +thread handling other event types. + +Signed-off-by: Jim Fehlig +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Ján Tomko +--- + src/libxl/libxl_domain.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -616,7 +616,7 @@ libxlDomainEventHandler(void *data, VIR_ + shutdown_info->driver = driver; + shutdown_info->vm = vm; + shutdown_info->event = (libxl_event *)event; +- if (virAsprintf(&name, "ev-%d", event->domid) < 0) ++ if (virAsprintf(&name, "shutdown-event-%d", event->domid) < 0) + goto cleanup; + /* + * Cleanup will be handled by the shutdown thread. diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-4.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-4.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-4.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,151 @@ +Backport of: + +From b9a5faea49b7412e26d7389af4c32fc2b3ee80e5 Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Wed, 24 Nov 2021 11:36:55 -0700 +Subject: [PATCH] libxl: Handle domain death events in a thread +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Similar to domain shutdown events, processing domain death events can be a +lengthy process and we don't want to block the event handler while the +operation completes. Move the death handling function to a thread. + +Signed-off-by: Jim Fehlig +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Ján Tomko +--- + src/libxl/libxl_domain.c | 67 ++++++++++++++++++++++++++++------------ + 1 file changed, 47 insertions(+), 20 deletions(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -551,12 +551,17 @@ libxlDomainShutdownThread(void *opaque) + } + + static void +-libxlDomainHandleDeath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) ++libxlDomainDeathThread(void *opaque) + { ++ struct libxlEventHandlerThreadInfo *death_info = opaque; ++ virDomainObj *vm = death_info->vm; ++ libxl_event *ev = death_info->event; ++ libxlDriverPrivate *driver = death_info->driver; + virObjectEventPtr dom_event = NULL; ++ libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) +- return; ++ goto cleanup; + + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED); + dom_event = virDomainEventLifecycleNewFromObj(vm, +@@ -568,6 +573,11 @@ libxlDomainHandleDeath(libxlDriverPrivat + libxlDomainObjEndJob(driver, vm); + + virObjectEventStateQueue(driver->domainEventState, dom_event); ++ ++ cleanup: ++ virDomainObjEndAPI(&vm); ++ libxl_event_free(cfg->ctx, ev); ++ VIR_FREE(death_info); + } + + +@@ -581,6 +591,9 @@ libxlDomainEventHandler(void *data, VIR_ + libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; + virDomainObjPtr vm = NULL; + libxlDriverConfigPtr cfg; ++ struct libxlEventHandlerThreadInfo *thread_info = NULL; ++ virThread thread; ++ char *thread_name = NULL; + + if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN && + event->type != LIBXL_EVENT_TYPE_DOMAIN_DEATH) { +@@ -601,34 +614,29 @@ libxlDomainEventHandler(void *data, VIR_ + goto cleanup; + } + ++ /* ++ * Start event-specific threads to handle shutdown and death. ++ * They are potentially lengthy operations and we don't want to be ++ * blocking this event handler while they are in progress. ++ */ + if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { +- struct libxlEventHandlerThreadInfo *shutdown_info = NULL; +- virThread thread; +- char *name = NULL; +- +- /* +- * Start a thread to handle shutdown. We don't want to be tying up +- * libxl's event machinery by doing a potentially lengthy shutdown. +- */ +- if (VIR_ALLOC_N(shutdown_info, 1) < 0) ++ if (VIR_ALLOC_N(thread_info, 1) < 0) + goto cleanup; + +- shutdown_info->driver = driver; +- shutdown_info->vm = vm; +- shutdown_info->event = (libxl_event *)event; +- if (virAsprintf(&name, "shutdown-event-%d", event->domid) < 0) ++ thread_info->driver = driver; ++ thread_info->vm = vm; ++ thread_info->event = (libxl_event *)event; ++ if (virAsprintf(&thread_name, "shutdown-event-%d", event->domid) < 0) + goto cleanup; + /* + * Cleanup will be handled by the shutdown thread. + */ + if (virThreadCreateFull(&thread, false, libxlDomainShutdownThread, +- name, false, shutdown_info) < 0) { ++ thread_name, false, thread_info) < 0) { + /* + * Not much we can do on error here except log it. + */ + VIR_ERROR(_("Failed to create thread to handle domain shutdown")); +- VIR_FREE(shutdown_info); +- VIR_FREE(name); + goto cleanup; + } + /* +@@ -637,15 +645,36 @@ libxlDomainEventHandler(void *data, VIR_ + */ + return; + } else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) { ++ if (VIR_ALLOC_N(thread_info, 1) < 0) ++ goto cleanup; ++ ++ thread_info->driver = driver; ++ thread_info->vm = vm; ++ thread_info->event = (libxl_event *)event; ++ if (virAsprintf(&thread_name, "death-event-%d", event->domid) < 0) ++ goto cleanup; + /* +- * On death the domain is cleaned up from Xen's perspective. +- * Cleanup on the libvirt side can be done synchronously. ++ * Cleanup will be handled by the death thread. + */ +- libxlDomainHandleDeath(driver, vm); ++ if (virThreadCreateFull(&thread, false, libxlDomainDeathThread, ++ thread_name, false, thread_info) < 0) { ++ /* ++ * Not much we can do on error here except log it. ++ */ ++ VIR_ERROR(_("Failed to create thread to handle domain death")); ++ goto cleanup; ++ } ++ /* ++ * virDomainObjEndAPI is called in the death thread, where ++ * libxlEventHandlerThreadInfo and libxl_event are also freed. ++ */ ++ return; + } + + cleanup: + virDomainObjEndAPI(&vm); ++ VIR_FREE(thread_name); ++ VIR_FREE(thread_info); + cfg = libxlDriverConfigGet(driver); + /* Cast away any const */ + libxl_event_free(cfg->ctx, (libxl_event *)event); diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-5.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-5.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-5.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,173 @@ +Backport of: + +From 5c5df5310f72be4878a71ace47074c54e0d1a27d Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Wed, 24 Nov 2021 11:48:51 -0700 +Subject: [PATCH] libxl: Search for virDomainObj in event handler threads +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +libxl can deliver events and invoke callbacks on any application thread +calling into libxl. This can cause deadlock in the libvirt libxl driver + +Thread 19 (Thread 0x7f31411ec700 (LWP 14068) "libvirtd"): +#0 0x00007f318520cc7d in __lll_lock_wait () from /lib64/libpthread.so.0 +#1 0x00007f3185205ed5 in pthread_mutex_lock () from /lib64/libpthread.so.0 +#2 0x00007f3189488015 in virMutexLock (m=) at ../../src/util/virthread.c:79 +#3 0x00007f3189463f3b in virObjectLock (anyobj=) at ../../src/util/virobject.c:433 +#4 0x00007f31894f2f41 in virDomainObjListSearchID (payload=0x7f317400a6d0, name=, data=0x7f31411eaeac) at ../../src/conf/virdomainobjlist.c:105 +#5 0x00007f3189437ac5 in virHashSearch (ctable=0x7f3124025a30, iter=iter@entry=0x7f31894f2f30 , data=data@entry=0x7f31411eaeac, name=name@entry=0x0) at ../../src/util/virhash.c:745 +#6 0x00007f31894f3919 in virDomainObjListFindByID (doms=0x7f3124025430, id=) at ../../src/conf/virdomainobjlist.c:121 +#7 0x00007f3152f292e5 in libxlDomainEventHandler (data=0x7f3124023d80, event=0x7f310c010ae0) at ../../src/libxl/libxl_domain.c:660 +#8 0x00007f3152c6ff5d in egc_run_callbacks (egc=egc@entry=0x7f31411eaf50) at libxl_event.c:1427 +#9 0x00007f3152c718bd in libxl__egc_cleanup (egc=0x7f31411eaf50) at libxl_event.c:1458 +#10 libxl__ao_inprogress (ao=ao@entry=0x7f310c00b8a0, file=file@entry=0x7f3152cce987 "libxl_domain.c", line=line@entry=730, func=func@entry=0x7f3152ccf750 <__func__.22238> "libxl_domain_unpause") at libxl_event.c:2047 +#11 0x00007f3152c8c5b8 in libxl_domain_unpause (ctx=0x7f3124015a40, domid=, ao_how=ao_how@entry=0x0) at libxl_domain.c:730 +#12 0x00007f3152f2a584 in libxl_domain_unpause_0x041200 (domid=, ctx=) at /usr/include/libxl.h:1756 +#13 libxlDomainStart (driver=driver@entry=0x7f3124023d80, vm=vm@entry=0x7f317400a6d0, start_paused=start_paused@entry=false, restore_fd=restore_fd@entry=-1, restore_ver=, restore_ver@entry=2) at ../../src/libxl/libxl_domain.c:1482 +#14 0x00007f3152f2a6e3 in libxlDomainStartNew (driver=driver@entry=0x7f3124023d80, vm=vm@entry=0x7f317400a6d0, start_paused=start_paused@entry=false) at ../../src/libxl/libxl_domain.c:1545 +#15 0x00007f3152f2a789 in libxlDomainShutdownHandleRestart (driver=0x7f3124023d80, vm=0x7f317400a6d0) at ../../src/libxl/libxl_domain.c:464 +#16 0x00007f3152f2a9e4 in libxlDomainShutdownThread (opaque=) at ../../src/libxl/libxl_domain.c:559 +#17 0x00007f3189487ee2 in virThreadHelper (data=) at ../../src/util/virthread.c:196 +#18 0x00007f3185203539 in start_thread () from /lib64/libpthread.so.0 +#19 0x00007f3184f3becf in clone () from /lib64/libc.so.6 + +Frame 16 runs a thread created to handle domain shutdown processing for +domid 28712. In this case the event contained the reboot reason, so the +old domain is destroyed and a new one is created by libxlDomainStart new. +After starting the domain, it is unpaused by calling libxl_domain_unpause +in frame 12. While the thread is running within libxl, libxl takes the +opportunity to deliver a pending domain shutdown event for unrelated domid +28710. While searching for the associated virDomainObj by ID, a deadlock is +encountered when attempting to lock the virDomainObj for domid 28712, which +is already locked since this thread is processing its shutdown event. + +The deadlock can be avoided by moving the search for a virDomainObj +associated with the event domid to the shutdown thread. The same is done +for the death thread. + +Signed-off-by: Jim Fehlig +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Ján Tomko +--- + src/libxl/libxl_domain.c | 35 ++++++++++++++++++----------------- + 1 file changed, 18 insertions(+), 17 deletions(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -427,7 +427,6 @@ virDomainDefParserConfig libxlDomainDefP + struct libxlEventHandlerThreadInfo + { + libxlDriverPrivatePtr driver; +- virDomainObjPtr vm; + libxl_event *event; + }; + +@@ -436,7 +435,7 @@ static void + libxlDomainShutdownThread(void *opaque) + { + struct libxlEventHandlerThreadInfo *shutdown_info = opaque; +- virDomainObjPtr vm = shutdown_info->vm; ++ virDomainObjPtr vm = NULL; + libxl_event *ev = shutdown_info->event; + libxlDriverPrivatePtr driver = shutdown_info->driver; + virObjectEventPtr dom_event = NULL; +@@ -445,6 +444,12 @@ libxlDomainShutdownThread(void *opaque) + + cfg = libxlDriverConfigGet(driver); + ++ vm = virDomainObjListFindByID(driver->domains, ev->domid); ++ if (!vm) { ++ /* Nothing to do if we can't find the virDomainObj */ ++ goto cleanup; ++ } ++ + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + +@@ -554,12 +559,18 @@ static void + libxlDomainDeathThread(void *opaque) + { + struct libxlEventHandlerThreadInfo *death_info = opaque; +- virDomainObj *vm = death_info->vm; ++ virDomainObj *vm = NULL; + libxl_event *ev = death_info->event; + libxlDriverPrivate *driver = death_info->driver; + virObjectEventPtr dom_event = NULL; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + ++ vm = virDomainObjListFindByID(driver->domains, ev->domid); ++ if (!vm) { ++ /* Nothing to do if we can't find the virDomainObj */ ++ goto cleanup; ++ } ++ + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + +@@ -589,7 +600,6 @@ libxlDomainEventHandler(void *data, VIR_ + { + libxlDriverPrivatePtr driver = data; + libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; +- virDomainObjPtr vm = NULL; + libxlDriverConfigPtr cfg; + struct libxlEventHandlerThreadInfo *thread_info = NULL; + virThread thread; +@@ -608,12 +618,6 @@ libxlDomainEventHandler(void *data, VIR_ + if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND) + goto cleanup; + +- vm = virDomainObjListFindByID(driver->domains, event->domid); +- if (!vm) { +- /* Nothing to do if we can't find the virDomainObj */ +- goto cleanup; +- } +- + /* + * Start event-specific threads to handle shutdown and death. + * They are potentially lengthy operations and we don't want to be +@@ -624,7 +628,6 @@ libxlDomainEventHandler(void *data, VIR_ + goto cleanup; + + thread_info->driver = driver; +- thread_info->vm = vm; + thread_info->event = (libxl_event *)event; + if (virAsprintf(&thread_name, "shutdown-event-%d", event->domid) < 0) + goto cleanup; +@@ -640,8 +643,8 @@ libxlDomainEventHandler(void *data, VIR_ + goto cleanup; + } + /* +- * virDomainObjEndAPI is called in the shutdown thread, where +- * libxlEventHandlerThreadInfo and libxl_event are also freed. ++ * libxlEventHandlerThreadInfo and libxl_event are freed in the ++ * shutdown thread + */ + return; + } else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) { +@@ -649,7 +652,6 @@ libxlDomainEventHandler(void *data, VIR_ + goto cleanup; + + thread_info->driver = driver; +- thread_info->vm = vm; + thread_info->event = (libxl_event *)event; + if (virAsprintf(&thread_name, "death-event-%d", event->domid) < 0) + goto cleanup; +@@ -665,14 +667,13 @@ libxlDomainEventHandler(void *data, VIR_ + goto cleanup; + } + /* +- * virDomainObjEndAPI is called in the death thread, where +- * libxlEventHandlerThreadInfo and libxl_event are also freed. ++ * libxlEventHandlerThreadInfo and libxl_event are freed in the ++ * death thread + */ + return; + } + + cleanup: +- virDomainObjEndAPI(&vm); + VIR_FREE(thread_name); + VIR_FREE(thread_info); + cfg = libxlDriverConfigGet(driver); diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-6.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-6.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-6.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,90 @@ +Backport of: + +From a7a03324d86e111f81687b5315b8f296dde84340 Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Thu, 18 Nov 2021 12:03:20 -0700 +Subject: [PATCH] libxl: Protect access to libxlLogger files hash table +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The hash table of log file objects in libxlLogger is not protected against +concurrent access. It is possible for one thread to remove an entry while +another is updating it. Add a mutex to the libxlLogger object and lock it +when accessing the files hash table. + +Signed-off-by: Jim Fehlig +Reviewed-by: Daniel P. Berrangé +Reviewed-by: Ján Tomko +--- + src/libxl/libxl_logger.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/src/libxl/libxl_logger.c ++++ b/src/libxl/libxl_logger.c +@@ -32,6 +32,7 @@ + #include "util/virfile.h" + #include "util/virhash.h" + #include "util/virstring.h" ++#include "util/virthread.h" + #include "util/virtime.h" + + #define VIR_FROM_THIS VIR_FROM_LIBXL +@@ -47,6 +48,7 @@ struct xentoollog_logger_libvirt { + + /* map storing the opened fds: "domid" -> FILE* */ + virHashTablePtr files; ++ virMutex tableLock; + FILE *defaultLogFile; + }; + +@@ -91,7 +93,9 @@ libvirt_vmessage(xentoollog_logger *logg + start = start + 9; + *end = '\0'; + ++ virMutexLock(&lg->tableLock); + domainLogFile = virHashLookup(lg->files, start); ++ virMutexUnlock(&lg->tableLock); + if (domainLogFile) + logFile = domainLogFile; + +@@ -165,6 +169,11 @@ libxlLoggerNew(const char *logDir, virLo + if ((logger.defaultLogFile = fopen(path, "a")) == NULL) + goto cleanup; + ++ if (virMutexInit(&logger.tableLock) < 0) { ++ VIR_FORCE_FCLOSE(logger.defaultLogFile); ++ goto cleanup; ++ } ++ + if ((logger.files = virHashCreate(3, libxlLoggerFileFree)) == NULL) + goto cleanup; + +@@ -182,6 +191,7 @@ libxlLoggerFree(libxlLoggerPtr logger) + if (logger->defaultLogFile) + VIR_FORCE_FCLOSE(logger->defaultLogFile); + virHashFree(logger->files); ++ virMutexDestroy(&logger->tableLock); + xtl_logger_destroy(xtl_logger); + } + +@@ -205,7 +215,9 @@ libxlLoggerOpenFile(libxlLoggerPtr logge + path, virStrerror(errno, ebuf, sizeof(ebuf))); + goto cleanup; + } ++ virMutexLock(&logger->tableLock); + ignore_value(virHashAddEntry(logger->files, domidstr, logFile)); ++ virMutexUnlock(&logger->tableLock); + + /* domain_config is non NULL only when starting a new domain */ + if (domain_config) { +@@ -225,7 +237,9 @@ libxlLoggerCloseFile(libxlLoggerPtr logg + if (virAsprintf(&domidstr, "%d", id) < 0) + return; + ++ virMutexLock(&logger->tableLock); + ignore_value(virHashRemoveEntry(logger->files, domidstr)); ++ virMutexUnlock(&logger->tableLock); + + VIR_FREE(domidstr); + } diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-6pre1.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-6pre1.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-6pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-6pre1.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,53 @@ +Backport of: + +From 04bbaa2b1f828b83faea03041f246c14770726db Mon Sep 17 00:00:00 2001 +From: Peter Krempa +Date: Tue, 30 Nov 2021 11:34:43 +0100 +Subject: [PATCH] libxlLoggerNew: Avoid virHashFree by rearranging code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Allocate the hash table only after the log file is opened so that we +don't need to deallocate it on failure. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +Reviewed-by: Martin Kletzander +--- + src/libxl/libxl_logger.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/src/libxl/libxl_logger.c ++++ b/src/libxl/libxl_logger.c +@@ -159,24 +159,20 @@ libxlLoggerNew(const char *logDir, virLo + } + logger.logDir = logDir; + +- if ((logger.files = virHashCreate(3, libxlLoggerFileFree)) == NULL) +- return NULL; +- + if (virAsprintf(&path, "%s/libxl-driver.log", logDir) < 0) +- goto error; ++ goto cleanup; + + if ((logger.defaultLogFile = fopen(path, "a")) == NULL) +- goto error; ++ goto cleanup; ++ ++ if ((logger.files = virHashCreate(3, libxlLoggerFileFree)) == NULL) ++ goto cleanup; + + logger_out = XTL_NEW_LOGGER(libvirt, logger); + +- cleanup: ++cleanup: + VIR_FREE(path); + return logger_out; +- +- error: +- virHashFree(logger.files); +- goto cleanup; + } + + void diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-pre0.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-pre0.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-pre0.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-pre0.patch 2022-04-20 17:04:19.000000000 +0000 @@ -0,0 +1,161 @@ +Backport of: + +From fa30ee04a2a7205c3d664c67b88dd8df9cb1fb40 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= + +Date: Sat, 8 Dec 2018 03:46:00 +0100 +Subject: [PATCH] libxl: handle external domain destroy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If domain is killed with `xl destroy`, libvirt will not notice it and +still report the domain as running. Also trying to destroy the domain +through libvirt will fail. The only way to recover from such a situation +is to restart libvirt daemon. The problem is that even though libxl +report LIBXL_EVENT_TYPE_DOMAIN_DEATH, libvirt ignore it as all the +domain cleanup is done in a function actually destroying the domain. If +destroy is done outside of libvirt, there is no place where it would be +handled. + +Fix this by doing domain cleanup in LIBXL_EVENT_TYPE_DOMAIN_DEATH too. +To avoid doing it twice, add a ignoreDeathEvent flag +libxlDomainObjPrivate, set when the domain death is triggered by libvirt +itself. + +Signed-off-by: Marek Marczykowski-Górecki +Reviewed-by: Jim Fehlig +--- + src/libxl/libxl_domain.c | 71 ++++++++++++++++++++++++++++++++++++++-- + src/libxl/libxl_domain.h | 3 ++ + 2 files changed, 71 insertions(+), 3 deletions(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -555,6 +555,54 @@ libxlDomainShutdownThread(void *opaque) + virObjectUnref(cfg); + } + ++static void ++libxlDomainDeathThread(void *opaque) ++{ ++ struct libxlShutdownThreadInfo *shutdown_info = opaque; ++ virDomainObjPtr vm = NULL; ++ libxl_event *ev = shutdown_info->event; ++ libxlDriverPrivatePtr driver = shutdown_info->driver; ++ virObjectEventPtr dom_event = NULL; ++ libxlDriverConfigPtr cfg; ++ libxlDomainObjPrivatePtr priv; ++ ++ cfg = libxlDriverConfigGet(driver); ++ ++ vm = virDomainObjListFindByID(driver->domains, ev->domid); ++ if (!vm) { ++ /* vm->def->id already cleared, means the death was handled by the ++ * driver already */ ++ goto cleanup; ++ } ++ ++ priv = vm->privateData; ++ ++ if (priv->ignoreDeathEvent) { ++ priv->ignoreDeathEvent = false; ++ goto cleanup; ++ } ++ ++ if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) ++ goto cleanup; ++ ++ virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED); ++ dom_event = virDomainEventLifecycleNewFromObj(vm, ++ VIR_DOMAIN_EVENT_STOPPED, ++ VIR_DOMAIN_EVENT_STOPPED_DESTROYED); ++ libxlDomainCleanup(driver, vm); ++ if (!vm->persistent) ++ virDomainObjListRemove(driver->domains, vm); ++ libxlDomainObjEndJob(driver, vm); ++ ++ cleanup: ++ virDomainObjEndAPI(&vm); ++ virObjectEventStateQueue(driver->domainEventState, dom_event); ++ libxl_event_free(cfg->ctx, ev); ++ VIR_FREE(shutdown_info); ++ virObjectUnref(cfg); ++} ++ ++ + /* + * Handle previously registered domain event notification from libxenlight. + */ +@@ -566,8 +614,10 @@ libxlDomainEventHandler(void *data, VIR_ + struct libxlShutdownThreadInfo *shutdown_info = NULL; + virThread thread; + libxlDriverConfigPtr cfg; ++ int ret = -1; + +- if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { ++ if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN && ++ event->type != LIBXL_EVENT_TYPE_DOMAIN_DEATH) { + VIR_INFO("Unhandled event type %d", event->type); + goto error; + } +@@ -588,8 +638,14 @@ libxlDomainEventHandler(void *data, VIR_ + + shutdown_info->driver = driver; + shutdown_info->event = (libxl_event *)event; +- if (virThreadCreate(&thread, false, libxlDomainShutdownThread, +- shutdown_info) < 0) { ++ if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) ++ ret = virThreadCreate(&thread, false, libxlDomainShutdownThread, ++ shutdown_info); ++ else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) ++ ret = virThreadCreate(&thread, false, libxlDomainDeathThread, ++ shutdown_info); ++ ++ if (ret < 0) { + /* + * Not much we can do on error here except log it. + */ +@@ -711,14 +767,21 @@ libxlDomainDestroyInternal(libxlDriverPr + virDomainObjPtr vm) + { + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); ++ libxlDomainObjPrivatePtr priv = vm->privateData; + int ret = -1; + ++ /* Ignore next LIBXL_EVENT_TYPE_DOMAIN_DEATH as the caller will handle ++ * domain death appropriately already (having more info, like the reason). ++ */ ++ priv->ignoreDeathEvent = true; + /* Unlock virDomainObj during destroy, which can take considerable + * time on large memory domains. + */ + virObjectUnlock(vm); + ret = libxl_domain_destroy(cfg->ctx, vm->def->id, NULL); + virObjectLock(vm); ++ if (ret) ++ priv->ignoreDeathEvent = false; + + virObjectUnref(cfg); + return ret; +@@ -770,6 +833,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr + priv->deathW = NULL; + } + ++ priv->ignoreDeathEvent = false; ++ + if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback) + driver->inhibitCallback(false, driver->inhibitOpaque); + +--- a/src/libxl/libxl_domain.h ++++ b/src/libxl/libxl_domain.h +@@ -65,6 +65,9 @@ struct _libxlDomainObjPrivate { + /* console */ + virChrdevsPtr devs; + libxl_evgen_domain_death *deathW; ++ /* Flag to indicate the upcoming LIBXL_EVENT_TYPE_DOMAIN_DEATH is caused ++ * by libvirt and should not be handled separately */ ++ bool ignoreDeathEvent; + unsigned short migrationPort; + char *lockState; + diff -Nru libvirt-4.0.0/debian/patches/CVE-2021-4147-pre1.patch libvirt-4.0.0/debian/patches/CVE-2021-4147-pre1.patch --- libvirt-4.0.0/debian/patches/CVE-2021-4147-pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2021-4147-pre1.patch 2022-04-20 17:18:06.000000000 +0000 @@ -0,0 +1,226 @@ +Backport of: + +From 87a9d3a6b01baebdca33d95ad0e79781b6a46ca8 Mon Sep 17 00:00:00 2001 +From: Jim Fehlig +Date: Fri, 19 Feb 2021 16:29:10 -0700 +Subject: [PATCH] libxl: Fix domain shutdown + +Commit fa30ee04a2 caused a regression in normal domain shutown. +Initiating a shutdown from within the domain or via 'virsh shutdown' +does cause the guest OS running in the domain to shutdown, but libvirt +never reaps the domain so it is always shown in a running state until +calling 'virsh destroy'. + +The shutdown thread is also an internal user of the driver shutdown +machinery and eventually calls libxlDomainDestroyInternal where +the ignoreDeathEvent inhibitor is set, but running in a thread +introduces the possibility of racing with the death event from +libxl. This can be prevented by setting ignoreDeathEvent before +running the shutdown thread. + +An additional improvement is to handle the destroy event synchronously +instead of spawning a thread. The time consuming aspects of destroying +a domain have been completed when the destroy event is delivered. + +Signed-off-by: Jim Fehlig +Reviewed-by: Michal Privoznik +--- + src/libxl/libxl_domain.c | 120 +++++++++++++++++++-------------------- + 1 file changed, 57 insertions(+), 63 deletions(-) + +--- a/src/libxl/libxl_domain.c ++++ b/src/libxl/libxl_domain.c +@@ -427,6 +427,7 @@ virDomainDefParserConfig libxlDomainDefP + struct libxlShutdownThreadInfo + { + libxlDriverPrivatePtr driver; ++ virDomainObjPtr vm; + libxl_event *event; + }; + +@@ -435,7 +436,7 @@ static void + libxlDomainShutdownThread(void *opaque) + { + struct libxlShutdownThreadInfo *shutdown_info = opaque; +- virDomainObjPtr vm = NULL; ++ virDomainObjPtr vm = shutdown_info->vm; + libxl_event *ev = shutdown_info->event; + libxlDriverPrivatePtr driver = shutdown_info->driver; + virObjectEventPtr dom_event = NULL; +@@ -444,12 +445,6 @@ libxlDomainShutdownThread(void *opaque) + + cfg = libxlDriverConfigGet(driver); + +- vm = virDomainObjListFindByIDRef(driver->domains, ev->domid); +- if (!vm) { +- VIR_INFO("Received event for unknown domain ID %d", ev->domid); +- goto cleanup; +- } +- + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + +@@ -556,34 +551,18 @@ libxlDomainShutdownThread(void *opaque) + } + + static void +-libxlDomainDeathThread(void *opaque) ++libxlDomainHandleDeath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) + { +- struct libxlShutdownThreadInfo *shutdown_info = opaque; +- virDomainObjPtr vm = NULL; +- libxl_event *ev = shutdown_info->event; +- libxlDriverPrivatePtr driver = shutdown_info->driver; + virObjectEventPtr dom_event = NULL; +- libxlDriverConfigPtr cfg; +- libxlDomainObjPrivatePtr priv; +- +- cfg = libxlDriverConfigGet(driver); +- +- vm = virDomainObjListFindByID(driver->domains, ev->domid); +- if (!vm) { +- /* vm->def->id already cleared, means the death was handled by the +- * driver already */ +- goto cleanup; +- } +- +- priv = vm->privateData; ++ libxlDomainObjPrivatePtr priv = vm->privateData; + + if (priv->ignoreDeathEvent) { + priv->ignoreDeathEvent = false; +- goto cleanup; ++ return; + } + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) +- goto cleanup; ++ return; + + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED); + dom_event = virDomainEventLifecycleNewFromObj(vm, +@@ -594,12 +573,7 @@ libxlDomainDeathThread(void *opaque) + virDomainObjListRemove(driver->domains, vm); + libxlDomainObjEndJob(driver, vm); + +- cleanup: +- virDomainObjEndAPI(&vm); + virObjectEventStateQueue(driver->domainEventState, dom_event); +- libxl_event_free(cfg->ctx, ev); +- VIR_FREE(shutdown_info); +- virObjectUnref(cfg); + } + + +@@ -611,15 +585,13 @@ libxlDomainEventHandler(void *data, VIR_ + { + libxlDriverPrivatePtr driver = data; + libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; +- struct libxlShutdownThreadInfo *shutdown_info = NULL; +- virThread thread; ++ virDomainObjPtr vm = NULL; + libxlDriverConfigPtr cfg; +- int ret = -1; + + if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN && + event->type != LIBXL_EVENT_TYPE_DOMAIN_DEATH) { + VIR_INFO("Unhandled event type %d", event->type); +- goto error; ++ goto cleanup; + } + + /* +@@ -627,43 +599,67 @@ libxlDomainEventHandler(void *data, VIR_ + * after calling libxl_domain_suspend() are handled by its callers. + */ + if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND) +- goto error; ++ goto cleanup; + +- /* +- * Start a thread to handle shutdown. We don't want to be tying up +- * libxl's event machinery by doing a potentially lengthy shutdown. +- */ +- if (VIR_ALLOC(shutdown_info) < 0) +- goto error; ++ vm = virDomainObjListFindByID(driver->domains, event->domid); ++ if (!vm) { ++ /* Nothing to do if we can't find the virDomainObj */ ++ goto cleanup; ++ } + +- shutdown_info->driver = driver; +- shutdown_info->event = (libxl_event *)event; +- if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) +- ret = virThreadCreate(&thread, false, libxlDomainShutdownThread, +- shutdown_info); +- else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) +- ret = virThreadCreate(&thread, false, libxlDomainDeathThread, +- shutdown_info); ++ if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { ++ libxlDomainObjPrivatePtr priv = vm->privateData; ++ struct libxlShutdownThreadInfo *shutdown_info = NULL; ++ virThread thread; ++ char *name = NULL; + +- if (ret < 0) { + /* +- * Not much we can do on error here except log it. ++ * Start a thread to handle shutdown. We don't want to be tying up ++ * libxl's event machinery by doing a potentially lengthy shutdown. + */ +- VIR_ERROR(_("Failed to create thread to handle domain shutdown")); +- goto error; +- } ++ if (VIR_ALLOC_N(shutdown_info, 1) < 0) ++ goto cleanup; + +- /* +- * libxlShutdownThreadInfo and libxl_event are freed in shutdown thread +- */ +- return; ++ shutdown_info->driver = driver; ++ shutdown_info->vm = vm; ++ shutdown_info->event = (libxl_event *)event; ++ if (virAsprintf(&name, "ev-%d", event->domid) < 0) ++ goto cleanup; ++ /* ++ * Cleanup will be handled by the shutdown thread. ++ * Ignore the forthcoming death event from libxl ++ */ ++ priv->ignoreDeathEvent = true; ++ if (virThreadCreateFull(&thread, false, libxlDomainShutdownThread, ++ name, false, shutdown_info) < 0) { ++ priv->ignoreDeathEvent = false; ++ /* ++ * Not much we can do on error here except log it. ++ */ ++ VIR_ERROR(_("Failed to create thread to handle domain shutdown")); ++ VIR_FREE(shutdown_info); ++ VIR_FREE(name); ++ goto cleanup; ++ } ++ /* ++ * virDomainObjEndAPI is called in the shutdown thread, where ++ * libxlShutdownThreadInfo and libxl_event are also freed. ++ */ ++ return; ++ } else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) { ++ /* ++ * On death the domain is cleaned up from Xen's perspective. ++ * Cleanup on the libvirt side can be done synchronously. ++ */ ++ libxlDomainHandleDeath(driver, vm); ++ } + +- error: ++ cleanup: ++ virDomainObjEndAPI(&vm); + cfg = libxlDriverConfigGet(driver); + /* Cast away any const */ + libxl_event_free(cfg->ctx, (libxl_event *)event); + virObjectUnref(cfg); +- VIR_FREE(shutdown_info); + } + + void diff -Nru libvirt-4.0.0/debian/patches/CVE-2022-0897.patch libvirt-4.0.0/debian/patches/CVE-2022-0897.patch --- libvirt-4.0.0/debian/patches/CVE-2022-0897.patch 1970-01-01 00:00:00.000000000 +0000 +++ libvirt-4.0.0/debian/patches/CVE-2022-0897.patch 2022-04-20 17:17:54.000000000 +0000 @@ -0,0 +1,47 @@ +From a4947e8f63c3e6b7b067b444f3d6cf674c0d7f36 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +Date: Tue, 8 Mar 2022 17:28:38 +0000 +Subject: [PATCH] nwfilter: fix crash when counting number of network filters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The virNWFilterObjListNumOfNWFilters method iterates over the +driver->nwfilters, accessing virNWFilterObj instances. As such +it needs to be protected against concurrent modification of +the driver->nwfilters object. + +This API allows unprivileged users to connect, so users with +read-only access to libvirt can cause a denial of service +crash if they are able to race with a call of virNWFilterUndefine. +Since network filters are usually statically defined, this is +considered a low severity problem. + +This is assigned CVE-2022-0897. + +Reviewed-by: Eric Blake +Signed-off-by: Daniel P. Berrangé +--- + src/nwfilter/nwfilter_driver.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/src/nwfilter/nwfilter_driver.c ++++ b/src/nwfilter/nwfilter_driver.c +@@ -438,11 +438,15 @@ nwfilterLookupByName(virConnectPtr conn, + static int + nwfilterConnectNumOfNWFilters(virConnectPtr conn) + { ++ int ret; + if (virConnectNumOfNWFiltersEnsureACL(conn) < 0) + return -1; + +- return virNWFilterObjListNumOfNWFilters(driver->nwfilters, conn, +- virConnectNumOfNWFiltersCheckACL); ++ nwfilterDriverLock(); ++ ret = virNWFilterObjListNumOfNWFilters(driver->nwfilters, conn, ++ virConnectNumOfNWFiltersCheckACL); ++ nwfilterDriverUnlock(); ++ return ret; + } + + diff -Nru libvirt-4.0.0/debian/patches/series libvirt-4.0.0/debian/patches/series --- libvirt-4.0.0/debian/patches/series 2021-11-18 09:24:01.000000000 +0000 +++ libvirt-4.0.0/debian/patches/series 2022-04-20 17:17:50.000000000 +0000 @@ -142,3 +142,19 @@ ubuntu/lp1915811-fix-numa-topology.patch ubuntu/lp-1927519-virt-aa-helper-Purge-profile-if-corrupted.patch ubuntu/skip-new-pdwtags.patch +CVE-2020-25637-1.patch +CVE-2020-25637-2.patch +CVE-2020-25637-3.patch +CVE-2020-25637-4.patch +CVE-2021-3631.patch +CVE-2021-3975.patch +CVE-2021-4147-pre0.patch +CVE-2021-4147-pre1.patch +CVE-2021-4147-1.patch +CVE-2021-4147-2.patch +CVE-2021-4147-3.patch +CVE-2021-4147-4.patch +CVE-2021-4147-5.patch +CVE-2021-4147-6pre1.patch +CVE-2021-4147-6.patch +CVE-2022-0897.patch