From e152ee4aeefc89e1d5327f2f28fb79ef22e8e48e Mon Sep 17 00:00:00 2001 From: xzyang Date: Thu, 23 Dec 2021 17:37:59 +0800 Subject: [PATCH] update to libvirt-4.5.0-36.el7_9.5.src.rpm Signed-off-by: xzyang --- ...leak-DIR-on-OOM-in-virDMSanitizepath.patch | 50 ++ ...acvtap-names-when-formatting-parsing.patch | 145 +++++ ...emu-Create-multipath-targets-for-PRs.patch | 166 ++++++ ...ent-set-ifname-to-NULL-after-freeing.patch | 42 ++ ...-agent-job-in-qemuDomainSetTimeAgent.patch | 43 ++ ...rt-for-filtering-acls-by-uint-params.patch | 104 ++++ ...t-rpc-gendispatch-handle-empty-flags.patch | 51 ++ ...agent-in-virDomainInterfaceAddresses.patch | 74 +++ ...rIsDevMapperDevice-to-virdevmapper.c.patch | 189 +++++++ libvirt-util-Rework-virStringListAdd.patch | 145 +++++ ...uce-macro-for-automatic-string-lists.patch | 94 ++++ ...getsImpl-Check-for-dm-major-properly.patch | 66 +++ ...etTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch | 79 +++ ...ect-length-when-copying-into-dm.name.patch | 63 +++ ...pper-Don-t-cache-device-mapper-major.patch | 107 ++++ ...-libdevmapper-to-obtain-dependencies.patch | 496 ++++++++++++++++++ ...kernel-without-device-mapper-support.patch | 88 ++++ ...rors-when-opening-dev-mapper-control.patch | 95 ++++ ...stat-comparison-in-virDMSanitizepath.patch | 49 ++ ...two-WITH_DEVMAPPER-sections-together.patch | 73 +++ libvirt.spec | 53 +- 21 files changed, 2271 insertions(+), 1 deletion(-) create mode 100644 libvirt-RHEL-virdevmapper-Don-t-leak-DIR-on-OOM-in-virDMSanitizepath.patch create mode 100644 libvirt-conf-properly-clear-out-autogenerated-macvtap-names-when-formatting-parsing.patch create mode 100644 libvirt-qemu-Create-multipath-targets-for-PRs.patch create mode 100644 libvirt-qemu-agent-set-ifname-to-NULL-after-freeing.patch create mode 100644 libvirt-qemu-end-the-agent-job-in-qemuDomainSetTimeAgent.patch create mode 100644 libvirt-rpc-add-support-for-filtering-acls-by-uint-params.patch create mode 100644 libvirt-rpc-gendispatch-handle-empty-flags.patch create mode 100644 libvirt-rpc-require-write-acl-for-guest-agent-in-virDomainInterfaceAddresses.patch create mode 100644 libvirt-util-Move-virIsDevMapperDevice-to-virdevmapper.c.patch create mode 100644 libvirt-util-Rework-virStringListAdd.patch create mode 100644 libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch create mode 100644 libvirt-virDevMapperGetTargetsImpl-Check-for-dm-major-properly.patch create mode 100644 libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch create mode 100644 libvirt-virDevMapperGetTargetsImpl-Use-correct-length-when-copying-into-dm.name.patch create mode 100644 libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch create mode 100644 libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch create mode 100644 libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch create mode 100644 libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch create mode 100644 libvirt-virdevmapper-fix-stat-comparison-in-virDMSanitizepath.patch create mode 100644 libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch diff --git a/libvirt-RHEL-virdevmapper-Don-t-leak-DIR-on-OOM-in-virDMSanitizepath.patch b/libvirt-RHEL-virdevmapper-Don-t-leak-DIR-on-OOM-in-virDMSanitizepath.patch new file mode 100644 index 0000000..582714f --- /dev/null +++ b/libvirt-RHEL-virdevmapper-Don-t-leak-DIR-on-OOM-in-virDMSanitizepath.patch @@ -0,0 +1,50 @@ +From 357fc40405c4967654972ecdf0b210fed885185d Mon Sep 17 00:00:00 2001 +Message-Id: <357fc40405c4967654972ecdf0b210fed885185d@dist-git> +From: Michal Privoznik +Date: Fri, 19 Mar 2021 11:51:58 +0100 +Subject: [PATCH] RHEL: virdevmapper: Don't leak DIR on OOM in + virDMSanitizepath() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is a RHEL only patch, because it fixes a small issue in one +of backported commits that was basically rewritten from scratch +(v4.5.0-400-g6bf725c07c). + +During the rewrite I've introduced a problem, in which opened +/dev/mapper/ directory can leak if OOM happened afterwards. + +Fixes: 6bf725c07c25b56937c494b6c7e83e6ca27ec54c +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index dcb3c08df5..33cde6ca0c 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -216,7 +216,7 @@ virDMSanitizepath(const char *path) + VIR_AUTOFREE(char *) tmp = NULL; + + if (virAsprintf(&tmp, DEV_DM_DIR "/%s", ent->d_name) < 0) +- return NULL; ++ goto cleanup; + + if (stat(tmp, &sb[1]) == 0 && + sb[0].st_rdev == sb[1].st_rdev) { +@@ -225,6 +225,7 @@ virDMSanitizepath(const char *path) + } + } + ++ cleanup: + virDirClose(&dh); + return ret; + } +-- +2.31.0 + diff --git a/libvirt-conf-properly-clear-out-autogenerated-macvtap-names-when-formatting-parsing.patch b/libvirt-conf-properly-clear-out-autogenerated-macvtap-names-when-formatting-parsing.patch new file mode 100644 index 0000000..d52f188 --- /dev/null +++ b/libvirt-conf-properly-clear-out-autogenerated-macvtap-names-when-formatting-parsing.patch @@ -0,0 +1,145 @@ +From bcce526443723e7cf3272f67c4d34b6925b63209 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Laine Stump +Date: Sun, 13 Sep 2020 10:26:25 -0400 +Subject: [PATCH] conf: properly clear out autogenerated macvtap names when + formatting/parsing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Back when macvtap support was added in commit 315baab9443 in Feb. 2010 +(libvirt-0.7.7), it was setup to autogenerate a name for the device if +one wasn't supplied, in the pattern "macvtap%d" (or "macvlan%d"), +similar to the way an unspecified standard tap device name will lead +to an autogenerated "vnet%d". + +As a matter of fact, in commit ca1b7cc8e45 added in May 2010, the code +was changed to *always* ignore a supplied device name for macvtap +interfaces by deleting *any* name immediately during the +parsing (this was intended to prevent one domain which had failed to +completely start from deleting the macvtap device of another domain +which had subsequently been provided the same device name (this will +seem mildly ironic later). This was later fixed to only clear the +device name when inactive XML was being parsed. HOWEVER - this was +only done if the xml was - autogenerated +names were not cleared for (which could +also result in a macvtap device). + +Although the names of "vnetX" tap devices had always been +automatically cleared when parsing (see commit d1304583d +from July 2008 (!)), at the time macvtap support was added, both vnetX +and macvtapX device names were always included when formatting the +XML. + +Then in commit a8be259d0cc (July 2011, libvirt-0.9.4), +formatting was changed to also clear out "vnetX" device names during +XML formatting as well. However the same treatment wasn't given to +"macvtapX". + +Now in 2020, there has been a report that a failed migration leads to +the macvtap device of some other unrelated guest on the destination +host losing its network connectivity. It was determined that this was +due to the domain XML in the migration containing a macvtap device +name, e.g. "macvtap0", that was already in use by the other guest on +the destination. Normally this wouldn't be a problem, because libvirt +would see that the device was already in use, and then find a +different unused name. But in this case, other external problems were +causing the migration to fail prior to selecting a macvtap device and +successfully opening it, and during error recovery, qemuProcessStop() +was called, which went through all def->nets objects and (if they were +macvtap) deleted the device specified in net->ifname; since libvirt +hadn't gotten to the point of replacing the incoming "macvtap0" with +the name of a device it actually created for this guest, that meant +that "macvtap0" was deleted, *even though it was currently in use by a +different guest*! + +Whew! + +So, it turns out that when formatting "migratable" XML, "vnetX" +devices are omitted, just as when formatting "inactive" XML. By making +the code in both interface parsing and formatting consistent for +"vnetX", "macvtapX", and "macvlanX", we can thus make sure that the +autogenerated (and unneeded / completely *not* wanted) macvtap device +name will not be sent with the migration XML. This way when a +migration fails, net->ifname will be NULL, and libvirt won't have any +device to try and (erroneously) delete. + +Signed-off-by: Laine Stump +Reviewed-by: Daniel Henrique Barboza +(cherry picked from commit 282d135ddbb7203565cd5527b451469b14953994) + +https://bugzilla.redhat.com/1868549 + +Conflicts: src/conf/domain_conf.c - glib is now used upstream. Also + upstream has added managed_tap, which changes the context of one + hunk, and the position+context+exact content of another. + +Signed-off-by: Laine Stump +Message-Id: <20200913142625.21235-1-laine@redhat.com> +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 8bd527cfa1..75d099fdc7 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -11411,13 +11411,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, + } else if (!ifname && + virXMLNodeNameEqual(cur, "target")) { + ifname = virXMLPropString(cur, "dev"); +- if (ifname && +- (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) && +- (STRPREFIX(ifname, VIR_NET_GENERATED_TAP_PREFIX) || +- (prefix && STRPREFIX(ifname, prefix)))) { +- /* An auto-generated target name, blank it out */ +- VIR_FREE(ifname); +- } + } else if ((!ifname_guest || !ifname_guest_actual) && + virXMLNodeNameEqual(cur, "guest")) { + ifname_guest = virXMLPropString(cur, "dev"); +@@ -11708,14 +11701,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, + + def->data.direct.linkdev = dev; + dev = NULL; +- +- if (ifname && +- flags & VIR_DOMAIN_DEF_PARSE_INACTIVE && +- (STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) || +- STRPREFIX(ifname, VIR_NET_GENERATED_MACVLAN_PREFIX))) { +- VIR_FREE(ifname); +- } +- + break; + + case VIR_DOMAIN_NET_TYPE_HOSTDEV: +@@ -11757,6 +11742,15 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, + def->domain_name = domain_name; + domain_name = NULL; + } ++ if (ifname && ++ (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) && ++ (STRPREFIX(ifname, VIR_NET_GENERATED_TAP_PREFIX) || ++ STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) || ++ STRPREFIX(ifname, VIR_NET_GENERATED_MACVLAN_PREFIX) || ++ (prefix && STRPREFIX(ifname, prefix)))) { ++ /* An auto-generated target name, blank it out */ ++ VIR_FREE(ifname); ++ } + if (ifname != NULL) { + def->ifname = ifname; + ifname = NULL; +@@ -25394,6 +25388,8 @@ virDomainNetDefFormat(virBufferPtr buf, + if (def->ifname && + !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && + (STRPREFIX(def->ifname, VIR_NET_GENERATED_TAP_PREFIX) || ++ STRPREFIX(def->ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) || ++ STRPREFIX(def->ifname, VIR_NET_GENERATED_MACVLAN_PREFIX) || + (prefix && STRPREFIX(def->ifname, prefix))))) { + /* Skip auto-generated target names for inactive config. */ + virBufferEscapeString(buf, "\n", def->ifname); +-- +2.28.0 + diff --git a/libvirt-qemu-Create-multipath-targets-for-PRs.patch b/libvirt-qemu-Create-multipath-targets-for-PRs.patch new file mode 100644 index 0000000..2684b7c --- /dev/null +++ b/libvirt-qemu-Create-multipath-targets-for-PRs.patch @@ -0,0 +1,166 @@ +From d415286e93faf2f9c4fa5c5c589aa8d3f433d01d Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Fri, 19 Jun 2020 11:43:13 +0200 +Subject: [PATCH] qemu: Create multipath targets for PRs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If a disk has persistent reservations enabled, qemu-pr-helper +might open not only /dev/mapper/control but also individual +targets of the multipath device. We are already querying for them +in CGroups, but now we have to create them in the namespace too. +This was brought up in [1]. + +1: https://bugzilla.redhat.com/show_bug.cgi?id=1711045#c61 + +Signed-off-by: Michal Privoznik +Tested-by: Lin Ma +Reviewed-by: Jim Fehlig +(cherry picked from commit a30078cb832646177defd256e77c632905f1e6d0) + +https://bugzilla.redhat.com/show_bug.cgi?id=1839992 + +Conflicts: +- src/qemu/qemu_domain.c: Well, the upstream has NVMe and + downstream doesn't. So the functions I'm modifying look + different in the upstream. Tough luck. +- src/util/virdevmapper.h: The upstream moved to gnulib macros + (G_GNUC_NO_INLINE in this case). But since I'm removing changes + to qemuhotplugtest below, this particular change wasn't needed. + The include of "internal.h" is though (because of next commit). +- tests/qemuhotplugmock.c: +- tests/qemuhotplugtest.c: I'm completely dropping these two + changes because the upstream went a long way since and these + are only tests. + +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_domain.c | 59 ++++++++++++++++++++++++++++------------- + src/util/virdevmapper.h | 2 ++ + 2 files changed, 42 insertions(+), 19 deletions(-) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index b4792c9476..489e20a28a 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -57,6 +57,7 @@ + #include "secret_util.h" + #include "logging/log_manager.h" + #include "locking/domain_lock.h" ++#include "virdevmapper.h" + + #ifdef MAJOR_IN_MKDEV + # include +@@ -11325,13 +11326,29 @@ qemuDomainSetupDisk(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED, + int ret = -1; + + for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) { ++ VIR_AUTOSTRINGLIST targetPaths = NULL; ++ size_t i; ++ + if (!next->path || !virStorageSourceIsLocalStorage(next)) { + /* Not creating device. Just continue. */ + continue; + } + + if (qemuDomainCreateDevice(next->path, data, false) < 0) +- goto cleanup; ++ return -1; ++ ++ if (virDevMapperGetTargets(next->path, &targetPaths) < 0 && ++ errno != ENOSYS && errno != EBADF) { ++ virReportSystemError(errno, ++ _("Unable to get devmapper targets for %s"), ++ next->path); ++ return -1; ++ } ++ ++ for (i = 0; targetPaths && targetPaths[i]; i++) { ++ if (qemuDomainCreateDevice(targetPaths[i], data, false) < 0) ++ return -1; ++ } + } + + /* qemu-pr-helper might require access to /dev/mapper/control. */ +@@ -12342,39 +12359,43 @@ qemuDomainNamespaceSetupDisk(virDomainObjPtr vm, + virStorageSourcePtr src) + { + virStorageSourcePtr next; +- const char **paths = NULL; ++ VIR_AUTOSTRINGLIST paths = NULL; + size_t npaths = 0; +- char *dmPath = NULL; +- int ret = -1; +- +- if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) +- return 0; + + for (next = src; virStorageSourceIsBacking(next); next = next->backingStore) { ++ VIR_AUTOSTRINGLIST targetPaths = NULL; ++ + if (virStorageSourceIsEmpty(next) || + !virStorageSourceIsLocalStorage(next)) { + /* Not creating device. Just continue. */ + continue; + } + +- if (VIR_APPEND_ELEMENT_COPY(paths, npaths, next->path) < 0) +- goto cleanup; ++ if (virStringListAdd(&paths, next->path) < 0) ++ return -1; ++ ++ if (virDevMapperGetTargets(next->path, &targetPaths) < 0 && ++ errno != ENOSYS && errno != EBADF) { ++ virReportSystemError(errno, ++ _("Unable to get devmapper targets for %s"), ++ next->path); ++ return -1; ++ } ++ ++ if (virStringListMerge(&paths, &targetPaths) < 0) ++ return -1; + } + + /* qemu-pr-helper might require access to /dev/mapper/control. */ + if (src->pr && +- (VIR_STRDUP(dmPath, DEVICE_MAPPER_CONTROL_PATH) < 0 || +- VIR_APPEND_ELEMENT_COPY(paths, npaths, dmPath) < 0)) +- goto cleanup; ++ virStringListAdd(&paths, DEVICE_MAPPER_CONTROL_PATH) < 0) ++ return -1; + +- if (qemuDomainNamespaceMknodPaths(vm, paths, npaths) < 0) +- goto cleanup; ++ npaths = virStringListLength((const char **) paths); ++ if (qemuDomainNamespaceMknodPaths(vm, (const char **) paths, npaths) < 0) ++ return -1; + +- ret = 0; +- cleanup: +- VIR_FREE(dmPath); +- VIR_FREE(paths); +- return ret; ++ return 0; + } + + +diff --git a/src/util/virdevmapper.h b/src/util/virdevmapper.h +index 34d6655e77..42a7828fde 100644 +--- a/src/util/virdevmapper.h ++++ b/src/util/virdevmapper.h +@@ -24,6 +24,8 @@ + #ifndef __VIR_DEVMAPPER_H__ + # define __VIR_DEVMAPPER_H__ + ++#include "internal.h" ++ + int + virDevMapperGetTargets(const char *path, + char ***devPaths); +-- +2.27.0 + diff --git a/libvirt-qemu-agent-set-ifname-to-NULL-after-freeing.patch b/libvirt-qemu-agent-set-ifname-to-NULL-after-freeing.patch new file mode 100644 index 0000000..2f854f5 --- /dev/null +++ b/libvirt-qemu-agent-set-ifname-to-NULL-after-freeing.patch @@ -0,0 +1,42 @@ +From 0293adf3792eeb797c498feefa178309d28c4803 Mon Sep 17 00:00:00 2001 +Message-Id: <0293adf3792eeb797c498feefa178309d28c4803@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 30 Sep 2020 17:38:15 +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 +(cherry picked from commit a63b48c5ecef077bf0f909a85f453a605600cf05) +Signed-off-by: Ján Tomko + +Conflicts: src/qemu/qemu_agent.c + Commit ee247e1d which switched virStringListFree + to g_strfreev is missing downstream. +Message-Id: +Reviewed-by: Jiri Denemark +--- + src/qemu/qemu_agent.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c +index d6fd02a4b6..35bef8636d 100644 +--- a/src/qemu/qemu_agent.c ++++ b/src/qemu/qemu_agent.c +@@ -2055,6 +2055,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 */ +-- +2.28.0 + diff --git a/libvirt-qemu-end-the-agent-job-in-qemuDomainSetTimeAgent.patch b/libvirt-qemu-end-the-agent-job-in-qemuDomainSetTimeAgent.patch new file mode 100644 index 0000000..5b6dced --- /dev/null +++ b/libvirt-qemu-end-the-agent-job-in-qemuDomainSetTimeAgent.patch @@ -0,0 +1,43 @@ +From 34188b9f1bb1e53d2372e02c0388430a85f4cad5 Mon Sep 17 00:00:00 2001 +Message-Id: <34188b9f1bb1e53d2372e02c0388430a85f4cad5@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Thu, 18 Jun 2020 12:31:46 +0200 +Subject: [PATCH] qemu: end the agent job in qemuDomainSetTimeAgent +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This function grabs an agent job but ends a monitor job. +End the agent job instead. + +https://bugzilla.redhat.com/show_bug.cgi?id=1792723 + +Signed-off-by: Ján Tomko +Reported-by: Dan Zheng +Fixes: e005c95f56fee9ed780be7f8db103d690bd34cbd +(cherry picked from commit d61f95cf6a6fbd564e104c168d325581acd9cd8d) +Signed-off-by: Ján Tomko + +https://bugzilla.redhat.com/show_bug.cgi?id=1844952 +Message-Id: <7fa0860281f9f2a08acf488784738f54a8158e63.1592476262.git.jtomko@redhat.com> +Reviewed-by: Michal Privoznik +--- + src/qemu/qemu_driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index e1d9bbae99..449d869f98 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -19478,7 +19478,7 @@ qemuDomainSetTimeAgent(virQEMUDriverPtr driver, + qemuDomainObjExitAgent(vm, agent); + + endjob: +- qemuDomainObjEndJob(driver, vm); ++ qemuDomainObjEndAgentJob(vm); + return ret; + } + +-- +2.27.0 + diff --git a/libvirt-rpc-add-support-for-filtering-acls-by-uint-params.patch b/libvirt-rpc-add-support-for-filtering-acls-by-uint-params.patch new file mode 100644 index 0000000..59b6ef0 --- /dev/null +++ b/libvirt-rpc-add-support-for-filtering-acls-by-uint-params.patch @@ -0,0 +1,104 @@ +From 08f8c359dd6a090c1d5668df9f09159c53b55366 Mon Sep 17 00:00:00 2001 +Message-Id: <08f8c359dd6a090c1d5668df9f09159c53b55366@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 30 Sep 2020 17:38:13 +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 +(cherry picked from commit 50864dcda191eb35732dbd80fb6ca251a6bba923) +Signed-off-by: Ján Tomko +Message-Id: <92146976a682e6cc7e1490bcc542e9155a0207fb.1601480224.git.jtomko@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/remote/remote_protocol.x | 3 +++ + src/rpc/gendispatch.pl | 21 ++++++++++++++++++++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 52b92334fa..c370755f68 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -3591,6 +3591,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. +@@ -3600,6 +3601,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: : + * +diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl +index c243ac200f..cec3736066 100755 +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -2093,10 +2093,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"; +@@ -2104,6 +2106,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}; +@@ -2137,6 +2142,9 @@ elsif ($mode eq "client") { + if ($checkflags) { + push @argdecls, "unsigned int flags"; + } ++ if (defined $paramtocheck) { ++ push @argdecls, "unsigned int " . $paramtocheck; ++ } + + my $ret; + my $pass; +@@ -2195,6 +2203,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") { +-- +2.28.0 + diff --git a/libvirt-rpc-gendispatch-handle-empty-flags.patch b/libvirt-rpc-gendispatch-handle-empty-flags.patch new file mode 100644 index 0000000..79cc7a1 --- /dev/null +++ b/libvirt-rpc-gendispatch-handle-empty-flags.patch @@ -0,0 +1,51 @@ +From 2d684ee7a1544d9f84727302cb0e174842f0eb9c Mon Sep 17 00:00:00 2001 +Message-Id: <2d684ee7a1544d9f84727302cb0e174842f0eb9c@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 30 Sep 2020 17:38:12 +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 +(cherry picked from commit 955029bd0ad7ef96000f529ac38204a8f4a96401) +Signed-off-by: Ján Tomko +Message-Id: +Reviewed-by: Jiri Denemark +--- + src/rpc/gendispatch.pl | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl +index a8b9f5aeca..c243ac200f 100755 +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -2101,7 +2101,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; + } + } +@@ -2185,7 +2185,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; +-- +2.28.0 + diff --git a/libvirt-rpc-require-write-acl-for-guest-agent-in-virDomainInterfaceAddresses.patch b/libvirt-rpc-require-write-acl-for-guest-agent-in-virDomainInterfaceAddresses.patch new file mode 100644 index 0000000..c440b2c --- /dev/null +++ b/libvirt-rpc-require-write-acl-for-guest-agent-in-virDomainInterfaceAddresses.patch @@ -0,0 +1,74 @@ +From 9c54ef7c05dce6b67d6f7ff8ba8b414612bbaed1 Mon Sep 17 00:00:00 2001 +Message-Id: <9c54ef7c05dce6b67d6f7ff8ba8b414612bbaed1@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 30 Sep 2020 17:38: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 +(cherry picked from commit e4116eaa44cb366b59f7fe98f4b88d04c04970ad) +Signed-off-by: Ján Tomko + +Conflicts: src/lxc/lxc_driver.c + The LXC implementation of the API was introduced + in libvirt 6.1.0, so it's not present downstream. + src/qemu/qemu_driver.c + Commit 5910b180 is not present downstream. +Message-Id: <7db63b4388d8b1fd096892e1465abcff99c6696a.1601480224.git.jtomko@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/libxl/libxl_driver.c | 2 +- + src/qemu/qemu_driver.c | 2 +- + src/remote/remote_protocol.x | 1 + + 3 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c +index 1eb63c5b64..d157a78bef 100644 +--- a/src/libxl/libxl_driver.c ++++ b/src/libxl/libxl_driver.c +@@ -6199,7 +6199,7 @@ libxlDomainInterfaceAddresses(virDomainPtr dom, + if (!(vm = libxlDomObjFromDomain(dom))) + goto cleanup; + +- if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0) ++ if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def, source) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 449d869f98..223583b5a7 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -20687,7 +20687,7 @@ qemuDomainInterfaceAddresses(virDomainPtr dom, + if (!(vm = qemuDomObjFromDomain(dom))) + goto cleanup; + +- if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def) < 0) ++ if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def, source) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index c370755f68..78208e5855 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -5997,6 +5997,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, + +-- +2.28.0 + diff --git a/libvirt-util-Move-virIsDevMapperDevice-to-virdevmapper.c.patch b/libvirt-util-Move-virIsDevMapperDevice-to-virdevmapper.c.patch new file mode 100644 index 0000000..e754269 --- /dev/null +++ b/libvirt-util-Move-virIsDevMapperDevice-to-virdevmapper.c.patch @@ -0,0 +1,189 @@ +From a7197541f467bfd39d5504c438a90ef00ef0bc1e Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Fri, 19 Jun 2020 11:43:14 +0200 +Subject: [PATCH] util: Move virIsDevMapperDevice() to virdevmapper.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When introducing virdevmapper.c (in v4.3.0-rc1~427) I didn't +realize there is a function that calls in devmapper. The function +is called virIsDevMapperDevice() and lives in virutil.c. Now that +we have a special file for handling devmapper move it there. + +Signed-off-by: Michal Privoznik +Reviewed-by: Jiri Denemark +(cherry picked from commit dfa0e118f745fe3f4fe95975c6100f0fc6d788be) + +https://bugzilla.redhat.com/show_bug.cgi?id=1839992 + +Conflicts: +- src/libvirt_private.syms: Context, the downstream still has + virIsSUID() which was removed in upstream commit of v5.7.0-rc1~351 +- src/util/virdevmapper.h: Context, the downstream code hasn't + switched to #pragma once and still uses #endif. +- src/util/virutil.c: Again, context. + +Signed-off-by: Michal Privoznik +Message-Id: <31b696f526d21c5ce61b10ebe2c77c8fd0557ccc.1592559697.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + src/libvirt_private.syms | 2 +- + src/storage/parthelper.c | 2 +- + src/storage/storage_backend_disk.c | 1 + + src/util/virdevmapper.c | 24 ++++++++++++++++++++++++ + src/util/virdevmapper.h | 2 ++ + src/util/virutil.c | 23 ----------------------- + src/util/virutil.h | 2 -- + 7 files changed, 29 insertions(+), 27 deletions(-) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 3e5448af94..ef78b290db 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1716,6 +1716,7 @@ virDBusSetSharedBus; + + # util/virdevmapper.h + virDevMapperGetTargets; ++virIsDevMapperDevice; + + + # util/virdnsmasq.h +@@ -3132,7 +3133,6 @@ virHexToBin; + virHostGetDRMRenderNode; + virHostHasIOMMU; + virIndexToDiskName; +-virIsDevMapperDevice; + virIsSUID; + virMemoryLimitIsSet; + virMemoryLimitTruncate; +diff --git a/src/storage/parthelper.c b/src/storage/parthelper.c +index afdaa1cee2..d098356164 100644 +--- a/src/storage/parthelper.c ++++ b/src/storage/parthelper.c +@@ -40,11 +40,11 @@ + #include + #include + +-#include "virutil.h" + #include "virfile.h" + #include "c-ctype.h" + #include "virstring.h" + #include "virgettext.h" ++#include "virdevmapper.h" + + /* we don't need to include the full internal.h just for this */ + #define STREQ(a, b) (strcmp(a, b) == 0) +diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backend_disk.c +index c638e2db25..742510d986 100644 +--- a/src/storage/storage_backend_disk.c ++++ b/src/storage/storage_backend_disk.c +@@ -36,6 +36,7 @@ + #include "virfile.h" + #include "configmake.h" + #include "virstring.h" ++#include "virdevmapper.h" + + #define VIR_FROM_THIS VIR_FROM_STORAGE + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index a360c3e677..944baad562 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -218,3 +218,27 @@ virDevMapperGetTargets(const char *path ATTRIBUTE_UNUSED, + return -1; + } + #endif /* ! WITH_DEVMAPPER */ ++ ++ ++#if WITH_DEVMAPPER ++bool ++virIsDevMapperDevice(const char *dev_name) ++{ ++ struct stat buf; ++ ++ if (!stat(dev_name, &buf) && ++ S_ISBLK(buf.st_mode) && ++ dm_is_dm_major(major(buf.st_rdev))) ++ return true; ++ ++ return false; ++} ++ ++#else /* ! WITH_DEVMAPPER */ ++ ++bool ++virIsDevMapperDevice(const char *dev_name G_GNUC_UNUSED) ++{ ++ return false; ++} ++#endif /* ! WITH_DEVMAPPER */ +diff --git a/src/util/virdevmapper.h b/src/util/virdevmapper.h +index 42a7828fde..78dc47e888 100644 +--- a/src/util/virdevmapper.h ++++ b/src/util/virdevmapper.h +@@ -30,4 +30,6 @@ int + virDevMapperGetTargets(const char *path, + char ***devPaths); + ++bool ++virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1); + #endif /* __VIR_DEVMAPPER_H__ */ +diff --git a/src/util/virutil.c b/src/util/virutil.c +index fd70df120b..e803fee993 100644 +--- a/src/util/virutil.c ++++ b/src/util/virutil.c +@@ -44,9 +44,6 @@ + #include + #include + +-#if WITH_DEVMAPPER +-# include +-#endif + + #include + #ifdef HAVE_GETPWUID_R +@@ -1620,26 +1617,6 @@ void virWaitForDevices(void) + {} + #endif + +-#if WITH_DEVMAPPER +-bool +-virIsDevMapperDevice(const char *dev_name) +-{ +- struct stat buf; +- +- if (!stat(dev_name, &buf) && +- S_ISBLK(buf.st_mode) && +- dm_is_dm_major(major(buf.st_rdev))) +- return true; +- +- return false; +-} +-#else +-bool virIsDevMapperDevice(const char *dev_name ATTRIBUTE_UNUSED) +-{ +- return false; +-} +-#endif +- + bool + virValidateWWN(const char *wwn) + { +diff --git a/src/util/virutil.h b/src/util/virutil.h +index b0ee8329e2..dbd6a40bce 100644 +--- a/src/util/virutil.h ++++ b/src/util/virutil.h +@@ -152,8 +152,6 @@ int virGetUserID(const char *name, + int virGetGroupID(const char *name, + gid_t *gid) ATTRIBUTE_RETURN_CHECK; + +-bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1); +- + bool virValidateWWN(const char *wwn); + + int virGetDeviceID(const char *path, +-- +2.27.0 + diff --git a/libvirt-util-Rework-virStringListAdd.patch b/libvirt-util-Rework-virStringListAdd.patch new file mode 100644 index 0000000..da41814 --- /dev/null +++ b/libvirt-util-Rework-virStringListAdd.patch @@ -0,0 +1,145 @@ +From 4727de9e9048ffa25784eb0cd536a13ac9644529 Mon Sep 17 00:00:00 2001 +Message-Id: <4727de9e9048ffa25784eb0cd536a13ac9644529@dist-git> +From: Michal Privoznik +Date: Fri, 19 Jun 2020 11:43:12 +0200 +Subject: [PATCH] util: Rework virStringListAdd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So every caller does the same: they use virStringListAdd() to add +new item into the list and then free the old copy to replace it +with new list. It's not very memory effective, nor environmental +friendly. + +Signed-off-by: Michal Privoznik +Reviewed-by: Erik Skultety +(cherry picked from commit 71a390e0fdb4e6cbeaef4c9045a501a6c8de5412) + +https://bugzilla.redhat.com/show_bug.cgi?id=1839992 + +Signed-off-by: Michal Privoznik +Message-Id: <75aadf9f9464504bd1feec27d082b28c9fec0cbe.1592559697.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + src/util/virmacmap.c | 8 ++------ + src/util/virstring.c | 33 ++++++++++++--------------------- + src/util/virstring.h | 4 ++-- + tests/virstringtest.c | 6 +----- + 4 files changed, 17 insertions(+), 34 deletions(-) + +diff --git a/src/util/virmacmap.c b/src/util/virmacmap.c +index 88ca9b3f36..c7b700fa05 100644 +--- a/src/util/virmacmap.c ++++ b/src/util/virmacmap.c +@@ -90,7 +90,6 @@ virMacMapAddLocked(virMacMapPtr mgr, + { + int ret = -1; + char **macsList = NULL; +- char **newMacsList = NULL; + + if ((macsList = virHashLookup(mgr->macs, domain)) && + virStringListHasString((const char**) macsList, mac)) { +@@ -98,15 +97,12 @@ virMacMapAddLocked(virMacMapPtr mgr, + goto cleanup; + } + +- if (!(newMacsList = virStringListAdd((const char **) macsList, mac)) || +- virHashUpdateEntry(mgr->macs, domain, newMacsList) < 0) ++ if (virStringListAdd(&macsList, mac) < 0 || ++ virHashUpdateEntry(mgr->macs, domain, macsList) < 0) + goto cleanup; +- newMacsList = NULL; +- virStringListFree(macsList); + + ret = 0; + cleanup: +- virStringListFree(newMacsList); + return ret; + } + +diff --git a/src/util/virstring.c b/src/util/virstring.c +index 0f13b6c664..74fa2f6a94 100644 +--- a/src/util/virstring.c ++++ b/src/util/virstring.c +@@ -175,32 +175,23 @@ char *virStringListJoin(const char **strings, + * @strings: a NULL-terminated array of strings + * @item: string to add + * +- * Creates new strings list with all strings duplicated and @item +- * at the end of the list. Callers is responsible for freeing +- * both @strings and returned list. ++ * Appends @item into string list @strings. If *@strings is not ++ * allocated yet new string list is created. ++ * ++ * Returns: 0 on success, ++ * -1 otherwise + */ +-char ** +-virStringListAdd(const char **strings, ++int ++virStringListAdd(char ***strings, + const char *item) + { +- char **ret = NULL; +- size_t i = virStringListLength(strings); +- +- if (VIR_ALLOC_N(ret, i + 2) < 0) +- goto error; +- +- for (i = 0; strings && strings[i]; i++) { +- if (VIR_STRDUP(ret[i], strings[i]) < 0) +- goto error; +- } ++ size_t i = virStringListLength((const char **) *strings); + +- if (VIR_STRDUP(ret[i], item) < 0) +- goto error; ++ if (VIR_EXPAND_N(*strings, i, 2) < 0 || ++ VIR_STRDUP((*strings)[i - 2], item) < 0) ++ return -1; + +- return ret; +- error: +- virStringListFree(ret); +- return NULL; ++ return 0; + } + + +diff --git a/src/util/virstring.h b/src/util/virstring.h +index e68b9eec79..a3db08ce58 100644 +--- a/src/util/virstring.h ++++ b/src/util/virstring.h +@@ -41,8 +41,8 @@ char *virStringListJoin(const char **strings, + const char *delim) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +-char **virStringListAdd(const char **strings, +- const char *item); ++int virStringListAdd(char ***strings, ++ const char *item); + void virStringListRemove(char ***strings, + const char *item); + +diff --git a/tests/virstringtest.c b/tests/virstringtest.c +index 1230aba5b7..1a1e6364d1 100644 +--- a/tests/virstringtest.c ++++ b/tests/virstringtest.c +@@ -179,12 +179,8 @@ static int testAdd(const void *args) + size_t i; + + for (i = 0; data->tokens[i]; i++) { +- char **tmp = virStringListAdd((const char **)list, data->tokens[i]); +- if (!tmp) ++ if (virStringListAdd(&list, data->tokens[i]) < 0) + goto cleanup; +- virStringListFree(list); +- list = tmp; +- tmp = NULL; + } + + if (!list && +-- +2.27.0 + diff --git a/libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch b/libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch new file mode 100644 index 0000000..d28b610 --- /dev/null +++ b/libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch @@ -0,0 +1,94 @@ +From 62e22785c706e7ee7f99a6600d4505dc890838ef Mon Sep 17 00:00:00 2001 +Message-Id: <62e22785c706e7ee7f99a6600d4505dc890838ef@dist-git> +From: Peter Krempa +Date: Fri, 19 Jun 2020 11:43:11 +0200 +Subject: [PATCH] util: string: Introduce macro for automatic string lists +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Similar to VIR_AUTOPTR, VIR_AUTOSTRINGLIST defines a list of strings +which will be freed if the pointer is leaving scope. + +Signed-off-by: Peter Krempa +Reviewed-by: Erik Skultety +(cherry picked from commit daefda165b28b399478137c75b5466f865c65be5) + +https://bugzilla.redhat.com/show_bug.cgi?id=1839992 + +Conflicts: +- src/util/virstring.h - Context. This is RHEL-7.9; did you + really think this would be a clean backport? Plenty of + patches changed virstring.h in the last two years. + +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/libvirt_private.syms | 1 + + src/util/virstring.c | 10 ++++++++++ + src/util/virstring.h | 10 ++++++++++ + 3 files changed, 21 insertions(+) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 2a3950fd35..3e5448af94 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -2917,6 +2917,7 @@ virStringHasControlChars; + virStringIsEmpty; + virStringIsPrintable; + virStringListAdd; ++virStringListAutoFree; + virStringListFree; + virStringListFreeCount; + virStringListGetFirstWithPrefix; +diff --git a/src/util/virstring.c b/src/util/virstring.c +index 15f367af7c..0f13b6c664 100644 +--- a/src/util/virstring.c ++++ b/src/util/virstring.c +@@ -332,6 +332,16 @@ void virStringListFree(char **strings) + } + + ++void virStringListAutoFree(char ***strings) ++{ ++ if (!*strings) ++ return; ++ ++ virStringListFree(*strings); ++ *strings = NULL; ++} ++ ++ + /** + * virStringListFreeCount: + * @strings: array of strings to free +diff --git a/src/util/virstring.h b/src/util/virstring.h +index 607ae66e99..e68b9eec79 100644 +--- a/src/util/virstring.h ++++ b/src/util/virstring.h +@@ -53,6 +53,7 @@ int virStringListCopy(char ***dst, + const char **src); + + void virStringListFree(char **strings); ++void virStringListAutoFree(char ***strings); + void virStringListFreeCount(char **strings, + size_t count); + +@@ -309,4 +310,13 @@ int virStringParsePort(const char *str, + unsigned int *port) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + ++/** ++ * VIR_AUTOSTRINGLIST: ++ * ++ * Declares a NULL-terminated list of strings which will be automatically freed ++ * when the pointer goes out of scope. ++ */ ++# define VIR_AUTOSTRINGLIST \ ++ __attribute__((cleanup(virStringListAutoFree))) char ** ++ + #endif /* __VIR_STRING_H__ */ +-- +2.27.0 + diff --git a/libvirt-virDevMapperGetTargetsImpl-Check-for-dm-major-properly.patch b/libvirt-virDevMapperGetTargetsImpl-Check-for-dm-major-properly.patch new file mode 100644 index 0000000..fda9943 --- /dev/null +++ b/libvirt-virDevMapperGetTargetsImpl-Check-for-dm-major-properly.patch @@ -0,0 +1,66 @@ +From a3ac7f49d3592fb9acdf2c4de6f2bf7329745faa Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Fri, 19 Jun 2020 11:43:15 +0200 +Subject: [PATCH] virDevMapperGetTargetsImpl: Check for dm major properly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In v6.4.0-rc1~143 I've introduced a check that is supposed to +return from the function early, if given path is not a dm target. +While the idea is still valid, the implementation had a flaw. +It calls stat() over given path and the uses major(sb.st_dev) to +learn the major of the device. This is then passed to +dm_is_dm_major() which returns true or false depending whether +the device is under devmapper's control or not. + +The problem with this approach is in how the major of the device +is obtained - paths managed by devmapper are special files and +thus we want to be using st_rdev instead of st_dev to obtain the +major number. Well, that's what virIsDevMapperDevice() does +already so might as well us that. + +Fixes: 01626c668ecfbe465d18799ac4628e6127ea1d47 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1839992 + +Signed-off-by: Michal Privoznik +Reviewed-by: Jiri Denemark +(cherry picked from commit d53ab9f54ea8d6cc1e5c3b04c4eb743cae9518ce) +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index 944baad562..c69830ac70 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -69,7 +69,6 @@ virDevMapperGetTargetsImpl(const char *path, + char ***devPaths_ret, + unsigned int ttl) + { +- struct stat sb; + struct dm_task *dmt = NULL; + struct dm_deps *deps; + struct dm_info info; +@@ -88,13 +87,7 @@ virDevMapperGetTargetsImpl(const char *path, + return ret; + } + +- if (stat(path, &sb) < 0) { +- if (errno == ENOENT) +- return 0; +- return -1; +- } +- +- if (!dm_is_dm_major(major(sb.st_dev))) ++ if (!virIsDevMapperDevice(path)) + return 0; + + if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) { +-- +2.27.0 + diff --git a/libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch b/libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch new file mode 100644 index 0000000..d4c155b --- /dev/null +++ b/libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch @@ -0,0 +1,79 @@ +From dce266130a7eef93d3f76940929cc92e1316b0a0 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:30 +0100 +Subject: [PATCH] virDevMapperGetTargetsImpl: Use VIR_AUTOSTRINGLIST +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since we have VIR_AUTOSTRINGLIST we can use it to free string +lists used in the function automatically. + +Signed-off-by: Michal Privoznik +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit b8ebbe05451fde7ce541564f73437a29ffd5db0d) + +Conflicts: +- src/util/virdevmapper.c: Another Glib conflict, but + fortunately, this time it's only in the context - the cherry + picked commit uses g_steal_pointer() because of + a3931b4996e46db409ad031e0230a507fb303287 + but the old code still uses VIR_STEAL_PTR(). + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index 6aee00112c..50d12ea0f1 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -72,8 +72,7 @@ virDevMapperGetTargetsImpl(const char *path, + struct dm_task *dmt = NULL; + struct dm_deps *deps; + struct dm_info info; +- char **devPaths = NULL; +- char **recursiveDevPaths = NULL; ++ VIR_AUTOSTRINGLIST devPaths = NULL; + size_t i; + int ret = -1; + +@@ -139,28 +138,19 @@ virDevMapperGetTargetsImpl(const char *path, + goto cleanup; + } + +- recursiveDevPaths = NULL; + for (i = 0; i < deps->count; i++) { +- char **tmpPaths; ++ VIR_AUTOSTRINGLIST tmpPaths = NULL; + + if (virDevMapperGetTargetsImpl(devPaths[i], &tmpPaths, ttl - 1) < 0) + goto cleanup; + +- if (tmpPaths && +- virStringListMerge(&recursiveDevPaths, &tmpPaths) < 0) { +- virStringListFree(tmpPaths); ++ if (virStringListMerge(&devPaths, &tmpPaths) < 0) + goto cleanup; +- } + } + +- if (virStringListMerge(&devPaths, &recursiveDevPaths) < 0) +- goto cleanup; +- + VIR_STEAL_PTR(*devPaths_ret, devPaths); + ret = 0; + cleanup: +- virStringListFree(recursiveDevPaths); +- virStringListFree(devPaths); + dm_task_destroy(dmt); + return ret; + } +-- +2.31.0 + diff --git a/libvirt-virDevMapperGetTargetsImpl-Use-correct-length-when-copying-into-dm.name.patch b/libvirt-virDevMapperGetTargetsImpl-Use-correct-length-when-copying-into-dm.name.patch new file mode 100644 index 0000000..5eab1f5 --- /dev/null +++ b/libvirt-virDevMapperGetTargetsImpl-Use-correct-length-when-copying-into-dm.name.patch @@ -0,0 +1,63 @@ +From 575ba6e90f005cefb8b1100169a024083d8b4a4a Mon Sep 17 00:00:00 2001 +Message-Id: <575ba6e90f005cefb8b1100169a024083d8b4a4a@dist-git> +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:36 +0100 +Subject: [PATCH] virDevMapperGetTargetsImpl: Use correct length when copying + into dm.name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For reasons unknown, when rewriting this code and dropping +libdevmapper I've mistakenly used incorrect length of dm.name. In +linux/dm-ioctl.h the dm_ioctl struct is defined as follows: + + #define DM_NAME_LEN 128 + + struct dm_ioctl { + ... + char name[DM_NAME_LEN]; /* device name */ + ... + }; + +However, when copying string into this member, DM_TABLE_DEPS was +used, which is defined as follows: + + #define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl) + +After decryption, this results in the following size: 3241737483. + +Fixes: 22494556542c676d1b9e7f1c1f2ea13ac17e1e3e +Signed-off-by: Michal Privoznik +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 4f30c1bb8c32374c62f90abb5aa224611c59c363) + +Conflicts: +- src/util/virdevmapper.c: The same story as a few commits ago: + virStrcpy() returns a pointer, but the cherry picked commit + expects integer. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index 4994b4caef..dcb3c08df5 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -257,7 +257,7 @@ virDevMapperGetTargetsImpl(int controlFD, + if (!(sanitizedPath = virDMSanitizepath(path))) + return 0; + +- if (virStrcpy(dm.name, sanitizedPath, DM_TABLE_DEPS) == NULL) { ++ if (virStrcpy(dm.name, sanitizedPath, DM_NAME_LEN) == NULL) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Resolved device mapper name too long")); + return -1; +-- +2.31.0 + diff --git a/libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch b/libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch new file mode 100644 index 0000000..a63c189 --- /dev/null +++ b/libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch @@ -0,0 +1,107 @@ +From fb8c44edabd188957fe3e3deb97a605f71c394b8 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:32 +0100 +Subject: [PATCH] virdevmapper: Don't cache device-mapper major +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The device mapper major is needed in virIsDevMapperDevice() which +determines whether given device is managed by device-mapper. This +number is obtained by parsing /proc/devices and then stored in a +global variable so that the file doesn't have to be parsed again. +However, as it turns out this logic is flawed - the major number +is not static and can change as it can be specified as a +parameter when loading the dm-mod module. + +Unfortunately, I was not able to come up with a good solution and +thus the /proc/devices file is being parsed every time we need +the device mapper major. + +Signed-off-by: Michal Privoznik +Reviewed-by: Peter Krempa +Reviewed-by: Christian Ehrhardt +Tested-by: Christian Ehrhardt +(cherry picked from commit 82bb167f0d15b733b23931205be3488b83cb9ec6) + +Conflicts: +- src/util/virdevmapper.c: The VIR_ONCE_GLOBAL_INIT() call was + missing a semicolon at EOL which was added there in + af36f8a641809556ac18dcc076f996033cb2385c which isn't + backported. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: <206f7453debcfd7a013317989893be8a0688045c.1615203117.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index ebf446d966..725de736c1 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -49,11 +49,9 @@ + + verify(BUF_SIZE > sizeof(struct dm_ioctl)); + +-static unsigned int virDMMajor; +- + + static int +-virDevMapperOnceInit(void) ++virDevMapperGetMajor(unsigned int *major) + { + VIR_AUTOFREE(char *) buf = NULL; + VIR_AUTOSTRINGLIST lines = NULL; +@@ -72,7 +70,7 @@ virDevMapperOnceInit(void) + + if (sscanf(lines[i], "%u %ms\n", &maj, &dev) == 2 && + STREQ(dev, DM_NAME)) { +- virDMMajor = maj; ++ *major = maj; + break; + } + } +@@ -88,9 +86,6 @@ virDevMapperOnceInit(void) + } + + +-VIR_ONCE_GLOBAL_INIT(virDevMapper) +- +- + static void * + virDMIoctl(int controlFD, int cmd, struct dm_ioctl *dm, char **buf) + { +@@ -318,9 +313,6 @@ virDevMapperGetTargets(const char *path, + * consist of devices or yet another targets. If that's the + * case, we have to stop recursion somewhere. */ + +- if (virDevMapperInitialize() < 0) +- return -1; +- + if ((controlFD = virDMOpen()) < 0) + return -1; + +@@ -332,13 +324,14 @@ bool + virIsDevMapperDevice(const char *dev_name) + { + struct stat buf; ++ unsigned int major; + +- if (virDevMapperInitialize() < 0) ++ if (virDevMapperGetMajor(&major) < 0) + return false; + + if (!stat(dev_name, &buf) && + S_ISBLK(buf.st_mode) && +- major(buf.st_rdev) == virDMMajor) ++ major(buf.st_rdev) == major) + return true; + + return false; +-- +2.31.0 + diff --git a/libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch b/libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch new file mode 100644 index 0000000..97f30bb --- /dev/null +++ b/libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch @@ -0,0 +1,496 @@ +From 6bf725c07c25b56937c494b6c7e83e6ca27ec54c Mon Sep 17 00:00:00 2001 +Message-Id: <6bf725c07c25b56937c494b6c7e83e6ca27ec54c@dist-git> +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:31 +0100 +Subject: [PATCH] virdevmapper: Don't use libdevmapper to obtain dependencies +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE-2020-14339 + +When building domain's private /dev in a namespace, libdevmapper +is consulted for getting full dependency tree of domain's disks. +The reason is that for a multipath devices all dependent devices +must be created in the namespace and allowed in CGroups. + +However, this approach is very fragile as building of namespace +happens in the forked off child process, after mass close of FDs +and just before dropping privileges and execing QEMU. And it so +happens that when calling libdevmapper APIs, one of them opens +/dev/mapper/control and saves the FD into a global variable. The +FD is kept open until the lib is unlinked or dm_lib_release() is +called explicitly. We are doing neither. + +However, the virDevMapperGetTargets() function is called also +from libvirtd (when setting up CGroups) and thus has to be thread +safe. Unfortunately, libdevmapper APIs are not thread safe (nor +async signal safe) and thus we can't use them. Reimplement what +libdevmapper would do using plain C (ioctl()-s, /proc/devices +parsing, /dev/mapper dirwalking, and so on). + +Fixes: a30078cb832646177defd256e77c632905f1e6d0 +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1858260 + +Signed-off-by: Michal Privoznik +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 22494556542c676d1b9e7f1c1f2ea13ac17e1e3e) + +Conflicts: +- po/POTFILES.in: This file doesn't exist, only POTFILES does. +- src/util/virdevmapper.c: Couple of problems. Firstly, + 03c532cf9711dd6ad35380455a77141ef7d492ab isn't backported, so + the header files include looks a bit different. Secondly, + 91d88aaf23994691ea94973dd988ca5825c1e1b1 isn't backported, so + we have to stick with virAsprintf() instead of + g_strdup_printf(). Thirdly, virStrncpy() behaves a bit + differently: with the old code it returns pointer to copied + string or NULL, with the new code (cherry-picked one) it + already returns an integer, and on the top of that, specifying + -1 for the source len means strlen() is used under the hood + (see 6c0d0210cbcd5d647f0d882c07f077d444bc707d and + 7d70a63b947e9a654a4e3fffa0ffa355f5549ec7 - neither is + backported). + +In addition, I had to de-GLib the code. In RHEL-7 there is no +g_autofree, G_STATIC_ASSERT, g_new0, g_strdup, g_strdup_printf, +or g_steal_pointer. I had switch these to their old counterparts +we used to use. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: <3c7fd3071d8a9a58c8716f850880e3a0869243d3.1615203117.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + po/POTFILES | 1 + + src/util/virdevmapper.c | 315 +++++++++++++++++++++++++++++----------- + 2 files changed, 228 insertions(+), 88 deletions(-) + +diff --git a/po/POTFILES b/po/POTFILES +index be2874487c..82a08da04a 100644 +--- a/po/POTFILES ++++ b/po/POTFILES +@@ -206,6 +206,7 @@ src/util/vircommand.c + src/util/virconf.c + src/util/vircrypto.c + src/util/virdbus.c ++src/util/virdevmapper.c + src/util/virdnsmasq.c + src/util/virerror.c + src/util/virerror.h +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index 50d12ea0f1..ebf446d966 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -23,40 +23,67 @@ + + #include + +-#ifdef MAJOR_IN_MKDEV +-# include +-#elif MAJOR_IN_SYSMACROS ++#include "virdevmapper.h" ++#include "internal.h" ++ ++#ifdef __linux__ + # include +-#endif ++# include ++# include ++# include ++# include ++# include + +-#ifdef WITH_DEVMAPPER +-# include +-#endif ++# include "virthread.h" ++# include "viralloc.h" ++# include "virstring.h" ++# include "virfile.h" ++ ++# define VIR_FROM_THIS VIR_FROM_STORAGE ++ ++# define PROC_DEVICES "/proc/devices" ++# define DM_NAME "device-mapper" ++# define DEV_DM_DIR "/dev/" DM_DIR ++# define CONTROL_PATH DEV_DM_DIR "/" DM_CONTROL_NODE ++# define BUF_SIZE (16 * 1024) ++ ++verify(BUF_SIZE > sizeof(struct dm_ioctl)); ++ ++static unsigned int virDMMajor; + +-#include "virdevmapper.h" +-#include "internal.h" +-#include "virthread.h" +-#include "viralloc.h" +-#include "virstring.h" +- +-#ifdef WITH_DEVMAPPER +-static void +-virDevMapperDummyLogger(int level ATTRIBUTE_UNUSED, +- const char *file ATTRIBUTE_UNUSED, +- int line ATTRIBUTE_UNUSED, +- int dm_errno ATTRIBUTE_UNUSED, +- const char *fmt ATTRIBUTE_UNUSED, +- ...) +-{ +- return; +-} + + static int + virDevMapperOnceInit(void) + { +- /* Ideally, we would not need this. But libdevmapper prints +- * error messages to stderr by default. Sad but true. */ +- dm_log_with_errno_init(virDevMapperDummyLogger); ++ VIR_AUTOFREE(char *) buf = NULL; ++ VIR_AUTOSTRINGLIST lines = NULL; ++ size_t i; ++ ++ if (virFileReadAll(PROC_DEVICES, BUF_SIZE, &buf) < 0) ++ return -1; ++ ++ lines = virStringSplit(buf, "\n", 0); ++ if (!lines) ++ return -1; ++ ++ for (i = 0; lines[i]; i++) { ++ VIR_AUTOFREE(char *) dev = NULL; ++ unsigned int maj; ++ ++ if (sscanf(lines[i], "%u %ms\n", &maj, &dev) == 2 && ++ STREQ(dev, DM_NAME)) { ++ virDMMajor = maj; ++ break; ++ } ++ } ++ ++ if (!lines[i]) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unable to find major for %s"), ++ DM_NAME); ++ return -1; ++ } ++ + return 0; + } + +@@ -64,95 +91,200 @@ virDevMapperOnceInit(void) + VIR_ONCE_GLOBAL_INIT(virDevMapper) + + ++static void * ++virDMIoctl(int controlFD, int cmd, struct dm_ioctl *dm, char **buf) ++{ ++ size_t bufsize = BUF_SIZE; ++ ++ reread: ++ if (VIR_ALLOC_N(*buf, bufsize) < 0) ++ return NULL; ++ ++ dm->version[0] = DM_VERSION_MAJOR; ++ dm->version[1] = 0; ++ dm->version[2] = 0; ++ dm->data_size = bufsize; ++ dm->data_start = sizeof(struct dm_ioctl); ++ ++ memcpy(*buf, dm, sizeof(struct dm_ioctl)); ++ ++ if (ioctl(controlFD, cmd, *buf) < 0) { ++ VIR_FREE(*buf); ++ return NULL; ++ } ++ ++ memcpy(dm, *buf, sizeof(struct dm_ioctl)); ++ ++ if (dm->flags & DM_BUFFER_FULL_FLAG) { ++ bufsize += BUF_SIZE; ++ VIR_FREE(*buf); ++ goto reread; ++ } ++ ++ return *buf + dm->data_start; ++} ++ ++ + static int +-virDevMapperGetTargetsImpl(const char *path, +- char ***devPaths_ret, +- unsigned int ttl) ++virDMOpen(void) + { +- struct dm_task *dmt = NULL; +- struct dm_deps *deps; +- struct dm_info info; +- VIR_AUTOSTRINGLIST devPaths = NULL; +- size_t i; +- int ret = -1; ++ VIR_AUTOCLOSE controlFD = -1; ++ struct dm_ioctl dm; ++ VIR_AUTOFREE(char *) tmp = NULL; ++ int ret; + +- *devPaths_ret = NULL; ++ memset(&dm, 0, sizeof(dm)); + +- if (virDevMapperInitialize() < 0) +- return ret; ++ if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) ++ return -1; + +- if (ttl == 0) { +- errno = ELOOP; ++ if (!virDMIoctl(controlFD, DM_VERSION, &dm, &tmp)) { ++ virReportSystemError(errno, "%s", ++ _("Unable to get device-mapper version")); ++ return -1; ++ } ++ ++ if (dm.version[0] != DM_VERSION_MAJOR) { ++ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, ++ _("Unsupported device-mapper version. Expected %d got %d"), ++ DM_VERSION_MAJOR, dm.version[0]); ++ return -1; ++ } ++ ++ ret = controlFD; ++ controlFD = -1; ++ return ret; ++} ++ ++ ++static char * ++virDMSanitizepath(const char *path) ++{ ++ VIR_AUTOFREE(char *) dmDirPath = NULL; ++ struct dirent *ent = NULL; ++ struct stat sb[2]; ++ DIR *dh = NULL; ++ const char *p; ++ char *ret = NULL; ++ int rc; ++ ++ /* If a path is NOT provided then assume it's DM name */ ++ p = strrchr(path, '/'); ++ ++ if (!p) { ++ ignore_value(VIR_STRDUP(ret, path)); + return ret; ++ } else { ++ p++; + } + +- if (!virIsDevMapperDevice(path)) +- return 0; ++ /* It's a path. Check if the last component is DM name */ ++ if (stat(path, &sb[0]) < 0) { ++ virReportError(errno, ++ _("Unable to stat %p"), ++ path); ++ return NULL; ++ } + +- if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) { +- if (errno == ENOENT || errno == ENODEV) { +- /* It's okay. Kernel is probably built without +- * devmapper support. */ +- ret = 0; +- } ++ if (virAsprintf(&dmDirPath, DEV_DM_DIR "/%s", p) < 0) ++ return NULL; ++ ++ if (stat(dmDirPath, &sb[1]) == 0 && ++ sb[0].st_rdev == sb[1].st_rdev) { ++ ignore_value(VIR_STRDUP(ret, p)); + return ret; + } + +- if (!dm_task_set_name(dmt, path)) { +- if (errno == ENOENT) { +- /* It's okay, @path is not managed by devmapper => +- * not a devmapper device. */ +- ret = 0; ++ /* The last component of @path wasn't DM name. Let's check if ++ * there's a device under /dev/mapper/ with the same rdev. */ ++ if (virDirOpen(&dh, DEV_DM_DIR) < 0) ++ return NULL; ++ ++ while ((rc = virDirRead(dh, &ent, DEV_DM_DIR)) > 0) { ++ VIR_AUTOFREE(char *) tmp = NULL; ++ ++ if (virAsprintf(&tmp, DEV_DM_DIR "/%s", ent->d_name) < 0) ++ return NULL; ++ ++ if (stat(tmp, &sb[1]) == 0 && ++ sb[0].st_rdev == sb[0].st_rdev) { ++ VIR_STEAL_PTR(ret, tmp); ++ break; + } +- goto cleanup; + } + +- dm_task_no_open_count(dmt); ++ virDirClose(&dh); ++ return ret; ++} + +- if (!dm_task_run(dmt)) { +- if (errno == ENXIO) { +- /* If @path = "/dev/mapper/control" ENXIO is returned. */ +- ret = 0; +- } +- goto cleanup; ++ ++static int ++virDevMapperGetTargetsImpl(int controlFD, ++ const char *path, ++ char ***devPaths_ret, ++ unsigned int ttl) ++{ ++ VIR_AUTOFREE(char *) sanitizedPath = NULL; ++ VIR_AUTOFREE(char *) buf = NULL; ++ struct dm_ioctl dm; ++ struct dm_target_deps *deps = NULL; ++ VIR_AUTOSTRINGLIST devPaths = NULL; ++ size_t i; ++ ++ memset(&dm, 0, sizeof(dm)); ++ *devPaths_ret = NULL; ++ ++ if (ttl == 0) { ++ errno = ELOOP; ++ return -1; + } + +- if (!dm_task_get_info(dmt, &info)) +- goto cleanup; ++ if (!virIsDevMapperDevice(path)) ++ return 0; ++ ++ if (!(sanitizedPath = virDMSanitizepath(path))) ++ return 0; + +- if (!info.exists) { +- ret = 0; +- goto cleanup; ++ if (virStrcpy(dm.name, sanitizedPath, DM_TABLE_DEPS) == NULL) { ++ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", ++ _("Resolved device mapper name too long")); ++ return -1; + } + +- if (!(deps = dm_task_get_deps(dmt))) +- goto cleanup; ++ deps = virDMIoctl(controlFD, DM_TABLE_DEPS, &dm, &buf); ++ if (!deps) { ++ if (errno == ENXIO) ++ return 0; ++ ++ virReportSystemError(errno, ++ _("Unable to query dependencies for %s"), ++ path); ++ return -1; ++ } + + if (VIR_ALLOC_N_QUIET(devPaths, deps->count + 1) < 0) +- goto cleanup; ++ return -1; + + for (i = 0; i < deps->count; i++) { + if (virAsprintfQuiet(&devPaths[i], "/dev/block/%u:%u", +- major(deps->device[i]), +- minor(deps->device[i])) < 0) +- goto cleanup; ++ major(deps->dev[i]), ++ minor(deps->dev[i])) < 0) { ++ return -1; ++ } + } + + for (i = 0; i < deps->count; i++) { + VIR_AUTOSTRINGLIST tmpPaths = NULL; + +- if (virDevMapperGetTargetsImpl(devPaths[i], &tmpPaths, ttl - 1) < 0) +- goto cleanup; ++ if (virDevMapperGetTargetsImpl(controlFD, devPaths[i], &tmpPaths, ttl - 1) < 0) ++ return -1; + + if (virStringListMerge(&devPaths, &tmpPaths) < 0) +- goto cleanup; ++ return -1; + } + + VIR_STEAL_PTR(*devPaths_ret, devPaths); +- ret = 0; +- cleanup: +- dm_task_destroy(dmt); +- return ret; ++ return 0; + } + + +@@ -171,9 +303,6 @@ virDevMapperGetTargetsImpl(const char *path, + * If @path consists of yet another devmapper targets these are + * consulted recursively. + * +- * If we don't have permissions to talk to kernel, -1 is returned +- * and errno is set to EBADF. +- * + * Returns 0 on success, + * -1 otherwise (with errno set, no libvirt error is + * reported) +@@ -182,13 +311,20 @@ int + virDevMapperGetTargets(const char *path, + char ***devPaths) + { ++ VIR_AUTOCLOSE controlFD = -1; + const unsigned int ttl = 32; + + /* Arbitrary limit on recursion level. A devmapper target can + * consist of devices or yet another targets. If that's the + * case, we have to stop recursion somewhere. */ + +- return virDevMapperGetTargetsImpl(path, devPaths, ttl); ++ if (virDevMapperInitialize() < 0) ++ return -1; ++ ++ if ((controlFD = virDMOpen()) < 0) ++ return -1; ++ ++ return virDevMapperGetTargetsImpl(controlFD, path, devPaths, ttl); + } + + +@@ -197,15 +333,18 @@ virIsDevMapperDevice(const char *dev_name) + { + struct stat buf; + ++ if (virDevMapperInitialize() < 0) ++ return false; ++ + if (!stat(dev_name, &buf) && + S_ISBLK(buf.st_mode) && +- dm_is_dm_major(major(buf.st_rdev))) +- return true; ++ major(buf.st_rdev) == virDMMajor) ++ return true; + + return false; + } + +-#else /* ! WITH_DEVMAPPER */ ++#else /* !defined(__linux__) */ + + int + virDevMapperGetTargets(const char *path ATTRIBUTE_UNUSED, +@@ -221,4 +360,4 @@ virIsDevMapperDevice(const char *dev_name G_GNUC_UNUSED) + { + return false; + } +-#endif /* ! WITH_DEVMAPPER */ ++#endif /* ! defined(__linux__) */ +-- +2.31.0 + diff --git a/libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch b/libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch new file mode 100644 index 0000000..84bd3fa --- /dev/null +++ b/libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch @@ -0,0 +1,88 @@ +From 8474f0f611f4372bd4f98c6df92f50566f631db0 Mon Sep 17 00:00:00 2001 +Message-Id: <8474f0f611f4372bd4f98c6df92f50566f631db0@dist-git> +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:33 +0100 +Subject: [PATCH] virdevmapper: Handle kernel without device-mapper support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In one of my latest patch (v6.6.0~30) I was trying to remove +libdevmapper use in favor of our own implementation. However, the +code did not take into account that device mapper can be not +compiled into the kernel (e.g. be a separate module that's not +loaded) in which case /proc/devices won't have the device-mapper +major number and thus virDevMapperGetTargets() and/or +virIsDevMapperDevice() fails. + +However, such failure is safe to ignore, because if device mapper +is missing then there can't be any multipath devices and thus we +don't need to allow the deps in CGroups, nor create them in the +domain private namespace, etc. + +Fixes: 22494556542c676d1b9e7f1c1f2ea13ac17e1e3e +Reported-by: Andrea Bolognani +Reported-by: Christian Ehrhardt +Signed-off-by: Michal Privoznik +Reviewed-by: Peter Krempa +Reviewed-by: Christian Ehrhardt +Tested-by: Christian Ehrhardt +(cherry picked from commit feb8564a3cc63bc8f68284063d53ec0d2d81a1cc) +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: <11f41c0fd7b7c8365e24398173cb0bb2f8e785de.1615203117.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index 725de736c1..a76fe95922 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -57,6 +57,9 @@ virDevMapperGetMajor(unsigned int *major) + VIR_AUTOSTRINGLIST lines = NULL; + size_t i; + ++ if (!virFileExists(CONTROL_PATH)) ++ return -2; ++ + if (virFileReadAll(PROC_DEVICES, BUF_SIZE, &buf) < 0) + return -1; + +@@ -130,8 +133,13 @@ virDMOpen(void) + + memset(&dm, 0, sizeof(dm)); + +- if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) ++ if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) { ++ if (errno == ENOENT) ++ return -2; ++ ++ virReportSystemError(errno, _("Unable to open %s"), CONTROL_PATH); + return -1; ++ } + + if (!virDMIoctl(controlFD, DM_VERSION, &dm, &tmp)) { + virReportSystemError(errno, "%s", +@@ -313,8 +321,16 @@ virDevMapperGetTargets(const char *path, + * consist of devices or yet another targets. If that's the + * case, we have to stop recursion somewhere. */ + +- if ((controlFD = virDMOpen()) < 0) ++ if ((controlFD = virDMOpen()) < 0) { ++ if (controlFD == -2) { ++ /* The CONTROL_PATH doesn't exist. Probably the ++ * module isn't loaded, yet. Don't error out, just ++ * exit. */ ++ return 0; ++ } ++ + return -1; ++ } + + return virDevMapperGetTargetsImpl(controlFD, path, devPaths, ttl); + } +-- +2.31.0 + diff --git a/libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch b/libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch new file mode 100644 index 0000000..d5b8c7c --- /dev/null +++ b/libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch @@ -0,0 +1,95 @@ +From fb3d8e295473034a271f09c6ce46f9500fcfa2c5 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:34 +0100 +Subject: [PATCH] virdevmapper: Ignore all errors when opening + /dev/mapper/control +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So far, only ENOENT is ignored (to deal with kernels without +devmapper). However, as reported on the list, under certain +scenarios a different error can occur. For instance, when libvirt +is running inside a container which doesn't have permissions to +talk to the devmapper. If this is the case, then open() returns +-1 and sets errno=EPERM. + +Assuming that multipath devices are fairly narrow use case and +using them in a restricted container is even more narrow the best +fix seems to be to ignore all open errors BUT produce a warning +on failure. To avoid flooding logs with warnings on kernels +without devmapper the level is reduced to a plain debug message. + +Reported-by: Christian Ehrhardt +Reviewed-by: Christian Ehrhardt +Signed-off-by: Michal Privoznik +(cherry picked from commit 53d9af1e7924757e3b5f661131dd707d7110d094) + +I had to replace g_strerror() from the original commit with +virStrerror() which is what we use in downstream. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: <8e45903b261c50d92cea4bf3d87f724a262c928f.1615203117.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index a76fe95922..a04d9650a6 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -38,9 +38,12 @@ + # include "viralloc.h" + # include "virstring.h" + # include "virfile.h" ++# include "virlog.h" + + # define VIR_FROM_THIS VIR_FROM_STORAGE + ++VIR_LOG_INIT("util.virdevmapper"); ++ + # define PROC_DEVICES "/proc/devices" + # define DM_NAME "device-mapper" + # define DEV_DM_DIR "/dev/" DM_DIR +@@ -134,11 +137,17 @@ virDMOpen(void) + memset(&dm, 0, sizeof(dm)); + + if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0) { +- if (errno == ENOENT) +- return -2; +- +- virReportSystemError(errno, _("Unable to open %s"), CONTROL_PATH); +- return -1; ++ char ebuf[1024]; ++ ++ /* We can't talk to devmapper. Produce a warning and let ++ * the caller decide what to do next. */ ++ if (errno == ENOENT) { ++ VIR_DEBUG("device mapper not available"); ++ } else { ++ VIR_WARN("unable to open %s: %s", ++ CONTROL_PATH, virStrerror(errno, ebuf, sizeof(ebuf))); ++ } ++ return -2; + } + + if (!virDMIoctl(controlFD, DM_VERSION, &dm, &tmp)) { +@@ -323,9 +332,9 @@ virDevMapperGetTargets(const char *path, + + if ((controlFD = virDMOpen()) < 0) { + if (controlFD == -2) { +- /* The CONTROL_PATH doesn't exist. Probably the +- * module isn't loaded, yet. Don't error out, just +- * exit. */ ++ /* The CONTROL_PATH doesn't exist or is unusable. ++ * Probably the module isn't loaded, yet. Don't error ++ * out, just exit. */ + return 0; + } + +-- +2.31.0 + diff --git a/libvirt-virdevmapper-fix-stat-comparison-in-virDMSanitizepath.patch b/libvirt-virdevmapper-fix-stat-comparison-in-virDMSanitizepath.patch new file mode 100644 index 0000000..9bef718 --- /dev/null +++ b/libvirt-virdevmapper-fix-stat-comparison-in-virDMSanitizepath.patch @@ -0,0 +1,49 @@ +From 99e00695f1ab24e122e83087162a84b2bf2b81e2 Mon Sep 17 00:00:00 2001 +Message-Id: <99e00695f1ab24e122e83087162a84b2bf2b81e2@dist-git> +From: Pavel Hrdina +Date: Mon, 8 Mar 2021 12:57:35 +0100 +Subject: [PATCH] virdevmapper: fix stat comparison in virDMSanitizepath +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduced by commit <22494556542c676d1b9e7f1c1f2ea13ac17e1e3e> which +fixed a CVE. + +If the @path passed to virDMSanitizepath() is not a DM name or not a +path to DM name this function could return incorrect sanitized path as +it would always be the first device under /dev/mapper/. + +Signed-off-by: Pavel Hrdina +Reviewed-by: Peter Krempa +(cherry picked from commit f711fa9ad09f68ea7f0bcaf999fab9c06dc6a93e) + +Conflicts: +- src/util/virdevmapper.c: Context, the downstream has + VIR_STEAL_PTR() while the cherry picked commit uses + g_steal_pointer() already. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index a04d9650a6..4994b4caef 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -219,7 +219,7 @@ virDMSanitizepath(const char *path) + return NULL; + + if (stat(tmp, &sb[1]) == 0 && +- sb[0].st_rdev == sb[0].st_rdev) { ++ sb[0].st_rdev == sb[1].st_rdev) { + VIR_STEAL_PTR(ret, tmp); + break; + } +-- +2.31.0 + diff --git a/libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch b/libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch new file mode 100644 index 0000000..df558fa --- /dev/null +++ b/libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch @@ -0,0 +1,73 @@ +From b578178e72373c13f4e1e819793e28b9d39fc2f2 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Mon, 8 Mar 2021 12:57:29 +0100 +Subject: [PATCH] virdevmapper.c: Join two WITH_DEVMAPPER sections together +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are two distinct WITH_DEVMAPPER sections in the file, for +different functions each. Rearrange the code to make some of +future commits smaller. + +Signed-off-by: Michal Privoznik +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit ae5752aabc09f435675504246e30a0b9c4795d79) + +Conflicts: +-src/util/virdevmapper.c: The old code uses ATTRIBUTE_UNUSED, the +cherry picked commit used G_GNUC_UNUSED because of commit +679f8b3994457f7801b470b7c6a3379d844d0f79 which is not backported. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1933557 +Signed-off-by: Michal Privoznik +Message-Id: <675e510b0dfca0f4b4f3dc3ed3952b763182bad3.1615203117.git.mprivozn@redhat.com> +Reviewed-by: Ján Tomko +--- + src/util/virdevmapper.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c +index c69830ac70..6aee00112c 100644 +--- a/src/util/virdevmapper.c ++++ b/src/util/virdevmapper.c +@@ -201,19 +201,7 @@ virDevMapperGetTargets(const char *path, + return virDevMapperGetTargetsImpl(path, devPaths, ttl); + } + +-#else /* ! WITH_DEVMAPPER */ +- +-int +-virDevMapperGetTargets(const char *path ATTRIBUTE_UNUSED, +- char ***devPaths ATTRIBUTE_UNUSED) +-{ +- errno = ENOSYS; +- return -1; +-} +-#endif /* ! WITH_DEVMAPPER */ + +- +-#if WITH_DEVMAPPER + bool + virIsDevMapperDevice(const char *dev_name) + { +@@ -229,6 +217,15 @@ virIsDevMapperDevice(const char *dev_name) + + #else /* ! WITH_DEVMAPPER */ + ++int ++virDevMapperGetTargets(const char *path ATTRIBUTE_UNUSED, ++ char ***devPaths ATTRIBUTE_UNUSED) ++{ ++ errno = ENOSYS; ++ return -1; ++} ++ ++ + bool + virIsDevMapperDevice(const char *dev_name G_GNUC_UNUSED) + { +-- +2.31.0 + diff --git a/libvirt.spec b/libvirt.spec index 62685ce..4949ae0 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -253,7 +253,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 4.5.0 -Release: 36%{?dist}%{?extra_release} +Release: 36%{?dist}.5%{?extra_release} License: LGPLv2+ URL: https://libvirt.org/ @@ -641,6 +641,26 @@ Patch375: libvirt-qemu-remove-qemuDomainObjBegin-EndJobWithAgent.patch Patch376: libvirt-storage-Fix-daemon-crash-on-lookup-storagepool-by-targetpath.patch Patch377: libvirt-virDevMapperGetTargetsImpl-Be-tolerant-to-kernels-without-DM-support.patch Patch378: libvirt-virDevMapperGetTargetsImpl-quit-early-if-device-is-not-a-devmapper-target.patch +Patch379: libvirt-qemu-end-the-agent-job-in-qemuDomainSetTimeAgent.patch +Patch380: libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch +Patch381: libvirt-util-Rework-virStringListAdd.patch +Patch382: libvirt-qemu-Create-multipath-targets-for-PRs.patch +Patch383: libvirt-util-Move-virIsDevMapperDevice-to-virdevmapper.c.patch +Patch384: libvirt-virDevMapperGetTargetsImpl-Check-for-dm-major-properly.patch +Patch385: libvirt-rpc-gendispatch-handle-empty-flags.patch +Patch386: libvirt-rpc-add-support-for-filtering-acls-by-uint-params.patch +Patch387: libvirt-rpc-require-write-acl-for-guest-agent-in-virDomainInterfaceAddresses.patch +Patch388: libvirt-qemu-agent-set-ifname-to-NULL-after-freeing.patch +Patch389: libvirt-conf-properly-clear-out-autogenerated-macvtap-names-when-formatting-parsing.patch +Patch390: libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch +Patch391: libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch +Patch392: libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch +Patch393: libvirt-virdevmapper-Don-t-cache-device-mapper-major.patch +Patch394: libvirt-virdevmapper-Handle-kernel-without-device-mapper-support.patch +Patch395: libvirt-virdevmapper-Ignore-all-errors-when-opening-dev-mapper-control.patch +Patch396: libvirt-virdevmapper-fix-stat-comparison-in-virDMSanitizepath.patch +Patch397: libvirt-virDevMapperGetTargetsImpl-Use-correct-length-when-copying-into-dm.name.patch +Patch398: libvirt-RHEL-virdevmapper-Don-t-leak-DIR-on-OOM-in-virDMSanitizepath.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2543,6 +2563,37 @@ exit 0 %changelog +* Fri Mar 19 2021 Jiri Denemark - 4.5.0-36.el7_9.5 +- RHEL: virdevmapper: Don't leak DIR on OOM in virDMSanitizepath() (rhbz#1933557) + +* Thu Mar 18 2021 Jiri Denemark - 4.5.0-36.el7_9.4 +- virdevmapper.c: Join two WITH_DEVMAPPER sections together (rhbz#1933557) +- virDevMapperGetTargetsImpl: Use VIR_AUTOSTRINGLIST (rhbz#1933557) +- virdevmapper: Don't use libdevmapper to obtain dependencies (rhbz#1933557) +- virdevmapper: Don't cache device-mapper major (rhbz#1933557) +- virdevmapper: Handle kernel without device-mapper support (rhbz#1933557) +- virdevmapper: Ignore all errors when opening /dev/mapper/control (rhbz#1933557) +- virdevmapper: fix stat comparison in virDMSanitizepath (rhbz#1933557) +- virDevMapperGetTargetsImpl: Use correct length when copying into dm.name (rhbz#1933557) + +* Tue Oct 20 2020 Jiri Denemark - 4.5.0-36.el7_9.3 +- rpc: gendispatch: handle empty flags (CVE-2020-25637) +- rpc: add support for filtering @acls by uint params (CVE-2020-25637) +- rpc: require write acl for guest agent in virDomainInterfaceAddresses (CVE-2020-25637) +- qemu: agent: set ifname to NULL after freeing (CVE-2020-25637) +- conf: properly clear out autogenerated macvtap names when formatting/parsing (rhbz#1868549) + +* Wed Jul 22 2020 Jiri Denemark - 4.5.0-36.el7_9.2 +- Rebuild to correct invalid dist tag + +* Thu Jul 16 2020 Jiri Denemark - 4.5.0-36.el7_9.1 +- qemu: end the agent job in qemuDomainSetTimeAgent (rhbz#1844952) +- util: string: Introduce macro for automatic string lists (rhbz#1839992) +- util: Rework virStringListAdd (rhbz#1839992) +- qemu: Create multipath targets for PRs (rhbz#1839992) +- util: Move virIsDevMapperDevice() to virdevmapper.c (rhbz#1839992) +- virDevMapperGetTargetsImpl: Check for dm major properly (rhbz#1839992) + * Wed May 13 2020 Jiri Denemark - 4.5.0-36 - virDevMapperGetTargetsImpl: Be tolerant to kernels without DM support (rhbz#1823976) - virDevMapperGetTargetsImpl: quit early if device is not a devmapper target (rhbz#1823976) -- Gitee