diff --git a/SOURCES/libvirt-qemu-block-Remove-active-write-bitmap-even-if-there-are-no-bitmaps-to-merge.patch b/SOURCES/libvirt-qemu-block-Remove-active-write-bitmap-even-if-there-are-no-bitmaps-to-merge.patch
new file mode 100644
index 0000000..78fb8d3
--- /dev/null
+++ b/SOURCES/libvirt-qemu-block-Remove-active-write-bitmap-even-if-there-are-no-bitmaps-to-merge.patch
@@ -0,0 +1,105 @@
+From cb297cdd8dc75abc8fd0d60dddf54cbe305d4c14 Mon Sep 17 00:00:00 2001
+Message-Id: <cb297cdd8dc75abc8fd0d60dddf54cbe305d4c14@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 21 Jul 2020 13:56:23 +0200
+Subject: [PATCH] qemu: block: Remove 'active-write' bitmap even if there are
+ no bitmaps to merge
+
+The 'libvirt-tmp-activewrite' bitmap is added during the 'pivot'
+operation of block copy and active layer block commit operations
+regardless of whether there are any bitmaps to merge, but was not
+removed unless a bitmap was merged. This meant that subsequent attempts
+to merge into the same image would fail.
+
+Fix it by checking whether the 'libvirt-tmp-activewrite' would be used
+by the code and don't skip the code which would delete it.
+
+This is a regression introduced when we switched to the new code for
+block commit in <20a7abc2d2d> and for block copy in <7bfff40fdfe5>. The
+actual bug originates from <4fa8654ece>.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1857735
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 9d039863e2cae227cc73b7a886b40be5e5218a12)
+
+rhel-8.3: https://bugzilla.redhat.com/show_bug.cgi?id=1857779
+rhel-av-8.2.1: not cloned yet
+Message-Id: <4fea6a40be534d5a6fe7aad88d6bee1c3e77dcfb.1595332476.git.pkrempa@redhat.com>
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_block.c                                    | 3 ++-
+ tests/qemublocktestdata/bitmapblockcommit/empty          | 9 +++++++++
+ .../bitmapblockcopy/empty-deep-out.json                  | 9 +++++++++
+ .../bitmapblockcopy/empty-shallow-out.json               | 9 +++++++++
+ 4 files changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
+index 18c3861a2e..dc5fa3da03 100644
+--- a/src/qemu/qemu_block.c
++++ b/src/qemu/qemu_block.c
+@@ -2935,7 +2935,7 @@ qemuBlockGetBitmapMergeActions(virStorageSourcePtr topsrc,
+ 
+     if (!(bitmaps = qemuBlockGetBitmapMergeActionsGetBitmaps(topsrc, bitmapname,
+                                                              blockNamedNodeData)))
+-        return 0;
++        goto done;
+ 
+     for (next = bitmaps; next; next = next->next) {
+         const char *curbitmap = next->data;
+@@ -2992,6 +2992,7 @@ qemuBlockGetBitmapMergeActions(virStorageSourcePtr topsrc,
+             return -1;
+     }
+ 
++ done:
+     if (writebitmapsrc &&
+         qemuMonitorTransactionBitmapRemove(act, writebitmapsrc->nodeformat,
+                                            "libvirt-tmp-activewrite") < 0)
+diff --git a/tests/qemublocktestdata/bitmapblockcommit/empty b/tests/qemublocktestdata/bitmapblockcommit/empty
+index 9260011852..eddef0ddcd 100644
+--- a/tests/qemublocktestdata/bitmapblockcommit/empty
++++ b/tests/qemublocktestdata/bitmapblockcommit/empty
+@@ -1 +1,10 @@
+ merge bitmpas:
++[
++  {
++    "type": "block-dirty-bitmap-remove",
++    "data": {
++      "node": "libvirt-2-format",
++      "name": "libvirt-tmp-activewrite"
++    }
++  }
++]
+diff --git a/tests/qemublocktestdata/bitmapblockcopy/empty-deep-out.json b/tests/qemublocktestdata/bitmapblockcopy/empty-deep-out.json
+index e69de29bb2..99f2589ed4 100644
+--- a/tests/qemublocktestdata/bitmapblockcopy/empty-deep-out.json
++++ b/tests/qemublocktestdata/bitmapblockcopy/empty-deep-out.json
+@@ -0,0 +1,9 @@
++[
++  {
++    "type": "block-dirty-bitmap-remove",
++    "data": {
++      "node": "mirror-format-node",
++      "name": "libvirt-tmp-activewrite"
++    }
++  }
++]
+diff --git a/tests/qemublocktestdata/bitmapblockcopy/empty-shallow-out.json b/tests/qemublocktestdata/bitmapblockcopy/empty-shallow-out.json
+index e69de29bb2..99f2589ed4 100644
+--- a/tests/qemublocktestdata/bitmapblockcopy/empty-shallow-out.json
++++ b/tests/qemublocktestdata/bitmapblockcopy/empty-shallow-out.json
+@@ -0,0 +1,9 @@
++[
++  {
++    "type": "block-dirty-bitmap-remove",
++    "data": {
++      "node": "mirror-format-node",
++      "name": "libvirt-tmp-activewrite"
++    }
++  }
++]
+-- 
+2.27.0
+
diff --git a/SOURCES/libvirt-qemu-blockjob-Actually-delete-temporary-bitmap-on-failed-active-commit.patch b/SOURCES/libvirt-qemu-blockjob-Actually-delete-temporary-bitmap-on-failed-active-commit.patch
new file mode 100644
index 0000000..3edbf3b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-blockjob-Actually-delete-temporary-bitmap-on-failed-active-commit.patch
@@ -0,0 +1,65 @@
+From 2069251b1f50e1aaec566909478f1443ccfe32e6 Mon Sep 17 00:00:00 2001
+Message-Id: <2069251b1f50e1aaec566909478f1443ccfe32e6@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 21 Jul 2020 13:56:22 +0200
+Subject: [PATCH] qemu: blockjob: Actually delete temporary bitmap on failed
+ active commit
+
+Commit 20a7abc2d2d tried to delete the possibly leftover bitmap but
+neglected to call the actual monitor to do so.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 378e4fbc795c607485799cbd060f34483f580544)
+
+rhel-8.3: https://bugzilla.redhat.com/show_bug.cgi?id=1857779
+rhel-av-8.2.1: not cloned yet
+Message-Id: <add765f8f49b70dbfe1c2adf7e63e6e21b480c6d.1595332476.git.pkrempa@redhat.com>
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_blockjob.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
+index 7e2df1445d..486fca31f3 100644
+--- a/src/qemu/qemu_blockjob.c
++++ b/src/qemu/qemu_blockjob.c
+@@ -1378,8 +1378,10 @@ qemuBlockJobProcessEventConcludedCopyAbort(virQEMUDriverPtr driver,
+ static void
+ qemuBlockJobProcessEventFailedActiveCommit(virQEMUDriverPtr driver,
+                                            virDomainObjPtr vm,
+-                                           qemuBlockJobDataPtr job)
++                                           qemuBlockJobDataPtr job,
++                                           qemuDomainAsyncJob asyncJob)
+ {
++    qemuDomainObjPrivatePtr priv = vm->privateData;
+     g_autoptr(virJSONValue) actions = virJSONValueNewArray();
+     virDomainDiskDefPtr disk = job->disk;
+ 
+@@ -1391,6 +1393,13 @@ qemuBlockJobProcessEventFailedActiveCommit(virQEMUDriverPtr driver,
+     ignore_value(qemuMonitorTransactionBitmapRemove(actions, disk->mirror->nodeformat,
+                                                     "libvirt-tmp-activewrite"));
+ 
++    if (qemuDomainObjEnterMonitorAsync(priv->driver, vm, asyncJob) < 0)
++        return;
++
++    qemuMonitorTransaction(priv->mon, &actions);
++
++    if (qemuDomainObjExitMonitor(priv->driver, vm) < 0)
++        return;
+ 
+     /* Ideally, we would make the backing chain read only again (yes, SELinux
+      * can do that using different labels). But that is not implemented yet and
+@@ -1515,7 +1524,7 @@ qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job,
+         if (success) {
+             qemuBlockJobProcessEventCompletedActiveCommit(driver, vm, job, asyncJob);
+         } else {
+-            qemuBlockJobProcessEventFailedActiveCommit(driver, vm, job);
++            qemuBlockJobProcessEventFailedActiveCommit(driver, vm, job, asyncJob);
+         }
+         break;
+ 
+-- 
+2.27.0
+
diff --git a/SOURCES/libvirt-qemu-blockjob-Don-t-base-bitmap-handling-of-active-layer-block-commit-on-QEMU_CAPS_BLOCKDEV_REOPEN.patch b/SOURCES/libvirt-qemu-blockjob-Don-t-base-bitmap-handling-of-active-layer-block-commit-on-QEMU_CAPS_BLOCKDEV_REOPEN.patch
new file mode 100644
index 0000000..13d121b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-blockjob-Don-t-base-bitmap-handling-of-active-layer-block-commit-on-QEMU_CAPS_BLOCKDEV_REOPEN.patch
@@ -0,0 +1,59 @@
+From 3c9641730c62ffae735d7984b3bc0632a9194b03 Mon Sep 17 00:00:00 2001
+Message-Id: <3c9641730c62ffae735d7984b3bc0632a9194b03@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 21 Jul 2020 13:56:21 +0200
+Subject: [PATCH] qemu: blockjob: Don't base bitmap handling of active-layer
+ block commit on QEMU_CAPS_BLOCKDEV_REOPEN
+
+The handler finalizing the active layer block commit doesn't actually
+reopen the file for active layer block commit, so the comment and check
+are invalid.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit d73f107469c8882a47ffbf1a55bd0b0370d6969e)
+
+rhel-8.3: https://bugzilla.redhat.com/show_bug.cgi?id=1857779
+rhel-av-8.2.1: not cloned yet
+Message-Id: <6946fb2535038e24dcef4884806c11c258f0fc70.1595332476.git.pkrempa@redhat.com>
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_blockjob.c | 3 ++-
+ src/qemu/qemu_driver.c   | 6 +-----
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
+index 6e33f8666c..7e2df1445d 100644
+--- a/src/qemu/qemu_blockjob.c
++++ b/src/qemu/qemu_blockjob.c
+@@ -1063,7 +1063,8 @@ qemuBlockJobProcessEventCompletedCommitBitmaps(virDomainObjPtr vm,
+     g_autoptr(virJSONValue) actions = NULL;
+     bool active = job->type == QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT;
+ 
+-    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN))
++    if (!active &&
++        !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN))
+         return 0;
+ 
+     if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob)))
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 9e3a455814..ad5ef7d67d 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -17631,11 +17631,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
+         break;
+ 
+     case QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT:
+-        /* we technically don't need reopen here, but we couldn't prepare
+-         * the bitmaps if it wasn't present thus must skip this */
+-        if (blockdev &&
+-            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN)) {
+-
++        if (blockdev) {
+             actions = virJSONValueNewArray();
+ 
+             if (qemuMonitorTransactionBitmapAdd(actions,
+-- 
+2.27.0
+
diff --git a/SOURCES/libvirt-qemuDomainBlockPivot-Ignore-failures-of-creating-active-layer-bitmap.patch b/SOURCES/libvirt-qemuDomainBlockPivot-Ignore-failures-of-creating-active-layer-bitmap.patch
new file mode 100644
index 0000000..17a09fa
--- /dev/null
+++ b/SOURCES/libvirt-qemuDomainBlockPivot-Ignore-failures-of-creating-active-layer-bitmap.patch
@@ -0,0 +1,42 @@
+From 0084cc867b6de11a1b5ac1207ada57a3cc43acaf Mon Sep 17 00:00:00 2001
+Message-Id: <0084cc867b6de11a1b5ac1207ada57a3cc43acaf@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 21 Jul 2020 13:56:25 +0200
+Subject: [PATCH] qemuDomainBlockPivot: Ignore failures of creating active
+ layer bitmap
+
+Ignore errors from creating "libvirt-tmp-activewrite" bitmap. This
+prevents failures of finishing blockjobs if the bitmap already exists.
+
+Note that if the bitmap exists, the worst case that can happen is that
+more bits are marked as dirty in the resulting merge.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 66dc4992fa8a51c4e774d32bcf75f26b1365e998)
+
+rhel-8.3: https://bugzilla.redhat.com/show_bug.cgi?id=1857779
+rhel-av-8.2.1: not cloned yet
+Message-Id: <9cec292732836005d59b50a0701acb804ed1dda5.1595332476.git.pkrempa@redhat.com>
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ 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 454d7b1c16..b5df0c63d4 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -17659,7 +17659,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
+         }
+ 
+         if (bitmapactions && rc == 0)
+-            rc = qemuMonitorTransaction(priv->mon, &bitmapactions);
++            ignore_value(qemuMonitorTransaction(priv->mon, &bitmapactions));
+ 
+         if (rc == 0)
+             ret = qemuMonitorJobComplete(priv->mon, job->name);
+-- 
+2.27.0
+
diff --git a/SOURCES/libvirt-qemuDomainBlockPivot-Rename-actions-to-bitmapactions.patch b/SOURCES/libvirt-qemuDomainBlockPivot-Rename-actions-to-bitmapactions.patch
new file mode 100644
index 0000000..3054d1d
--- /dev/null
+++ b/SOURCES/libvirt-qemuDomainBlockPivot-Rename-actions-to-bitmapactions.patch
@@ -0,0 +1,73 @@
+From 31a752d5bdd63d431b619ec5045b431fc3ca6bef Mon Sep 17 00:00:00 2001
+Message-Id: <31a752d5bdd63d431b619ec5045b431fc3ca6bef@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 21 Jul 2020 13:56:24 +0200
+Subject: [PATCH] qemuDomainBlockPivot: Rename 'actions' to 'bitmapactions'
+
+There are two possible 'transaction' command arguments in the function.
+Rename 'actions' as they deal with creating bitmaps only.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+(cherry picked from commit 24ac1a7c04fded2f8639478abead72bb57506162)
+
+rhel-8.3: https://bugzilla.redhat.com/show_bug.cgi?id=1857779
+rhel-av-8.2.1: not cloned yet
+Message-Id: <6a3969721f1e701a16eb3679dcc37c9908c753ae.1595332476.git.pkrempa@redhat.com>
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_driver.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index ad5ef7d67d..454d7b1c16 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -17564,7 +17564,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
+     int ret = -1;
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
+-    g_autoptr(virJSONValue) actions = NULL;
++    g_autoptr(virJSONValue) bitmapactions = NULL;
+     g_autoptr(virJSONValue) reopenactions = NULL;
+ 
+     if (job->state != QEMU_BLOCKJOB_STATE_READY) {
+@@ -17597,9 +17597,9 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
+             bool shallow = job->jobflags & VIR_DOMAIN_BLOCK_COPY_SHALLOW;
+             bool reuse = job->jobflags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT;
+ 
+-            actions = virJSONValueNewArray();
++            bitmapactions = virJSONValueNewArray();
+ 
+-            if (qemuMonitorTransactionBitmapAdd(actions,
++            if (qemuMonitorTransactionBitmapAdd(bitmapactions,
+                                                 disk->mirror->nodeformat,
+                                                 "libvirt-tmp-activewrite",
+                                                 false,
+@@ -17632,9 +17632,9 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
+ 
+     case QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT:
+         if (blockdev) {
+-            actions = virJSONValueNewArray();
++            bitmapactions = virJSONValueNewArray();
+ 
+-            if (qemuMonitorTransactionBitmapAdd(actions,
++            if (qemuMonitorTransactionBitmapAdd(bitmapactions,
+                                                 job->data.commit.base->nodeformat,
+                                                 "libvirt-tmp-activewrite",
+                                                 false,
+@@ -17658,8 +17658,8 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
+             }
+         }
+ 
+-        if (actions && rc == 0)
+-            rc = qemuMonitorTransaction(priv->mon, &actions);
++        if (bitmapactions && rc == 0)
++            rc = qemuMonitorTransaction(priv->mon, &bitmapactions);
+ 
+         if (rc == 0)
+             ret = qemuMonitorJobComplete(priv->mon, job->name);
+-- 
+2.27.0
+
diff --git a/SOURCES/libvirt-src-assume-sys-sysmacros.h-always-exists-on-Linux.patch b/SOURCES/libvirt-src-assume-sys-sysmacros.h-always-exists-on-Linux.patch
new file mode 100644
index 0000000..dc51d5e
--- /dev/null
+++ b/SOURCES/libvirt-src-assume-sys-sysmacros.h-always-exists-on-Linux.patch
@@ -0,0 +1,168 @@
+From 06e0a9d40c52736919f32578f926bf4d829e77ec Mon Sep 17 00:00:00 2001
+Message-Id: <06e0a9d40c52736919f32578f926bf4d829e77ec@dist-git>
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Mon, 27 Jul 2020 12:36:49 +0200
+Subject: [PATCH] src: assume sys/sysmacros.h always exists on Linux
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+All our supported Linux distros now have this header.
+It has never existed on FreeBSD / macOS / Mingw.
+
+Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit 03c532cf9711dd6ad35380455a77141ef7d492ab)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1860421
+
+Conflicts:
+- src/util/virutil.c - context, because
+  db72866310d1e520efa8ed2d4589bdb5e76a1c95 (util: add API for
+  reading password from the console) isn't backported.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <ec98419d1aaa478bd3ac7a41aa9cb8b316695ef9.1595846084.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_audit.c  | 4 +---
+ src/lxc/lxc_controller.c | 4 +---
+ src/lxc/lxc_driver.c     | 4 +---
+ src/qemu/qemu_domain.c   | 4 +---
+ src/util/vircgroup.c     | 8 +-------
+ src/util/virdevmapper.c  | 4 +---
+ src/util/virutil.c       | 4 +---
+ tests/vircgroupmock.c    | 8 +-------
+ 8 files changed, 8 insertions(+), 32 deletions(-)
+
+diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
+index fdccc585fb..6d3579e0f6 100644
+--- a/src/conf/domain_audit.c
++++ b/src/conf/domain_audit.c
+@@ -23,9 +23,7 @@
+ 
+ #include <sys/stat.h>
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
++#ifdef __linux__
+ # include <sys/sysmacros.h>
+ #endif
+ 
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index 42c631ed0b..0da89dba89 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -25,9 +25,7 @@
+ #include <sys/wait.h>
+ #include <sys/socket.h>
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
++#ifdef __linux__
+ # include <sys/sysmacros.h>
+ #endif
+ 
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index 780c6ed4a2..a8c93dd228 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -25,9 +25,7 @@
+ #include <sched.h>
+ #include <sys/utsname.h>
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
++#ifdef __linux__
+ # include <sys/sysmacros.h>
+ #endif
+ 
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 1e968368ae..ffe88ff027 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -64,9 +64,7 @@
+ #include "backup_conf.h"
+ #include "virdevmapper.h"
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
++#ifdef __linux__
+ # include <sys/sysmacros.h>
+ #endif
+ #include <sys/time.h>
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index dff2f6fd3a..a45c2e7f2f 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -25,13 +25,7 @@
+ # include <sys/mount.h>
+ # include <fcntl.h>
+ # include <sys/stat.h>
+-
+-# ifdef MAJOR_IN_MKDEV
+-#  include <sys/mkdev.h>
+-# elif MAJOR_IN_SYSMACROS
+-#  include <sys/sysmacros.h>
+-# endif
+-
++# include <sys/sysmacros.h>
+ # include <sys/types.h>
+ # include <signal.h>
+ # include <dirent.h>
+diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c
+index c346432d86..40a82285f9 100644
+--- a/src/util/virdevmapper.c
++++ b/src/util/virdevmapper.c
+@@ -20,9 +20,7 @@
+ 
+ #include <config.h>
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
++#ifdef __linux__
+ # include <sys/sysmacros.h>
+ #endif
+ 
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index 17fd06dbb2..5e6bbb37c0 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -28,9 +28,7 @@
+ #include <poll.h>
+ #include <sys/stat.h>
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
++#ifdef __linux__
+ # include <sys/sysmacros.h>
+ #endif
+ 
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index 9ec3b576d2..66b8c01852 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -23,13 +23,7 @@
+ # include <unistd.h>
+ # include <fcntl.h>
+ # include <sys/stat.h>
+-
+-# ifdef MAJOR_IN_MKDEV
+-#  include <sys/mkdev.h>
+-# elif MAJOR_IN_SYSMACROS
+-#  include <sys/sysmacros.h>
+-# endif
+-
++# include <sys/sysmacros.h>
+ # include <stdarg.h>
+ # include "testutilslxc.h"
+ # include "virstring.h"
+-- 
+2.28.0
+
diff --git a/SOURCES/libvirt-virDevMapperGetTargets-Don-t-ignore-EBADF.patch b/SOURCES/libvirt-virDevMapperGetTargets-Don-t-ignore-EBADF.patch
new file mode 100644
index 0000000..077da01
--- /dev/null
+++ b/SOURCES/libvirt-virDevMapperGetTargets-Don-t-ignore-EBADF.patch
@@ -0,0 +1,61 @@
+From 16b2178f23f82688b988c12bf7ee6caa97974669 Mon Sep 17 00:00:00 2001
+Message-Id: <16b2178f23f82688b988c12bf7ee6caa97974669@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 27 Jul 2020 12:36:53 +0200
+Subject: [PATCH] virDevMapperGetTargets: Don't ignore EBADF
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit e450ebb4c6eab1b7376a5ba873d10936ad563b75)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1860421
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <6dc32e8797122ad9ecd44a60aaff8e70d060b3b9.1595846084.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_cgroup.c | 2 +-
+ src/qemu/qemu_domain.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
+index 57a1231855..3a62b4ac15 100644
+--- a/src/qemu/qemu_cgroup.c
++++ b/src/qemu/qemu_cgroup.c
+@@ -89,7 +89,7 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
+     }
+ 
+     if (virDevMapperGetTargets(path, &targetPaths) < 0 &&
+-        errno != ENOSYS && errno != EBADF) {
++        errno != ENOSYS) {
+         virReportSystemError(errno,
+                              _("Unable to get devmapper targets for %s"),
+                              path);
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index ffe88ff027..35b536868a 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -14924,7 +14924,7 @@ qemuDomainSetupDisk(virQEMUDriverConfigPtr cfg G_GNUC_UNUSED,
+                 goto cleanup;
+ 
+             if (virDevMapperGetTargets(next->path, &targetPaths) < 0 &&
+-                errno != ENOSYS && errno != EBADF) {
++                errno != ENOSYS) {
+                 virReportSystemError(errno,
+                                      _("Unable to get devmapper targets for %s"),
+                                      next->path);
+@@ -15985,7 +15985,7 @@ qemuDomainNamespaceSetupDisk(virDomainObjPtr vm,
+             tmpPath = g_strdup(next->path);
+ 
+             if (virDevMapperGetTargets(next->path, &targetPaths) < 0 &&
+-                errno != ENOSYS && errno != EBADF) {
++                errno != ENOSYS) {
+                 virReportSystemError(errno,
+                                      _("Unable to get devmapper targets for %s"),
+                                      next->path);
+-- 
+2.28.0
+
diff --git a/SOURCES/libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch b/SOURCES/libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch
new file mode 100644
index 0000000..2d72c75
--- /dev/null
+++ b/SOURCES/libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch
@@ -0,0 +1,73 @@
+From 318beaace7890f3ccf2d09c1afcdde40f4f0284f Mon Sep 17 00:00:00 2001
+Message-Id: <318beaace7890f3ccf2d09c1afcdde40f4f0284f@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 27 Jul 2020 12:36:51 +0200
+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 <mprivozn@redhat.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit b8ebbe05451fde7ce541564f73437a29ffd5db0d)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1860421
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <c93475780b29c50e19492521e3b9cd19498f119b.1595846084.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ 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 118dc82e94..44c4731fb4 100644
+--- a/src/util/virdevmapper.c
++++ b/src/util/virdevmapper.c
+@@ -67,8 +67,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;
+ 
+@@ -133,28 +132,19 @@ virDevMapperGetTargetsImpl(const char *path,
+                                       minor(deps->device[i]));
+     }
+ 
+-    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;
+-
+     *devPaths_ret = g_steal_pointer(&devPaths);
+     ret = 0;
+  cleanup:
+-    virStringListFree(recursiveDevPaths);
+-    virStringListFree(devPaths);
+     dm_task_destroy(dmt);
+     return ret;
+ }
+-- 
+2.28.0
+
diff --git a/SOURCES/libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch b/SOURCES/libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch
new file mode 100644
index 0000000..27647cd
--- /dev/null
+++ b/SOURCES/libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch
@@ -0,0 +1,467 @@
+From 7ba9a0bbdf30984c13e7719e0646fffc7539f853 Mon Sep 17 00:00:00 2001
+Message-Id: <7ba9a0bbdf30984c13e7719e0646fffc7539f853@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 27 Jul 2020 12:36:52 +0200
+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 <mprivozn@redhat.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit 22494556542c676d1b9e7f1c1f2ea13ac17e1e3e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1860421
+
+Conflicts:
+- po/POTFILES.in - In c6a0d3ff8b4ead3b1f38a40668df65f152cc2f32
+  (po: change the format of POTFILES.in) we've changed the format
+  of the file and haven't backported it, yet.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <bf0ad2c93723aab2579368496aab4289701a94d8.1595846084.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ po/POTFILES.in          |   1 +
+ src/util/virdevmapper.c | 300 +++++++++++++++++++++++++++++-----------
+ 2 files changed, 217 insertions(+), 84 deletions(-)
+
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 29984042f4..49348292eb 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -238,6 +238,7 @@
+ @SRCDIR@/src/util/vircrypto.c
+ @SRCDIR@/src/util/virdbus.c
+ @SRCDIR@/src/util/virdnsmasq.c
++@SRCDIR@/src/util/virdevmapper.c
+ @SRCDIR@/src/util/virerror.c
+ @SRCDIR@/src/util/virerror.h
+ @SRCDIR@/src/util/virevent.c
+diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c
+index 44c4731fb4..a471504176 100644
+--- a/src/util/virdevmapper.c
++++ b/src/util/virdevmapper.c
+@@ -20,38 +20,67 @@
+ 
+ #include <config.h>
+ 
++#include "virdevmapper.h"
++#include "internal.h"
++
+ #ifdef __linux__
+ # include <sys/sysmacros.h>
+-#endif
++# include <linux/dm-ioctl.h>
++# include <sys/ioctl.h>
++# include <sys/types.h>
++# include <sys/stat.h>
++# include <fcntl.h>
+ 
+-#ifdef WITH_DEVMAPPER
+-# include <libdevmapper.h>
+-#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)
++
++G_STATIC_ASSERT(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 G_GNUC_UNUSED,
+-                        const char *file G_GNUC_UNUSED,
+-                        int line G_GNUC_UNUSED,
+-                        int dm_errno G_GNUC_UNUSED,
+-                        const char *fmt G_GNUC_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);
++    g_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++) {
++        g_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;
+ }
+ 
+@@ -59,94 +88,190 @@ 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:
++    *buf = g_new0(char, bufsize);
++
++    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,
++virDMOpen(void)
++{
++    VIR_AUTOCLOSE controlFD = -1;
++    struct dm_ioctl dm;
++    g_autofree char *tmp = NULL;
++    int ret;
++
++    memset(&dm, 0, sizeof(dm));
++
++    if ((controlFD = open(CONTROL_PATH, O_RDWR)) < 0)
++        return -1;
++
++    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)
++{
++    g_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)
++        return g_strdup(path);
++    else
++        p++;
++
++    /* 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;
++    }
++
++    dmDirPath = g_strdup_printf(DEV_DM_DIR "/%s", p);
++
++    if (stat(dmDirPath, &sb[1]) == 0 &&
++        sb[0].st_rdev == sb[1].st_rdev) {
++        return g_strdup(p);
++    }
++
++    /* 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) {
++        g_autofree char *tmp = g_strdup_printf(DEV_DM_DIR "/%s", ent->d_name);
++
++        if (stat(tmp, &sb[1]) == 0 &&
++            sb[0].st_rdev == sb[0].st_rdev) {
++            ret = g_steal_pointer(&tmp);
++            break;
++        }
++    }
++
++    virDirClose(&dh);
++    return ret;
++}
++
++
++static int
++virDevMapperGetTargetsImpl(int controlFD,
++                           const char *path,
+                            char ***devPaths_ret,
+                            unsigned int ttl)
+ {
+-    struct dm_task *dmt = NULL;
+-    struct dm_deps *deps;
+-    struct dm_info info;
++    g_autofree char *sanitizedPath = NULL;
++    g_autofree char *buf = NULL;
++    struct dm_ioctl dm;
++    struct dm_target_deps *deps = NULL;
+     VIR_AUTOSTRINGLIST devPaths = NULL;
+     size_t i;
+-    int ret = -1;
+ 
++    memset(&dm, 0, sizeof(dm));
+     *devPaths_ret = NULL;
+ 
+-    if (virDevMapperInitialize() < 0)
+-        return ret;
+-
+     if (ttl == 0) {
+         errno = ELOOP;
+-        return ret;
++        return -1;
+     }
+ 
+     if (!virIsDevMapperDevice(path))
+         return 0;
+ 
+-    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;
+-        }
+-        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;
+-        }
+-        goto cleanup;
+-    }
+-
+-    dm_task_no_open_count(dmt);
++    if (!(sanitizedPath = virDMSanitizepath(path)))
++        return 0;
+ 
+-    if (!dm_task_run(dmt)) {
+-        if (errno == ENXIO) {
+-            /* If @path = "/dev/mapper/control" ENXIO is returned. */
+-            ret = 0;
+-        }
+-        goto cleanup;
++    if (virStrncpy(dm.name, sanitizedPath, -1, DM_TABLE_DEPS) < 0) {
++        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
++                       _("Resolved device mapper name too long"));
++        return -1;
+     }
+ 
+-    if (!dm_task_get_info(dmt, &info))
+-        goto cleanup;
++    deps = virDMIoctl(controlFD, DM_TABLE_DEPS, &dm, &buf);
++    if (!deps) {
++        if (errno == ENXIO)
++            return 0;
+ 
+-    if (!info.exists) {
+-        ret = 0;
+-        goto cleanup;
++        virReportSystemError(errno,
++                             _("Unable to query dependencies for %s"),
++                             path);
++        return -1;
+     }
+ 
+-    if (!(deps = dm_task_get_deps(dmt)))
+-        goto cleanup;
+-
+     if (VIR_ALLOC_N_QUIET(devPaths, deps->count + 1) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     for (i = 0; i < deps->count; i++) {
+         devPaths[i] = g_strdup_printf("/dev/block/%u:%u",
+-                                      major(deps->device[i]),
+-                                      minor(deps->device[i]));
++                                      major(deps->dev[i]),
++                                      minor(deps->dev[i]));
+     }
+ 
+     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;
+     }
+ 
+     *devPaths_ret = g_steal_pointer(&devPaths);
+-    ret = 0;
+- cleanup:
+-    dm_task_destroy(dmt);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -165,9 +290,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)
+@@ -176,13 +298,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);
+ }
+ 
+ 
+@@ -191,15 +320,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 G_GNUC_UNUSED,
+@@ -215,4 +347,4 @@ virIsDevMapperDevice(const char *dev_name G_GNUC_UNUSED)
+ {
+     return false;
+ }
+-#endif /* ! WITH_DEVMAPPER */
++#endif /* ! defined(__linux__) */
+-- 
+2.28.0
+
diff --git a/SOURCES/libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch b/SOURCES/libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch
new file mode 100644
index 0000000..c3b6b78
--- /dev/null
+++ b/SOURCES/libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch
@@ -0,0 +1,69 @@
+From 4e021109613173e72df17eca6bff970ebb86b47f Mon Sep 17 00:00:00 2001
+Message-Id: <4e021109613173e72df17eca6bff970ebb86b47f@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 27 Jul 2020 12:36:50 +0200
+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 <mprivozn@redhat.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit ae5752aabc09f435675504246e30a0b9c4795d79)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1860421
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <2b5410a10bb23e8a9526c663052afbb6f37b0a0c.1595846084.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ 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 40a82285f9..118dc82e94 100644
+--- a/src/util/virdevmapper.c
++++ b/src/util/virdevmapper.c
+@@ -195,19 +195,7 @@ virDevMapperGetTargets(const char *path,
+     return virDevMapperGetTargetsImpl(path, devPaths, ttl);
+ }
+ 
+-#else /* ! WITH_DEVMAPPER */
+-
+-int
+-virDevMapperGetTargets(const char *path G_GNUC_UNUSED,
+-                       char ***devPaths G_GNUC_UNUSED)
+-{
+-    errno = ENOSYS;
+-    return -1;
+-}
+-#endif /* ! WITH_DEVMAPPER */
+ 
+-
+-#if WITH_DEVMAPPER
+ bool
+ virIsDevMapperDevice(const char *dev_name)
+ {
+@@ -223,6 +211,15 @@ virIsDevMapperDevice(const char *dev_name)
+ 
+ #else /* ! WITH_DEVMAPPER */
+ 
++int
++virDevMapperGetTargets(const char *path G_GNUC_UNUSED,
++                       char ***devPaths G_GNUC_UNUSED)
++{
++    errno = ENOSYS;
++    return -1;
++}
++
++
+ bool
+ virIsDevMapperDevice(const char *dev_name G_GNUC_UNUSED)
+ {
+-- 
+2.28.0
+
diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec
index ed004d6..f8dfb3c 100644
--- a/SPECS/libvirt.spec
+++ b/SPECS/libvirt.spec
@@ -219,7 +219,7 @@
 Summary: Library providing a simple virtualization API
 Name: libvirt
 Version: 6.0.0
-Release: 25%{?dist}%{?extra_release}
+Release: 27%{?dist}%{?extra_release}
 License: LGPLv2+
 URL: https://libvirt.org/
 
@@ -656,6 +656,16 @@ Patch424: libvirt-tools-Secure-guest-check-on-s390-in-virt-host-validate.patch
 Patch425: libvirt-tools-Secure-guest-check-for-AMD-in-virt-host-validate.patch
 Patch426: libvirt-docs-Update-AMD-launch-secure-description.patch
 Patch427: libvirt-docs-Describe-protected-virtualization-guest-setup.patch
+Patch428: libvirt-qemu-blockjob-Don-t-base-bitmap-handling-of-active-layer-block-commit-on-QEMU_CAPS_BLOCKDEV_REOPEN.patch
+Patch429: libvirt-qemu-blockjob-Actually-delete-temporary-bitmap-on-failed-active-commit.patch
+Patch430: libvirt-qemu-block-Remove-active-write-bitmap-even-if-there-are-no-bitmaps-to-merge.patch
+Patch431: libvirt-qemuDomainBlockPivot-Rename-actions-to-bitmapactions.patch
+Patch432: libvirt-qemuDomainBlockPivot-Ignore-failures-of-creating-active-layer-bitmap.patch
+Patch433: libvirt-src-assume-sys-sysmacros.h-always-exists-on-Linux.patch
+Patch434: libvirt-virdevmapper.c-Join-two-WITH_DEVMAPPER-sections-together.patch
+Patch435: libvirt-virDevMapperGetTargetsImpl-Use-VIR_AUTOSTRINGLIST.patch
+Patch436: libvirt-virdevmapper-Don-t-use-libdevmapper-to-obtain-dependencies.patch
+Patch437: libvirt-virDevMapperGetTargets-Don-t-ignore-EBADF.patch
 
 Requires: libvirt-daemon = %{version}-%{release}
 Requires: libvirt-daemon-config-network = %{version}-%{release}
@@ -2432,6 +2442,20 @@ exit 0
 
 
 %changelog
+* Fri Aug  7 2020 Jiri Denemark <jdenemar@redhat.com> - 6.0.0-27
+- src: assume sys/sysmacros.h always exists on Linux (rhbz#1860421)
+- virdevmapper.c: Join two WITH_DEVMAPPER sections together (rhbz#1860421)
+- virDevMapperGetTargetsImpl: Use VIR_AUTOSTRINGLIST (rhbz#1860421)
+- virdevmapper: Don't use libdevmapper to obtain dependencies (CVE-2020-14339, rhbz#1860421)
+- virDevMapperGetTargets: Don't ignore EBADF (rhbz#1860421)
+
+* Fri Jul 24 2020 Jiri Denemark <jdenemar@redhat.com> - 6.0.0-26
+- qemu: blockjob: Don't base bitmap handling of active-layer block commit on QEMU_CAPS_BLOCKDEV_REOPEN (rhbz#1857779)
+- qemu: blockjob: Actually delete temporary bitmap on failed active commit (rhbz#1857779)
+- qemu: block: Remove 'active-write' bitmap even if there are no bitmaps to merge (rhbz#1857779)
+- qemuDomainBlockPivot: Rename 'actions' to 'bitmapactions' (rhbz#1857779)
+- qemuDomainBlockPivot: Ignore failures of creating active layer bitmap (rhbz#1857779)
+
 * Wed Jun 24 2020 Jiri Denemark <jdenemar@redhat.com> - 6.0.0-25
 - Upgrade components in virt:rhel module:stream for RHEL-8.3 release (rhbz#1828317)
 - conf: Don't format http cookies unless VIR_DOMAIN_DEF_FORMAT_SECURE is used (CVE-2020-14301)