diff --git a/SOURCES/libvirt-Pass-oldDev-to-virDomainDefCompatibleDevice-on-device-update.patch b/SOURCES/libvirt-Pass-oldDev-to-virDomainDefCompatibleDevice-on-device-update.patch
new file mode 100644
index 0000000..cca3d5a
--- /dev/null
+++ b/SOURCES/libvirt-Pass-oldDev-to-virDomainDefCompatibleDevice-on-device-update.patch
@@ -0,0 +1,270 @@
+From 7164bcc8bec5165de244a74f32ca1469c7091d2d Mon Sep 17 00:00:00 2001
+Message-Id: <7164bcc8bec5165de244a74f32ca1469c7091d2d@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Thu, 22 Feb 2018 13:30:27 +0100
+Subject: [PATCH] Pass oldDev to virDomainDefCompatibleDevice on device update
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When calling virDomainDefCompatibleDevice to check a new device during
+device update, we need to pass the original device which is going to be
+updated in addition to the new device. Otherwise, the function can
+report false conflicts.
+
+The new argument is currently ignored by virDomainDefCompatibleDevice,
+but this will change in the following patch.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1546971
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit b6a264e8550d4add3946ec2fd9ae31a76fbf16fe)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1557922
+
+Conflicts:
+	src/qemu/qemu_driver.c -- context, qemuDomainUpdateDeviceLive
+            requires connection pointer in RHEL
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/domain_conf.c |  3 ++-
+ src/conf/domain_conf.h |  3 ++-
+ src/lxc/lxc_driver.c   | 15 ++++++++-----
+ src/qemu/qemu_driver.c | 51 +++++++++++++++++++++++++++++++++---------
+ 4 files changed, 54 insertions(+), 18 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 031d4b8e55..e9bba70057 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -27185,7 +27185,8 @@ virDomainDeviceInfoCheckBootIndex(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ 
+ int
+ virDomainDefCompatibleDevice(virDomainDefPtr def,
+-                             virDomainDeviceDefPtr dev)
++                             virDomainDeviceDefPtr dev,
++                             virDomainDeviceDefPtr oldDev ATTRIBUTE_UNUSED)
+ {
+     virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
+ 
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 3817887322..fb09496e89 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -3006,7 +3006,8 @@ typedef enum {
+ } virDomainDeviceAction;
+ 
+ int virDomainDefCompatibleDevice(virDomainDefPtr def,
+-                                 virDomainDeviceDefPtr dev);
++                                 virDomainDeviceDefPtr dev,
++                                 virDomainDeviceDefPtr oldDev);
+ 
+ void virDomainRNGDefFree(virDomainRNGDefPtr def);
+ 
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index 7829ef8618..fe2405d08b 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -3579,6 +3579,7 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
+ {
+     int ret = -1;
+     virDomainNetDefPtr net;
++    virDomainDeviceDef oldDev = { .type = dev->type };
+     int idx;
+ 
+     switch (dev->type) {
+@@ -3587,8 +3588,11 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
+         if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
+             goto cleanup;
+ 
+-        virDomainNetDefFree(vmdef->nets[idx]);
++        oldDev.data.net = vmdef->nets[idx];
++        if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0)
++            return -1;
+ 
++        virDomainNetDefFree(vmdef->nets[idx]);
+         vmdef->nets[idx] = net;
+         dev->data.net = NULL;
+         ret = 0;
+@@ -4791,7 +4795,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom,
+         if (!vmdef)
+             goto endjob;
+ 
+-        if (virDomainDefCompatibleDevice(vmdef, dev) < 0)
++        if (virDomainDefCompatibleDevice(vmdef, dev, NULL) < 0)
+             goto endjob;
+ 
+         if ((ret = lxcDomainAttachDeviceConfig(vmdef, dev)) < 0)
+@@ -4799,7 +4803,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom,
+     }
+ 
+     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+-        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
++        if (virDomainDefCompatibleDevice(vm->def, dev_copy, NULL) < 0)
+             goto endjob;
+ 
+         if ((ret = lxcDomainAttachDeviceLive(dom->conn, driver, vm, dev_copy)) < 0)
+@@ -4902,9 +4906,8 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom,
+         if (!vmdef)
+             goto endjob;
+ 
+-        if (virDomainDefCompatibleDevice(vmdef, dev) < 0)
+-            goto endjob;
+-
++        /* virDomainDefCompatibleDevice call is delayed until we know the
++         * device we're going to update. */
+         if ((ret = lxcDomainUpdateDeviceConfig(vmdef, dev)) < 0)
+             goto endjob;
+     }
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index b8022a06ba..3bd2d983a2 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -7830,6 +7830,7 @@ qemuDomainChangeDiskLive(virConnectPtr conn,
+ {
+     virDomainDiskDefPtr disk = dev->data.disk;
+     virDomainDiskDefPtr orig_disk = NULL;
++    virDomainDeviceDef oldDev = { .type = dev->type };
+     int ret = -1;
+ 
+     if (virStorageTranslateDiskSourcePool(conn, disk) < 0)
+@@ -7847,6 +7848,10 @@ qemuDomainChangeDiskLive(virConnectPtr conn,
+         goto cleanup;
+     }
+ 
++    oldDev.data.disk = orig_disk;
++    if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev) < 0)
++        goto cleanup;
++
+     if (!qemuDomainDiskChangeSupported(disk, orig_disk))
+         goto cleanup;
+ 
+@@ -7890,19 +7895,36 @@ qemuDomainUpdateDeviceLive(virConnectPtr conn,
+                            bool force)
+ {
+     virQEMUDriverPtr driver = dom->conn->privateData;
++    virDomainDeviceDef oldDev = { .type = dev->type };
+     int ret = -1;
++    int idx;
+ 
+     switch ((virDomainDeviceType) dev->type) {
+     case VIR_DOMAIN_DEVICE_DISK:
+         qemuDomainObjCheckDiskTaint(driver, vm, dev->data.disk, NULL);
+         ret = qemuDomainChangeDiskLive(conn, vm, dev, driver, force);
+         break;
++
+     case VIR_DOMAIN_DEVICE_GRAPHICS:
++        if ((idx = qemuDomainFindGraphicsIndex(vm->def, dev->data.graphics) >= 0)) {
++            oldDev.data.graphics = vm->def->graphics[idx];
++            if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev) < 0)
++                return -1;
++        }
++
+         ret = qemuDomainChangeGraphics(driver, vm, dev->data.graphics);
+         break;
++
+     case VIR_DOMAIN_DEVICE_NET:
++        if ((idx = virDomainNetFindIdx(vm->def, dev->data.net)) >= 0) {
++            oldDev.data.net = vm->def->nets[idx];
++            if (virDomainDefCompatibleDevice(vm->def, dev, &oldDev) < 0)
++                return -1;
++        }
++
+         ret = qemuDomainChangeNet(driver, vm, dev);
+         break;
++
+     case VIR_DOMAIN_DEVICE_FS:
+     case VIR_DOMAIN_DEVICE_INPUT:
+     case VIR_DOMAIN_DEVICE_SOUND:
+@@ -8317,6 +8339,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
+     virDomainDiskDefPtr newDisk;
+     virDomainGraphicsDefPtr newGraphics;
+     virDomainNetDefPtr net;
++    virDomainDeviceDef oldDev = { .type = dev->type };
+     int pos;
+ 
+     switch ((virDomainDeviceType) dev->type) {
+@@ -8328,6 +8351,10 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
+             return -1;
+         }
+ 
++        oldDev.data.disk = vmdef->disks[pos];
++        if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0)
++            return -1;
++
+         virDomainDiskDefFree(vmdef->disks[pos]);
+         vmdef->disks[pos] = newDisk;
+         dev->data.disk = NULL;
+@@ -8343,8 +8370,11 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
+             return -1;
+         }
+ 
+-        virDomainGraphicsDefFree(vmdef->graphics[pos]);
++        oldDev.data.graphics = vmdef->graphics[pos];
++        if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0)
++            return -1;
+ 
++        virDomainGraphicsDefFree(vmdef->graphics[pos]);
+         vmdef->graphics[pos] = newGraphics;
+         dev->data.graphics = NULL;
+         break;
+@@ -8354,8 +8384,11 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
+         if ((pos = virDomainNetFindIdx(vmdef, net)) < 0)
+             return -1;
+ 
+-        virDomainNetDefFree(vmdef->nets[pos]);
++        oldDev.data.net = vmdef->nets[pos];
++        if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev) < 0)
++            return -1;
+ 
++        virDomainNetDefFree(vmdef->nets[pos]);
+         vmdef->nets[pos] = net;
+         dev->data.net = NULL;
+         break;
+@@ -8443,7 +8476,7 @@ qemuDomainAttachDeviceLiveAndConfig(virConnectPtr conn,
+         if (!vmdef)
+             goto cleanup;
+ 
+-        if (virDomainDefCompatibleDevice(vmdef, dev) < 0)
++        if (virDomainDefCompatibleDevice(vmdef, dev, NULL) < 0)
+             goto cleanup;
+         if ((ret = qemuDomainAttachDeviceConfig(vmdef, dev, conn, caps,
+                                                 parse_flags,
+@@ -8452,7 +8485,7 @@ qemuDomainAttachDeviceLiveAndConfig(virConnectPtr conn,
+     }
+ 
+     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+-        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
++        if (virDomainDefCompatibleDevice(vm->def, dev_copy, NULL) < 0)
+             goto cleanup;
+ 
+         if ((ret = qemuDomainAttachDeviceLive(vm, dev_copy, conn, driver)) < 0)
+@@ -8592,9 +8625,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
+         if (!vmdef)
+             goto endjob;
+ 
+-        if (virDomainDefCompatibleDevice(vmdef, dev) < 0)
+-            goto endjob;
+-
++        /* virDomainDefCompatibleDevice call is delayed until we know the
++         * device we're going to update. */
+         if ((ret = qemuDomainUpdateDeviceConfig(vmdef, dev, caps,
+                                                 parse_flags,
+                                                 driver->xmlopt)) < 0)
+@@ -8602,9 +8634,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
+     }
+ 
+     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+-        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
+-            goto endjob;
+-
++        /* virDomainDefCompatibleDevice call is delayed until we know the
++         * device we're going to update. */
+         if ((ret = qemuDomainUpdateDeviceLive(dom->conn, vm, dev_copy, dom, force)) < 0)
+             goto endjob;
+         /*
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-conf-Fix-crash-in-virDomainDefCompatibleDevice.patch b/SOURCES/libvirt-conf-Fix-crash-in-virDomainDefCompatibleDevice.patch
new file mode 100644
index 0000000..08e18b5
--- /dev/null
+++ b/SOURCES/libvirt-conf-Fix-crash-in-virDomainDefCompatibleDevice.patch
@@ -0,0 +1,47 @@
+From b5eaca77959775ffce33c459a06f0dcacee5338d Mon Sep 17 00:00:00 2001
+Message-Id: <b5eaca77959775ffce33c459a06f0dcacee5338d@dist-git>
+From: John Ferlan <jferlan@redhat.com>
+Date: Thu, 1 Mar 2018 07:08:32 -0500
+Subject: [PATCH] conf: Fix crash in virDomainDefCompatibleDevice
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit id 'edae027c' blindly assumed that the passed @oldDev
+parameter would not be NULL when calling virDomainDeviceGetInfo;
+however, commit id 'b6a264e8' passed NULL for AttachDevice
+callers under the premise that there wouldn't be a device
+to check/update against.
+
+Signed-off-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 5535856f0e31aa6abf4cda11b5c53c0f164680f0)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1557922
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/domain_conf.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index f21c776ccd..7f4da169d6 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -27202,9 +27202,12 @@ virDomainDefCompatibleDevice(virDomainDefPtr def,
+ {
+     virDomainCompatibleDeviceData data = {
+         .newInfo = virDomainDeviceGetInfo(dev),
+-        .oldInfo = virDomainDeviceGetInfo(oldDev),
++        .oldInfo = NULL,
+     };
+ 
++    if (oldDev)
++        data.oldInfo = virDomainDeviceGetInfo(oldDev);
++
+     if (!virDomainDefHasUSB(def) &&
+         def->os.type != VIR_DOMAIN_OSTYPE_EXE &&
+         virDomainDeviceIsUSB(dev)) {
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-internal-add-STRCASEPREFIX.patch b/SOURCES/libvirt-internal-add-STRCASEPREFIX.patch
new file mode 100644
index 0000000..e196502
--- /dev/null
+++ b/SOURCES/libvirt-internal-add-STRCASEPREFIX.patch
@@ -0,0 +1,36 @@
+From d31ebaf3eb3c4ead397c054cbe1a7dbfe331aad5 Mon Sep 17 00:00:00 2001
+Message-Id: <d31ebaf3eb3c4ead397c054cbe1a7dbfe331aad5@dist-git>
+From: Pino Toscano <ptoscano@redhat.com>
+Date: Thu, 12 Apr 2018 17:26:20 +0200
+Subject: [PATCH] internal: add STRCASEPREFIX
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Simple macro to check the prefix of a string in a case-insensitive way.
+
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+(cherry picked from commit e508e04b108709af0ca2c4d6728440b0edc3cc4b)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1566524
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/internal.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/internal.h b/src/internal.h
+index c29f20f022..f5e7a1886c 100644
+--- a/src/internal.h
++++ b/src/internal.h
+@@ -75,6 +75,7 @@
+ # define STRNEQLEN(a, b, n) (strncmp(a, b, n) != 0)
+ # define STRCASENEQLEN(a, b, n) (c_strncasecmp(a, b, n) != 0)
+ # define STRPREFIX(a, b) (strncmp(a, b, strlen(b)) == 0)
++# define STRCASEPREFIX(a, b) (c_strncasecmp(a, b, strlen(b)) == 0)
+ # define STRSKIP(a, b) (STRPREFIX(a, b) ? (a) + strlen(b) : NULL)
+ 
+ # define STREQ_NULLABLE(a, b)                           \
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-lxc-Drop-useless-check-in-live-device-update.patch b/SOURCES/libvirt-lxc-Drop-useless-check-in-live-device-update.patch
new file mode 100644
index 0000000..7b6e89c
--- /dev/null
+++ b/SOURCES/libvirt-lxc-Drop-useless-check-in-live-device-update.patch
@@ -0,0 +1,40 @@
+From 442ccfef325b73b201332c89cc53421f8299998e Mon Sep 17 00:00:00 2001
+Message-Id: <442ccfef325b73b201332c89cc53421f8299998e@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Thu, 22 Feb 2018 13:22:39 +0100
+Subject: [PATCH] lxc: Drop useless check in live device update
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Checking the new device definition makes little sense when lxc driver
+does not support live device update at all.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit e3497f3fc895c427ce35188f3ddb2bb47a853be9)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1557922
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/lxc/lxc_driver.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index b3f6f064f3..7829ef8618 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -4910,9 +4910,6 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom,
+     }
+ 
+     if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+-        if (virDomainDefCompatibleDevice(vm->def, dev_copy) < 0)
+-            goto endjob;
+-
+         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                        _("Unable to modify live devices"));
+ 
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-qemu-Fix-updating-device-with-boot-order.patch b/SOURCES/libvirt-qemu-Fix-updating-device-with-boot-order.patch
new file mode 100644
index 0000000..d554a0d
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Fix-updating-device-with-boot-order.patch
@@ -0,0 +1,105 @@
+From b3bd3f499bcf2fa9b2d61b5291e0a50bc7e8e595 Mon Sep 17 00:00:00 2001
+Message-Id: <b3bd3f499bcf2fa9b2d61b5291e0a50bc7e8e595@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Thu, 22 Feb 2018 13:51:36 +0100
+Subject: [PATCH] qemu: Fix updating device with boot order
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit v3.7.0-14-gc57f3fd2f8 prevented adding a <boot order='x'/>
+element to an inactive domain with global <boot dev='...'/> element.
+However, as a result of that change updating any device with boot order
+would fail with 'boot order X is already used by another device', where
+"another device" is in fact the device which is being updated.
+
+To fix this we have to ignore the device which we're about to update
+when checking for boot order conflicts.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1546971
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit edae027cfe02be4863dcef1e7f0ea0564766e312)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1557922
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/domain_conf.c | 29 ++++++++++++++++++++++-------
+ 1 file changed, 22 insertions(+), 7 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index e9bba70057..f21c776ccd 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -27166,18 +27166,30 @@ virDomainDeviceIsUSB(virDomainDeviceDefPtr dev)
+     return false;
+ }
+ 
++
++typedef struct _virDomainCompatibleDeviceData virDomainCompatibleDeviceData;
++typedef virDomainCompatibleDeviceData *virDomainCompatibleDeviceDataPtr;
++struct _virDomainCompatibleDeviceData {
++    virDomainDeviceInfoPtr newInfo;
++    virDomainDeviceInfoPtr oldInfo;
++};
++
+ static int
+ virDomainDeviceInfoCheckBootIndex(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                   virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
+                                   virDomainDeviceInfoPtr info,
+                                   void *opaque)
+ {
+-    virDomainDeviceInfoPtr newinfo = opaque;
++    virDomainCompatibleDeviceDataPtr data = opaque;
+ 
+-    if (info->bootIndex == newinfo->bootIndex) {
++    /* Ignore the device we're about to update */
++    if (data->oldInfo == info)
++        return 0;
++
++    if (info->bootIndex == data->newInfo->bootIndex) {
+         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                        _("boot order %u is already used by another device"),
+-                       newinfo->bootIndex);
++                       data->newInfo->bootIndex);
+         return -1;
+     }
+     return 0;
+@@ -27186,9 +27198,12 @@ virDomainDeviceInfoCheckBootIndex(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ int
+ virDomainDefCompatibleDevice(virDomainDefPtr def,
+                              virDomainDeviceDefPtr dev,
+-                             virDomainDeviceDefPtr oldDev ATTRIBUTE_UNUSED)
++                             virDomainDeviceDefPtr oldDev)
+ {
+-    virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
++    virDomainCompatibleDeviceData data = {
++        .newInfo = virDomainDeviceGetInfo(dev),
++        .oldInfo = virDomainDeviceGetInfo(oldDev),
++    };
+ 
+     if (!virDomainDefHasUSB(def) &&
+         def->os.type != VIR_DOMAIN_OSTYPE_EXE &&
+@@ -27199,7 +27214,7 @@ virDomainDefCompatibleDevice(virDomainDefPtr def,
+         return -1;
+     }
+ 
+-    if (info && info->bootIndex > 0) {
++    if (data.newInfo && data.newInfo->bootIndex > 0) {
+         if (def->os.nBootDevs > 0) {
+             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                            _("per-device boot elements cannot be used"
+@@ -27208,7 +27223,7 @@ virDomainDefCompatibleDevice(virDomainDefPtr def,
+         }
+         if (virDomainDeviceInfoIterate(def,
+                                        virDomainDeviceInfoCheckBootIndex,
+-                                       info) < 0)
++                                       &data) < 0)
+             return -1;
+     }
+ 
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-qemu-Use-dynamic-buffer-for-storing-PTY-aliases.patch b/SOURCES/libvirt-qemu-Use-dynamic-buffer-for-storing-PTY-aliases.patch
new file mode 100644
index 0000000..1486977
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Use-dynamic-buffer-for-storing-PTY-aliases.patch
@@ -0,0 +1,124 @@
+From fd11d55c30553c37d3d71d202348ac22029cba8d Mon Sep 17 00:00:00 2001
+Message-Id: <fd11d55c30553c37d3d71d202348ac22029cba8d@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 13 Apr 2018 10:09:29 +0200
+Subject: [PATCH] qemu: Use dynamic buffer for storing PTY aliases
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RHEL-7.6: https://bugzilla.redhat.com/show_bug.cgi?id=1560976
+RHEL-7.5.z: https://bugzilla.redhat.com/show_bug.cgi?id=1566525
+
+For historical reasons we've used 32 bytes long static buffer for
+storing PTY aliases. This breaks users scenario where they try to
+start a machine with user alias consisting of "ua-$uuid".
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit c4c32cb300beba41ecbca3ee4884c65630bde861)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+---
+ src/qemu/qemu_process.c | 39 ++++++++++++++++++++-------------------
+ 1 file changed, 20 insertions(+), 19 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index c86f7d3c5b..04147f381e 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -1931,21 +1931,18 @@ qemuProcessLookupPTYs(virDomainChrDefPtr *devices,
+                       int count,
+                       virHashTablePtr info)
+ {
++    char *id = NULL;
+     size_t i;
++    int ret = -1;
+ 
+     for (i = 0; i < count; i++) {
+         virDomainChrDefPtr chr = devices[i];
+         if (chr->source->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+-            char id[32];
+             qemuMonitorChardevInfoPtr entry;
+ 
+-            if (snprintf(id, sizeof(id), "char%s",
+-                         chr->info.alias) >= sizeof(id)) {
+-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                               _("failed to format device alias "
+-                                 "for PTY retrieval"));
++            VIR_FREE(id);
++            if (virAsprintf(&id, "char%s", chr->info.alias) < 0)
+                 return -1;
+-            }
+ 
+             entry = virHashLookup(info, id);
+             if (!entry || !entry->ptyPath) {
+@@ -1955,7 +1952,7 @@ qemuProcessLookupPTYs(virDomainChrDefPtr *devices,
+                      */
+                     virReportError(VIR_ERR_INTERNAL_ERROR,
+                                    _("no assigned pty for device %s"), id);
+-                    return -1;
++                    goto cleanup;
+                 } else {
+                     /* 'info chardev' had no pty path for this chardev,
+                      * but the log output had, so we're fine
+@@ -1966,11 +1963,14 @@ qemuProcessLookupPTYs(virDomainChrDefPtr *devices,
+ 
+             VIR_FREE(chr->source->data.file.path);
+             if (VIR_STRDUP(chr->source->data.file.path, entry->ptyPath) < 0)
+-                return -1;
++                goto cleanup;
+         }
+     }
+ 
+-    return 0;
++    ret = 0;
++ cleanup:
++    VIR_FREE(id);
++    return ret;
+ }
+ 
+ static int
+@@ -2022,7 +2022,8 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
+     int agentReason = VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL;
+     qemuMonitorChardevInfoPtr entry;
+     virObjectEventPtr event = NULL;
+-    char id[32];
++    char *id = NULL;
++    int ret = -1;
+ 
+     if (booted)
+         agentReason = VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_DOMAIN_STARTED;
+@@ -2030,13 +2031,10 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
+     for (i = 0; i < vm->def->nchannels; i++) {
+         virDomainChrDefPtr chr = vm->def->channels[i];
+         if (chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
+-            if (snprintf(id, sizeof(id), "char%s",
+-                         chr->info.alias) >= sizeof(id)) {
+-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                               _("failed to format device alias "
+-                                 "for PTY retrieval"));
+-                return -1;
+-            }
++
++            VIR_FREE(id);
++            if (virAsprintf(&id, "char%s", chr->info.alias) < 0)
++                goto cleanup;
+ 
+             /* port state not reported */
+             if (!(entry = virHashLookup(info, id)) ||
+@@ -2053,7 +2051,10 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
+         }
+     }
+ 
+-    return 0;
++    ret = 0;
++ cleanup:
++    VIR_FREE(id);
++    return ret;
+ }
+ 
+ 
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-guest-agent-CVE-2018-1064.patch b/SOURCES/libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-guest-agent-CVE-2018-1064.patch
new file mode 100644
index 0000000..8345e72
--- /dev/null
+++ b/SOURCES/libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-guest-agent-CVE-2018-1064.patch
@@ -0,0 +1,64 @@
+From d0b7ef97c4c5fe871664f2a952c8c3b0b4417d23 Mon Sep 17 00:00:00 2001
+Message-Id: <d0b7ef97c4c5fe871664f2a952c8c3b0b4417d23@dist-git>
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Thu, 1 Mar 2018 14:55:26 +0000
+Subject: [PATCH] qemu: avoid denial of service reading from QEMU guest agent
+ (CVE-2018-1064)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We read from the agent until seeing a \r\n pair to indicate a completed
+reply or event. To avoid memory denial-of-service though, we must have a
+size limit on amount of data we buffer. 10 MB is large enough that it
+ought to cope with normal agent replies, and small enough that we're not
+consuming unreasonable mem.
+
+This is identical to the flaw we had reading from the QEMU monitor
+as CVE-2018-5748, so rather embarrassing that we forgot to fix
+the agent code at the same time.
+
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit fbf31e1a4cd19d6f6e33e0937a009775cd7d9513)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_agent.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
+index 5d125c4138..9cf767bd8a 100644
+--- a/src/qemu/qemu_agent.c
++++ b/src/qemu/qemu_agent.c
+@@ -53,6 +53,15 @@ VIR_LOG_INIT("qemu.qemu_agent");
+ #define DEBUG_IO 0
+ #define DEBUG_RAW_IO 0
+ 
++/* We read from QEMU until seeing a \r\n pair to indicate a
++ * completed reply or event. To avoid memory denial-of-service
++ * though, we must have a size limit on amount of data we
++ * buffer. 10 MB is large enough that it ought to cope with
++ * normal QEMU replies, and small enough that we're not
++ * consuming unreasonable mem.
++ */
++#define QEMU_AGENT_MAX_RESPONSE (10 * 1024 * 1024)
++
+ /* When you are the first to uncomment this,
+  * don't forget to uncomment the corresponding
+  * part in qemuAgentIOProcessEvent as well.
+@@ -535,6 +544,12 @@ qemuAgentIORead(qemuAgentPtr mon)
+     int ret = 0;
+ 
+     if (avail < 1024) {
++        if (mon->bufferLength >= QEMU_AGENT_MAX_RESPONSE) {
++            virReportSystemError(ERANGE,
++                                 _("No complete agent response found in %d bytes"),
++                                 QEMU_AGENT_MAX_RESPONSE);
++            return -1;
++        }
+         if (VIR_REALLOC_N(mon->buffer,
+                           mon->bufferLength + 1024) < 0)
+             return -1;
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-monitor-CVE-2018-5748.patch b/SOURCES/libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-monitor-CVE-2018-5748.patch
new file mode 100644
index 0000000..7630658
--- /dev/null
+++ b/SOURCES/libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-monitor-CVE-2018-5748.patch
@@ -0,0 +1,60 @@
+From 5e5d757a039a60cba5ac89fe1998673c49a2d0b6 Mon Sep 17 00:00:00 2001
+Message-Id: <5e5d757a039a60cba5ac89fe1998673c49a2d0b6@dist-git>
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Tue, 16 Jan 2018 17:00:11 +0000
+Subject: [PATCH] qemu: avoid denial of service reading from QEMU monitor
+ (CVE-2018-5748)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We read from QEMU until seeing a \r\n pair to indicate a completed reply
+or event. To avoid memory denial-of-service though, we must have a size
+limit on amount of data we buffer. 10 MB is large enough that it ought
+to cope with normal QEMU replies, and small enough that we're not
+consuming unreasonable mem.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+(cherry picked from commit bc251ea91bcfddd2622fce6bce701a438b2e7276)
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_monitor.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index b6af209a83..d999f2d10c 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -55,6 +55,15 @@ VIR_LOG_INIT("qemu.qemu_monitor");
+ #define DEBUG_IO 0
+ #define DEBUG_RAW_IO 0
+ 
++/* We read from QEMU until seeing a \r\n pair to indicate a
++ * completed reply or event. To avoid memory denial-of-service
++ * though, we must have a size limit on amount of data we
++ * buffer. 10 MB is large enough that it ought to cope with
++ * normal QEMU replies, and small enough that we're not
++ * consuming unreasonable mem.
++ */
++#define QEMU_MONITOR_MAX_RESPONSE (10 * 1024 * 1024)
++
+ struct _qemuMonitor {
+     virObjectLockable parent;
+ 
+@@ -574,6 +583,12 @@ qemuMonitorIORead(qemuMonitorPtr mon)
+     int ret = 0;
+ 
+     if (avail < 1024) {
++        if (mon->bufferLength >= QEMU_MONITOR_MAX_RESPONSE) {
++            virReportSystemError(ERANGE,
++                                 _("No complete monitor response found in %d bytes"),
++                                 QEMU_MONITOR_MAX_RESPONSE);
++            return -1;
++        }
+         if (VIR_REALLOC_N(mon->buffer,
+                           mon->bufferLength + 1024) < 0)
+             return -1;
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-qemu_cgroup-Fix-rc-argument-on-virDomainAuditCgroupPath-calls.patch b/SOURCES/libvirt-qemu_cgroup-Fix-rc-argument-on-virDomainAuditCgroupPath-calls.patch
new file mode 100644
index 0000000..0d090e6
--- /dev/null
+++ b/SOURCES/libvirt-qemu_cgroup-Fix-rc-argument-on-virDomainAuditCgroupPath-calls.patch
@@ -0,0 +1,165 @@
+From d25881180ef0b8b11bb5a51317cb49a194e37a76 Mon Sep 17 00:00:00 2001
+Message-Id: <d25881180ef0b8b11bb5a51317cb49a194e37a76@dist-git>
+From: Eduardo Habkost <ehabkost@redhat.com>
+Date: Mon, 9 Apr 2018 15:46:47 +0200
+Subject: [PATCH] qemu_cgroup: Fix 'rc' argument on virDomainAuditCgroupPath()
+ calls
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1564996
+
+All calls to virDomainAuditCgroupPath() were passing 'rc == 0' as
+argument, when it was supposed to pass the 'rc' value directly.
+
+As a consequence, the audit events that were supposed to be
+logged (actual cgroup changes) were never being logged, and bogus
+audit events were logged when using regular files as disk image.
+
+Fix all calls to use the return value of
+virCgroup{Allow,Deny}Device*() directly as the 'rc' argument.
+
+Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 9a22251bbe6a4ff8dab90da53a1c0df82d8d29fc)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_cgroup.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
+index 41e27c21e2..b604edb31c 100644
+--- a/src/qemu/qemu_cgroup.c
++++ b/src/qemu/qemu_cgroup.c
+@@ -75,7 +75,7 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
+ 
+     virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path,
+                              virCgroupGetDevicePermsString(perms),
+-                             ret == 0);
++                             ret);
+ 
+     return ret;
+ }
+@@ -129,7 +129,7 @@ qemuTeardownImageCgroup(virDomainObjPtr vm,
+     ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, true);
+ 
+     virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path,
+-                             virCgroupGetDevicePermsString(perms), ret == 0);
++                             virCgroupGetDevicePermsString(perms), ret);
+ 
+     return ret;
+ }
+@@ -187,7 +187,7 @@ qemuSetupChrSourceCgroup(virDomainObjPtr vm,
+     ret = virCgroupAllowDevicePath(priv->cgroup, source->data.file.path,
+                                    VIR_CGROUP_DEVICE_RW, false);
+     virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
+-                             source->data.file.path, "rw", ret == 0);
++                             source->data.file.path, "rw", ret);
+ 
+     return ret;
+ }
+@@ -211,7 +211,7 @@ qemuTeardownChrSourceCgroup(virDomainObjPtr vm,
+     ret = virCgroupDenyDevicePath(priv->cgroup, source->data.file.path,
+                                   VIR_CGROUP_DEVICE_RW, false);
+     virDomainAuditCgroupPath(vm, priv->cgroup, "deny",
+-                             source->data.file.path, "rw", ret == 0);
++                             source->data.file.path, "rw", ret);
+ 
+     return ret;
+ }
+@@ -261,7 +261,7 @@ qemuSetupInputCgroup(virDomainObjPtr vm,
+         VIR_DEBUG("Process path '%s' for input device", dev->source.evdev);
+         ret = virCgroupAllowDevicePath(priv->cgroup, dev->source.evdev,
+                                        VIR_CGROUP_DEVICE_RW, false);
+-        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", dev->source.evdev, "rw", ret == 0);
++        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", dev->source.evdev, "rw", ret);
+         break;
+     }
+ 
+@@ -284,7 +284,7 @@ qemuTeardownInputCgroup(virDomainObjPtr vm,
+         VIR_DEBUG("Process path '%s' for input device", dev->source.evdev);
+         ret = virCgroupDenyDevicePath(priv->cgroup, dev->source.evdev,
+                                       VIR_CGROUP_DEVICE_RWM, false);
+-        virDomainAuditCgroupPath(vm, priv->cgroup, "deny", dev->source.evdev, "rwm", ret == 0);
++        virDomainAuditCgroupPath(vm, priv->cgroup, "deny", dev->source.evdev, "rwm", ret);
+         break;
+     }
+ 
+@@ -313,7 +313,7 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm,
+         rv = virCgroupAllowDevicePath(priv->cgroup, path[i], perms[i], false);
+         virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path[i],
+                                  virCgroupGetDevicePermsString(perms[i]),
+-                                 ret == 0);
++                                 rv);
+         if (rv < 0)
+             goto cleanup;
+     }
+@@ -357,7 +357,7 @@ qemuTeardownHostdevCgroup(virDomainObjPtr vm,
+         rv = virCgroupDenyDevicePath(priv->cgroup, path[i],
+                                      VIR_CGROUP_DEVICE_RWM, false);
+         virDomainAuditCgroupPath(vm, priv->cgroup,
+-                                 "deny", path[i], "rwm", rv == 0);
++                                 "deny", path[i], "rwm", rv);
+         if (rv < 0)
+             goto cleanup;
+     }
+@@ -388,7 +388,7 @@ qemuSetupMemoryDevicesCgroup(virDomainObjPtr vm,
+     rv = virCgroupAllowDevicePath(priv->cgroup, mem->nvdimmPath,
+                                   VIR_CGROUP_DEVICE_RW, false);
+     virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
+-                             mem->nvdimmPath, "rw", rv == 0);
++                             mem->nvdimmPath, "rw", rv);
+ 
+     return rv;
+ }
+@@ -410,7 +410,7 @@ qemuTeardownMemoryDevicesCgroup(virDomainObjPtr vm,
+     rv = virCgroupDenyDevicePath(priv->cgroup, mem->nvdimmPath,
+                                  VIR_CGROUP_DEVICE_RWM, false);
+     virDomainAuditCgroupPath(vm, priv->cgroup,
+-                             "deny", mem->nvdimmPath, "rwm", rv == 0);
++                             "deny", mem->nvdimmPath, "rwm", rv);
+     return rv;
+ }
+ 
+@@ -434,7 +434,7 @@ qemuSetupGraphicsCgroup(virDomainObjPtr vm,
+     ret = virCgroupAllowDevicePath(priv->cgroup, rendernode,
+                                    VIR_CGROUP_DEVICE_RW, false);
+     virDomainAuditCgroupPath(vm, priv->cgroup, "allow", rendernode,
+-                             "rw", ret == 0);
++                             "rw", ret);
+     return ret;
+ }
+ 
+@@ -573,7 +573,7 @@ qemuSetupRNGCgroup(virDomainObjPtr vm,
+                                       VIR_CGROUP_DEVICE_RW, false);
+         virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
+                                  rng->source.file,
+-                                 "rw", rv == 0);
++                                 "rw", rv);
+         if (rv < 0 &&
+             !virLastErrorIsSystemErrno(ENOENT))
+             return -1;
+@@ -600,7 +600,7 @@ qemuTeardownRNGCgroup(virDomainObjPtr vm,
+                                      VIR_CGROUP_DEVICE_RW, false);
+         virDomainAuditCgroupPath(vm, priv->cgroup, "deny",
+                                  rng->source.file,
+-                                 "rw", rv == 0);
++                                 "rw", rv);
+         if (rv < 0 &&
+             !virLastErrorIsSystemErrno(ENOENT))
+             return -1;
+@@ -693,7 +693,7 @@ qemuSetupDevicesCgroup(virDomainObjPtr vm)
+ 
+         rv = virCgroupAllowDevicePath(priv->cgroup, deviceACL[i],
+                                       VIR_CGROUP_DEVICE_RW, false);
+-        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", deviceACL[i], "rw", rv == 0);
++        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", deviceACL[i], "rw", rv);
+         if (rv < 0 &&
+             !virLastErrorIsSystemErrno(ENOENT))
+             goto cleanup;
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-qemu_cgroup-Handle-device-mapper-targets-properly.patch b/SOURCES/libvirt-qemu_cgroup-Handle-device-mapper-targets-properly.patch
new file mode 100644
index 0000000..547c467
--- /dev/null
+++ b/SOURCES/libvirt-qemu_cgroup-Handle-device-mapper-targets-properly.patch
@@ -0,0 +1,119 @@
+From 2a7678f0966137f6e9b226934ab8dd67d6f2e963 Mon Sep 17 00:00:00 2001
+Message-Id: <2a7678f0966137f6e9b226934ab8dd67d6f2e963@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 9 Apr 2018 15:46:50 +0200
+Subject: [PATCH] qemu_cgroup: Handle device mapper targets properly
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RHEL-7.6: https://bugzilla.redhat.com/show_bug.cgi?id=1557769
+RHEL-7.5.z: https://bugzilla.redhat.com/show_bug.cgi?id=1564996
+
+Problem with device mapper targets is that there can be several
+other devices 'hidden' behind them. For instance, /dev/dm-1 can
+consist of /dev/sda, /dev/sdb and /dev/sdc. Therefore, when
+setting up devices CGroup and namespaces we have to take this
+into account.
+
+This bug was exposed after Linux kernel was fixed. Initially,
+kernel used different functions for getting block device in
+open() and ioctl(). While CGroup permissions were checked in the
+former case, due to a bug in kernel they were not checked in the
+latter case. This changed with the upstream commit of
+519049afead4f7c3e6446028c41e99fde958cc04 (v4.16-rc5~11^2~4).
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 6dd84f6850ca4379203d1e7b999430ed59041208)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_cgroup.c | 46 +++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 43 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
+index b604edb31c..d88eb7881f 100644
+--- a/src/qemu/qemu_cgroup.c
++++ b/src/qemu/qemu_cgroup.c
+@@ -37,6 +37,7 @@
+ #include "virtypedparam.h"
+ #include "virnuma.h"
+ #include "virsystemd.h"
++#include "virdevmapper.h"
+ 
+ #define VIR_FROM_THIS VIR_FROM_QEMU
+ 
+@@ -60,7 +61,10 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
+ {
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     int perms = VIR_CGROUP_DEVICE_READ;
+-    int ret;
++    char **targetPaths = NULL;
++    size_t i;
++    int rv;
++    int ret = -1;
+ 
+     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
+         return 0;
+@@ -71,12 +75,41 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
+     VIR_DEBUG("Allow path %s, perms: %s",
+               path, virCgroupGetDevicePermsString(perms));
+ 
+-    ret = virCgroupAllowDevicePath(priv->cgroup, path, perms, true);
++    rv = virCgroupAllowDevicePath(priv->cgroup, path, perms, true);
+ 
+     virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path,
+                              virCgroupGetDevicePermsString(perms),
+-                             ret);
++                             rv);
++    if (rv < 0)
++        goto cleanup;
+ 
++    if (rv > 0) {
++        /* @path is neither character device nor block device. */
++        ret = 0;
++        goto cleanup;
++    }
++
++    if (virDevMapperGetTargets(path, &targetPaths) < 0 &&
++        errno != ENOSYS && errno != EBADF) {
++        virReportSystemError(errno,
++                             _("Unable to get devmapper targets for %s"),
++                             path);
++        goto cleanup;
++    }
++
++    for (i = 0; targetPaths && targetPaths[i]; i++) {
++        rv = virCgroupAllowDevicePath(priv->cgroup, targetPaths[i], perms, false);
++
++        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", targetPaths[i],
++                                 virCgroupGetDevicePermsString(perms),
++                                 rv);
++        if (rv < 0)
++            goto cleanup;
++    }
++
++    ret = 0;
++ cleanup:
++    virStringListFree(targetPaths);
+     return ret;
+ }
+ 
+@@ -131,6 +164,13 @@ qemuTeardownImageCgroup(virDomainObjPtr vm,
+     virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path,
+                              virCgroupGetDevicePermsString(perms), ret);
+ 
++    /* If you're looking for a counter part to
++     * qemuSetupImagePathCgroup you're at the right place.
++     * However, we can't just blindly deny all the device mapper
++     * targets of src->path because they might still be used by
++     * another disk in domain. Just like we are not removing
++     * disks from namespace. */
++
+     return ret;
+ }
+ 
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-util-Introduce-virDevMapperGetTargets.patch b/SOURCES/libvirt-util-Introduce-virDevMapperGetTargets.patch
new file mode 100644
index 0000000..0147868
--- /dev/null
+++ b/SOURCES/libvirt-util-Introduce-virDevMapperGetTargets.patch
@@ -0,0 +1,307 @@
+From c66b76761528f6294849cacaa8a99c49967d0070 Mon Sep 17 00:00:00 2001
+Message-Id: <c66b76761528f6294849cacaa8a99c49967d0070@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 9 Apr 2018 15:46:49 +0200
+Subject: [PATCH] util: Introduce virDevMapperGetTargets
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1564996
+
+This helper fetches dependencies for given device mapper target.
+
+At the same time, we need to provide a dummy log function because
+by default libdevmapper prints out error messages to stderr which
+we need to suppress.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit fd9d1e686db64fa9481b9eab4dabafa46713e2cf)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+
+Conflicts: src/util/Makefile.inc.am: src/Makefile split is not backported
+  yet (9cd0bdd1a178a76dbce4)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/Makefile.am          |   1 +
+ src/libvirt_private.syms |   4 +
+ src/util/virdevmapper.c  | 199 +++++++++++++++++++++++++++++++++++++++
+ src/util/virdevmapper.h  |  31 ++++++
+ 4 files changed, 235 insertions(+)
+ create mode 100644 src/util/virdevmapper.c
+ create mode 100644 src/util/virdevmapper.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 6b24a47afe..2130859045 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -111,6 +111,7 @@ UTIL_SOURCES =							\
+ 		util/virconf.c util/virconf.h			\
+ 		util/vircrypto.c util/vircrypto.h		\
+ 		util/virdbus.c util/virdbus.h util/virdbuspriv.h	\
++		util/virdevmapper.c util/virdevmapper.h \
+ 		util/virdnsmasq.c util/virdnsmasq.h		\
+ 		util/virebtables.c util/virebtables.h		\
+ 		util/virendian.h				\
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 15cc83931a..5bacafb462 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1625,6 +1625,10 @@ virDBusMessageUnref;
+ virDBusSetSharedBus;
+ 
+ 
++# util/virdevmapper.h
++virDevMapperGetTargets;
++
++
+ # util/virdnsmasq.h
+ dnsmasqAddDhcpHost;
+ dnsmasqAddHost;
+diff --git a/src/util/virdevmapper.c b/src/util/virdevmapper.c
+new file mode 100644
+index 0000000000..d2c25af003
+--- /dev/null
++++ b/src/util/virdevmapper.c
+@@ -0,0 +1,199 @@
++/*
++ * virdevmapper.c: Functions for handling device mapper
++ *
++ * Copyright (C) 2018 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Authors:
++ *     Michal Privoznik <mprivozn@redhat.com>
++ */
++
++#include <config.h>
++
++#ifdef MAJOR_IN_MKDEV
++# include <sys/mkdev.h>
++#elif MAJOR_IN_SYSMACROS
++# include <sys/sysmacros.h>
++#endif
++
++#ifdef WITH_DEVMAPPER
++# include <libdevmapper.h>
++#endif
++
++#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);
++    return 0;
++}
++
++
++VIR_ONCE_GLOBAL_INIT(virDevMapper)
++
++
++static int
++virDevMapperGetTargetsImpl(const char *path,
++                           char ***devPaths_ret,
++                           unsigned int ttl)
++{
++    struct dm_task *dmt = NULL;
++    struct dm_deps *deps;
++    struct dm_info info;
++    char **devPaths = NULL;
++    char **recursiveDevPaths = NULL;
++    size_t i;
++    int ret = -1;
++
++    *devPaths_ret = NULL;
++
++    if (virDevMapperInitialize() < 0)
++        return ret;
++
++    if (ttl == 0) {
++        errno = ELOOP;
++        return ret;
++    }
++
++    if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
++        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 (!dm_task_run(dmt))
++        goto cleanup;
++
++    if (!dm_task_get_info(dmt, &info))
++        goto cleanup;
++
++    if (!info.exists) {
++        ret = 0;
++        goto cleanup;
++    }
++
++    if (!(deps = dm_task_get_deps(dmt)))
++        goto cleanup;
++
++    if (VIR_ALLOC_N_QUIET(devPaths, deps->count + 1) < 0)
++        goto cleanup;
++
++    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;
++    }
++
++    recursiveDevPaths = NULL;
++    for (i = 0; i < deps->count; i++) {
++        char **tmpPaths;
++
++        if (virDevMapperGetTargetsImpl(devPaths[i], &tmpPaths, ttl - 1) < 0)
++            goto cleanup;
++
++        if (tmpPaths &&
++            virStringListMerge(&recursiveDevPaths, &tmpPaths) < 0) {
++            virStringListFree(tmpPaths);
++            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;
++}
++
++
++/**
++ * virDevMapperGetTargets:
++ * @path: devmapper target
++ * @devPaths: returned string list of devices
++ *
++ * For given @path figure out its targets, and store them in
++ * @devPaths array. Note, @devPaths is a string list so it's NULL
++ * terminated.
++ *
++ * If @path is not a devmapper device, @devPaths is set to NULL and
++ * success is returned.
++ *
++ * 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)
++ */
++int
++virDevMapperGetTargets(const char *path,
++                       char ***devPaths)
++{
++    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);
++}
++
++#else /* ! WITH_DEVMAPPER */
++
++int
++virDevMapperGetTargets(const char *path ATTRIBUTE_UNUSED,
++                       char ***devPaths ATTRIBUTE_UNUSED)
++{
++    errno = ENOSYS;
++    return -1;
++}
++#endif /* ! WITH_DEVMAPPER */
+diff --git a/src/util/virdevmapper.h b/src/util/virdevmapper.h
+new file mode 100644
+index 0000000000..34d6655e77
+--- /dev/null
++++ b/src/util/virdevmapper.h
+@@ -0,0 +1,31 @@
++/*
++ * virdevmapper.h: Functions for handling device mapper
++ *
++ * Copyright (C) 2018 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ * Authors:
++ *     Michal Privoznik <mprivozn@redhat.com>
++ */
++
++#ifndef __VIR_DEVMAPPER_H__
++# define __VIR_DEVMAPPER_H__
++
++int
++virDevMapperGetTargets(const char *path,
++                       char ***devPaths);
++
++#endif /* __VIR_DEVMAPPER_H__ */
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-util-Introduce-virStringListMerge.patch b/SOURCES/libvirt-util-Introduce-virStringListMerge.patch
new file mode 100644
index 0000000..1500fc6
--- /dev/null
+++ b/SOURCES/libvirt-util-Introduce-virStringListMerge.patch
@@ -0,0 +1,100 @@
+From a2798982df8432b5d26f247516ca5a43e0a94c58 Mon Sep 17 00:00:00 2001
+Message-Id: <a2798982df8432b5d26f247516ca5a43e0a94c58@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 9 Apr 2018 15:46:48 +0200
+Subject: [PATCH] util: Introduce virStringListMerge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1564996
+
+For two string lists merge one into the other one.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 72bf14d3456373130cd47157c0062e9125318716)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virstring.c     | 36 ++++++++++++++++++++++++++++++++++++
+ src/util/virstring.h     |  3 +++
+ 3 files changed, 40 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 9c64d0cb97..15cc83931a 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2775,6 +2775,7 @@ virStringListGetFirstWithPrefix;
+ virStringListHasString;
+ virStringListJoin;
+ virStringListLength;
++virStringListMerge;
+ virStringListRemove;
+ virStringMatch;
+ virStringParsePort;
+diff --git a/src/util/virstring.c b/src/util/virstring.c
+index b2ebce27ff..47d9efba25 100644
+--- a/src/util/virstring.c
++++ b/src/util/virstring.c
+@@ -239,6 +239,42 @@ virStringListRemove(char ***strings,
+ }
+ 
+ 
++/**
++ * virStringListMerge:
++ * @dst: a NULL-terminated array of strings to expand
++ * @src: a NULL-terminated array of strings
++ *
++ * Merges @src into @dst. Upon successful return from this
++ * function, @dst is resized to $(dst + src) elements and @src is
++ * freed.
++ *
++ * Returns 0 on success, -1 otherwise.
++ */
++int
++virStringListMerge(char ***dst,
++                   char ***src)
++{
++    size_t dst_len, src_len, i;
++
++    if (!src || !*src)
++        return 0;
++
++    dst_len = virStringListLength((const char **) *dst);
++    src_len = virStringListLength((const char **) *src);
++
++    if (VIR_REALLOC_N(*dst, dst_len + src_len + 1) < 0)
++        return -1;
++
++    for (i = 0; i <= src_len; i++)
++        (*dst)[i + dst_len] = (*src)[i];
++
++    /* Don't call virStringListFree() as it would free strings in
++     * @src. */
++    VIR_FREE(*src);
++    return 0;
++}
++
++
+ /**
+  * virStringListCopy:
+  * @dst: where to store the copy of @strings
+diff --git a/src/util/virstring.h b/src/util/virstring.h
+index cfd91be314..1fd43f98b7 100644
+--- a/src/util/virstring.h
++++ b/src/util/virstring.h
+@@ -46,6 +46,9 @@ char **virStringListAdd(const char **strings,
+ void virStringListRemove(char ***strings,
+                          const char *item);
+ 
++int virStringListMerge(char ***dst,
++                       char ***src);
++
+ int virStringListCopy(char ***dst,
+                       const char **src);
+ 
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-vmx-allocate-space-for-network-interfaces-if-needed.patch b/SOURCES/libvirt-vmx-allocate-space-for-network-interfaces-if-needed.patch
new file mode 100644
index 0000000..4b325cb
--- /dev/null
+++ b/SOURCES/libvirt-vmx-allocate-space-for-network-interfaces-if-needed.patch
@@ -0,0 +1,58 @@
+From 84131c477c2c5b512723e96b59528a93ed7d41c4 Mon Sep 17 00:00:00 2001
+Message-Id: <84131c477c2c5b512723e96b59528a93ed7d41c4@dist-git>
+From: Pino Toscano <ptoscano@redhat.com>
+Date: Thu, 12 Apr 2018 17:26:19 +0200
+Subject: [PATCH] vmx: allocate space for network interfaces if needed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Dynamically grow the array of network interfaces for each interface
+read, instead of using a single array of size 4.  This way, in the
+future it will be easier to not limit the number of network interfaces
+(which this patch still does not change).
+
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+(cherry picked from commit 6d394989fda53b53f0a21522bebe44ea01a40de9)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1566524
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/vmx/vmx.c | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
+index 85bf195cd7..3433f39d5c 100644
+--- a/src/vmx/vmx.c
++++ b/src/vmx/vmx.c
+@@ -1751,19 +1751,16 @@ virVMXParseConfig(virVMXContext *ctx,
+     }
+ 
+     /* def:nets */
+-    if (VIR_ALLOC_N(def->nets, 4) < 0)
+-        goto cleanup;
+-
+-    def->nnets = 0;
+-
+     for (controller = 0; controller < 4; ++controller) {
+-        if (virVMXParseEthernet(conf, controller,
+-                                &def->nets[def->nnets]) < 0) {
++        virDomainNetDefPtr net = NULL;
++        if (virVMXParseEthernet(conf, controller, &net) < 0)
+             goto cleanup;
+-        }
+ 
+-        if (def->nets[def->nnets] != NULL)
+-            ++def->nnets;
++        if (!net)
++            continue;
++
++        if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0)
++            goto cleanup;
+     }
+ 
+     /* def:inputs */
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-vmx-check-for-present-enabled-devices-earlier.patch b/SOURCES/libvirt-vmx-check-for-present-enabled-devices-earlier.patch
new file mode 100644
index 0000000..2420a3d
--- /dev/null
+++ b/SOURCES/libvirt-vmx-check-for-present-enabled-devices-earlier.patch
@@ -0,0 +1,237 @@
+From 5ca21a5c83e1c712d4d90f1981a23117ec8010f9 Mon Sep 17 00:00:00 2001
+Message-Id: <5ca21a5c83e1c712d4d90f1981a23117ec8010f9@dist-git>
+From: Pino Toscano <ptoscano@redhat.com>
+Date: Thu, 12 Apr 2018 17:26:18 +0200
+Subject: [PATCH] vmx: check for present/enabled devices earlier
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When parsing filesystems, network interfaces, serial ports, and
+parallel ports, check earlier whether they are present/enabled, delaying
+the allocation of the objects.
+
+This is mostly a small optimization, with no behaviour change.
+
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+(cherry picked from commit 5d5430e1fc6f853f79da39fbef08e97bebffc8eb)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1566524
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/vmx/vmx.c | 92 +++++++++++++++++----------------------------------
+ 1 file changed, 30 insertions(+), 62 deletions(-)
+
+diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
+index 622f22f037..85bf195cd7 100644
+--- a/src/vmx/vmx.c
++++ b/src/vmx/vmx.c
+@@ -2439,11 +2439,6 @@ int virVMXParseFileSystem(virConfPtr conf, int number, virDomainFSDefPtr *def)
+         return -1;
+     }
+ 
+-    if (!(*def = virDomainFSDefNew()))
+-        return -1;
+-
+-    (*def)->type = VIR_DOMAIN_FS_TYPE_MOUNT;
+-
+     snprintf(prefix, sizeof(prefix), "sharedFolder%d", number);
+ 
+     VMX_BUILD_NAME(present);
+@@ -2454,14 +2449,19 @@ int virVMXParseFileSystem(virConfPtr conf, int number, virDomainFSDefPtr *def)
+ 
+     /* vmx:present */
+     if (virVMXGetConfigBoolean(conf, present_name, &present, false, true) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     /* vmx:enabled */
+     if (virVMXGetConfigBoolean(conf, enabled_name, &enabled, false, true) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (!(present && enabled))
+-        goto ignore;
++        return 0;
++
++    if (!(*def = virDomainFSDefNew()))
++        return -1;
++
++    (*def)->type = VIR_DOMAIN_FS_TYPE_MOUNT;
+ 
+     /* vmx:hostPath */
+     if (virVMXGetConfigString(conf, hostPath_name, &hostPath, false) < 0)
+@@ -2497,14 +2497,6 @@ int virVMXParseFileSystem(virConfPtr conf, int number, virDomainFSDefPtr *def)
+     VIR_FREE(guestName);
+ 
+     return result;
+-
+- ignore:
+-    virDomainFSDefFree(*def);
+-    *def = NULL;
+-
+-    result = 0;
+-
+-    goto cleanup;
+ }
+ 
+ 
+@@ -2557,9 +2549,6 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
+         return -1;
+     }
+ 
+-    if (VIR_ALLOC(*def) < 0)
+-        return -1;
+-
+     snprintf(prefix, sizeof(prefix), "ethernet%d", controller);
+ 
+     VMX_BUILD_NAME(present);
+@@ -2575,17 +2564,20 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
+ 
+     /* vmx:present */
+     if (virVMXGetConfigBoolean(conf, present_name, &present, false, true) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     /* vmx:startConnected */
+     if (virVMXGetConfigBoolean(conf, startConnected_name, &startConnected,
+                                true, true) < 0) {
+-        goto cleanup;
++        return -1;
+     }
+ 
+     /* FIXME: Need to distiguish between active and inactive domains here */
+     if (! present/* && ! startConnected*/)
+-        goto ignore;
++        return 0;
++
++    if (VIR_ALLOC(*def) < 0)
++        return -1;
+ 
+     /* vmx:connectionType -> def:type */
+     if (virVMXGetConfigString(conf, connectionType_name, &connectionType,
+@@ -2726,14 +2718,6 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
+     VIR_FREE(vnet);
+ 
+     return result;
+-
+- ignore:
+-    virDomainNetDefFree(*def);
+-    *def = NULL;
+-
+-    result = 0;
+-
+-    goto cleanup;
+ }
+ 
+ 
+@@ -2773,11 +2757,6 @@ virVMXParseSerial(virVMXContext *ctx, virConfPtr conf, int port,
+         return -1;
+     }
+ 
+-    if (!(*def = virDomainChrDefNew(NULL)))
+-        return -1;
+-
+-    (*def)->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
+-
+     snprintf(prefix, sizeof(prefix), "serial%d", port);
+ 
+     VMX_BUILD_NAME(present);
+@@ -2788,17 +2767,22 @@ virVMXParseSerial(virVMXContext *ctx, virConfPtr conf, int port,
+ 
+     /* vmx:present */
+     if (virVMXGetConfigBoolean(conf, present_name, &present, false, true) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     /* vmx:startConnected */
+     if (virVMXGetConfigBoolean(conf, startConnected_name, &startConnected,
+                                true, true) < 0) {
+-        goto cleanup;
++        return -1;
+     }
+ 
+     /* FIXME: Need to distiguish between active and inactive domains here */
+     if (! present/* && ! startConnected*/)
+-        goto ignore;
++        return 0;
++
++    if (!(*def = virDomainChrDefNew(NULL)))
++        return -1;
++
++    (*def)->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
+ 
+     /* vmx:fileType -> def:type */
+     if (virVMXGetConfigString(conf, fileType_name, &fileType, true) < 0)
+@@ -2919,14 +2903,6 @@ virVMXParseSerial(virVMXContext *ctx, virConfPtr conf, int port,
+     virURIFree(parsedUri);
+ 
+     return result;
+-
+- ignore:
+-    virDomainChrDefFree(*def);
+-    *def = NULL;
+-
+-    result = 0;
+-
+-    goto cleanup;
+ }
+ 
+ 
+@@ -2961,11 +2937,6 @@ virVMXParseParallel(virVMXContext *ctx, virConfPtr conf, int port,
+         return -1;
+     }
+ 
+-    if (!(*def = virDomainChrDefNew(NULL)))
+-        return -1;
+-
+-    (*def)->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
+-
+     snprintf(prefix, sizeof(prefix), "parallel%d", port);
+ 
+     VMX_BUILD_NAME(present);
+@@ -2975,17 +2946,22 @@ virVMXParseParallel(virVMXContext *ctx, virConfPtr conf, int port,
+ 
+     /* vmx:present */
+     if (virVMXGetConfigBoolean(conf, present_name, &present, false, true) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     /* vmx:startConnected */
+     if (virVMXGetConfigBoolean(conf, startConnected_name, &startConnected,
+                                true, true) < 0) {
+-        goto cleanup;
++        return -1;
+     }
+ 
+     /* FIXME: Need to distiguish between active and inactive domains here */
+     if (! present/* && ! startConnected*/)
+-        goto ignore;
++        return 0;
++
++    if (!(*def = virDomainChrDefNew(NULL)))
++        return -1;
++
++    (*def)->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
+ 
+     /* vmx:fileType -> def:type */
+     if (virVMXGetConfigString(conf, fileType_name, &fileType, false) < 0)
+@@ -3029,14 +3005,6 @@ virVMXParseParallel(virVMXContext *ctx, virConfPtr conf, int port,
+     VIR_FREE(fileName);
+ 
+     return result;
+-
+- ignore:
+-    virDomainChrDefFree(*def);
+-    *def = NULL;
+-
+-    result = 0;
+-
+-    goto cleanup;
+ }
+ 
+ 
+-- 
+2.17.0
+
diff --git a/SOURCES/libvirt-vmx-convert-any-amount-of-NICs.patch b/SOURCES/libvirt-vmx-convert-any-amount-of-NICs.patch
new file mode 100644
index 0000000..5669eea
--- /dev/null
+++ b/SOURCES/libvirt-vmx-convert-any-amount-of-NICs.patch
@@ -0,0 +1,394 @@
+From 00b89ea9a9e0713ed663c4426f1f4f2e44d846b6 Mon Sep 17 00:00:00 2001
+Message-Id: <00b89ea9a9e0713ed663c4426f1f4f2e44d846b6@dist-git>
+From: Pino Toscano <ptoscano@redhat.com>
+Date: Thu, 12 Apr 2018 17:26:21 +0200
+Subject: [PATCH] vmx: convert any amount of NICs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Scan the parsed VMX file, and gather the biggest index of the network
+interfaces there: this way, it is possible to parse all the available
+network interfaces, instead of just 4 maximum.
+
+Add the VMX file attached to RHBZ#1560917 as testcase esx-in-the-wild-8.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1560917
+
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+(cherry picked from commit 5c744a2d445c01fdb9d83a9c3857ba6c0091d834)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1566524
+
+Signed-off-by: Pino Toscano <ptoscano@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/vmx/vmx.c                                 |  43 ++++-
+ .../vmx2xmldata/vmx2xml-esx-in-the-wild-8.vmx | 163 ++++++++++++++++++
+ .../vmx2xmldata/vmx2xml-esx-in-the-wild-8.xml |  89 ++++++++++
+ tests/vmx2xmltest.c                           |   1 +
+ 4 files changed, 288 insertions(+), 8 deletions(-)
+ create mode 100644 tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.vmx
+ create mode 100644 tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.xml
+
+diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
+index 3433f39d5c..2afb2e9b34 100644
+--- a/src/vmx/vmx.c
++++ b/src/vmx/vmx.c
+@@ -1286,6 +1286,36 @@ virVMXGatherSCSIControllers(virVMXContext *ctx, virDomainDefPtr def,
+     return result;
+ }
+ 
++struct virVMXConfigScanResults {
++    int networks_max_index;
++};
++
++static int
++virVMXConfigScanResultsCollector(const char* name,
++                                 virConfValuePtr value ATTRIBUTE_UNUSED,
++                                 void *opaque)
++{
++    struct virVMXConfigScanResults *results = opaque;
++
++    if (STRCASEPREFIX(name, "ethernet")) {
++        unsigned int idx;
++        char *p;
++
++        if (virStrToLong_uip(name + 8, &p, 10, &idx) < 0 ||
++            *p != '.') {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("failed to parse the index of the VMX key '%s'"),
++                           name);
++            return -1;
++        }
++
++        if ((int) idx > results->networks_max_index)
++            results->networks_max_index = (int) idx;
++    }
++
++    return 0;
++}
++
+ 
+ 
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+@@ -1322,6 +1352,7 @@ virVMXParseConfig(virVMXContext *ctx,
+     bool hgfs_disabled = true;
+     long long sharedFolder_maxNum = 0;
+     int cpumasklen;
++    struct virVMXConfigScanResults results = { -1 };
+ 
+     if (ctx->parseFileName == NULL) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+@@ -1357,6 +1388,9 @@ virVMXParseConfig(virVMXContext *ctx,
+             goto cleanup;
+     }
+ 
++    if (virConfWalk(conf, virVMXConfigScanResultsCollector, &results) < 0)
++        goto cleanup;
++
+     /* Allocate domain def */
+     if (!(def = virDomainDefNew()))
+         goto cleanup;
+@@ -1751,7 +1785,7 @@ virVMXParseConfig(virVMXContext *ctx,
+     }
+ 
+     /* def:nets */
+-    for (controller = 0; controller < 4; ++controller) {
++    for (controller = 0; controller <= results.networks_max_index; ++controller) {
+         virDomainNetDefPtr net = NULL;
+         if (virVMXParseEthernet(conf, controller, &net) < 0)
+             goto cleanup;
+@@ -2539,13 +2573,6 @@ virVMXParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
+         return -1;
+     }
+ 
+-    if (controller < 0 || controller > 3) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Ethernet controller index %d out of [0..3] range"),
+-                       controller);
+-        return -1;
+-    }
+-
+     snprintf(prefix, sizeof(prefix), "ethernet%d", controller);
+ 
+     VMX_BUILD_NAME(present);
+diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.vmx b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.vmx
+new file mode 100644
+index 0000000000..1e3dbf23ce
+--- /dev/null
++++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.vmx
+@@ -0,0 +1,163 @@
++.encoding = "UTF-8"
++config.version = "8"
++virtualHW.version = "11"
++vmci0.present = "TRUE"
++svga.vramSize = "8388608"
++memSize = "2048"
++sched.cpu.units = "mhz"
++tools.upgrade.policy = "manual"
++scsi0.virtualDev = "pvscsi"
++scsi0.present = "TRUE"
++sata0.present = "TRUE"
++sata0:0.deviceType = "cdrom-image"
++sata0:0.fileName = "/vmfs/volumes/692eb778-2d4937fe/CentOS-4.7.ServerCD-x86_64.iso"
++sata0:0.present = "TRUE"
++scsi0:0.deviceType = "scsi-hardDisk"
++scsi0:0.fileName = "RHEL7_6.vmdk"
++sched.scsi0:0.shares = "normal"
++scsi0:0.present = "TRUE"
++floppy0.startConnected = "FALSE"
++floppy0.clientDevice = "TRUE"
++floppy0.fileName = "vmware-null-remote-floppy"
++ethernet0.virtualDev = "vmxnet3"
++ethernet0.networkName = "VM Network"
++ethernet0.addressType = "static"
++ethernet0.address = "00:1a:4a:16:01:55"
++ethernet0.present = "TRUE"
++displayName = "RHEL7_10_NICs"
++guestOS = "rhel7-64"
++toolScripts.afterPowerOn = "TRUE"
++toolScripts.afterResume = "TRUE"
++toolScripts.beforeSuspend = "TRUE"
++toolScripts.beforePowerOff = "TRUE"
++tools.syncTime = "FALSE"
++messageBus.tunnelEnabled = "FALSE"
++uuid.bios = "42 35 94 20 99 dc 42 61-52 64 ba 58 dd ae 20 e4"
++vc.uuid = "50 35 1d e6 7d 56 29 ab-9d 72 c7 f9 ea 3f cf d0"
++sched.cpu.latencySensitivity = "normal"
++tools.guest.desktop.autolock = "FALSE"
++nvram = "RHEL7_6.nvram"
++pciBridge0.present = "TRUE"
++svga.present = "TRUE"
++pciBridge4.present = "TRUE"
++pciBridge4.virtualDev = "pcieRootPort"
++pciBridge4.functions = "8"
++pciBridge5.present = "TRUE"
++pciBridge5.virtualDev = "pcieRootPort"
++pciBridge5.functions = "8"
++pciBridge6.present = "TRUE"
++pciBridge6.virtualDev = "pcieRootPort"
++pciBridge6.functions = "8"
++pciBridge7.present = "TRUE"
++pciBridge7.virtualDev = "pcieRootPort"
++pciBridge7.functions = "8"
++hpet0.present = "true"
++sched.scsi0:0.throughputCap = "off"
++ethernet0.uptCompatibility = "TRUE"
++ethernet0.pciSlotNumber = "192"
++monitor.phys_bits_used = "42"
++pciBridge0.pciSlotNumber = "17"
++pciBridge4.pciSlotNumber = "21"
++pciBridge5.pciSlotNumber = "22"
++pciBridge6.pciSlotNumber = "23"
++pciBridge7.pciSlotNumber = "24"
++replay.supported = "false"
++sata0.pciSlotNumber = "33"
++scsi0.pciSlotNumber = "160"
++scsi0.sasWWID = "50 05 05 60 99 dc 42 60"
++softPowerOff = "FALSE"
++virtualHW.productCompatibility = "hosted"
++vmci0.pciSlotNumber = "32"
++vmotion.checkpointFBSize = "8388608"
++vmotion.checkpointSVGAPrimarySize = "8388608"
++tools.remindInstall = "FALSE"
++toolsInstallManager.lastInstallError = "0"
++toolsInstallManager.updateCounter = "1"
++migrate.hostlog = "RHEL7_6-2a23b979.hlog"
++sched.cpu.min = "0"
++sched.cpu.shares = "normal"
++sched.mem.min = "0"
++sched.mem.minSize = "0"
++sched.mem.shares = "normal"
++scsi0:1.deviceType = "scsi-hardDisk"
++scsi0:1.fileName = "RHEL7_6_1.vmdk"
++scsi0:1.mode = "independent-nonpersistent"
++sched.scsi0:1.shares = "normal"
++sched.scsi0:1.throughputCap = "off"
++scsi0:1.present = "TRUE"
++scsi0:2.deviceType = "scsi-hardDisk"
++scsi0:2.fileName = "/vmfs/volumes/5669422e-699d77db-c144-00e0815e303e/block4/block4.vmdk"
++sched.scsi0:2.shares = "normal"
++sched.scsi0:2.throughputCap = "off"
++scsi0:2.present = "TRUE"
++numvcpus = "8"
++cpuid.coresPerSocket = "2"
++sched.swap.derivedName = "/vmfs/volumes/29dcc8ec-e8d62d3b-0000-000000000000/RHEL7_6/RHEL7_6-05efff7d.vswp"
++uuid.location = "56 4d d9 db b7 4e df ce-58 6a 77 56 82 53 aa 18"
++replay.filename = ""
++scsi0:2.redo = ""
++scsi0:1.redo = ""
++scsi0:0.redo = ""
++vmci0.id = "-575790876"
++cleanShutdown = "TRUE"
++ethernet1.virtualDev = "e1000"
++ethernet1.networkName = "VM Network"
++ethernet1.addressType = "vpx"
++ethernet1.generatedAddress = "00:1a:4a:16:21:85"
++ethernet1.present = "TRUE"
++ethernet2.virtualDev = "e1000e"
++ethernet2.networkName = "VM Network"
++ethernet2.addressType = "vpx"
++ethernet2.generatedAddress = "00:1a:4a:16:21:82"
++ethernet2.present = "TRUE"
++ethernet3.virtualDev = "vmxnet3"
++ethernet3.networkName = "VM Network"
++ethernet3.addressType = "vpx"
++ethernet3.generatedAddress = "00:1a:4a:16:21:69"
++ethernet3.uptCompatibility = "TRUE"
++ethernet3.present = "TRUE"
++ethernet4.virtualDev = "vmxnet3"
++ethernet4.networkName = "VM Network"
++ethernet4.addressType = "vpx"
++ethernet4.generatedAddress = "00:1a:4a:16:21:80"
++ethernet4.uptCompatibility = "TRUE"
++ethernet4.present = "TRUE"
++ethernet5.virtualDev = "vmxnet3"
++ethernet5.networkName = "VM Network"
++ethernet5.addressType = "vpx"
++ethernet5.generatedAddress = "00:1a:4a:16:21:a3"
++ethernet5.uptCompatibility = "TRUE"
++ethernet5.present = "TRUE"
++ethernet6.virtualDev = "vmxnet3"
++ethernet6.networkName = "VM Network"
++ethernet6.addressType = "vpx"
++ethernet6.generatedAddress = "00:1a:4a:16:21:a8"
++ethernet6.uptCompatibility = "TRUE"
++ethernet6.present = "TRUE"
++ethernet7.virtualDev = "vmxnet3"
++ethernet7.networkName = "VM Network"
++ethernet7.addressType = "vpx"
++ethernet7.generatedAddress = "00:1a:4a:16:21:a9"
++ethernet7.uptCompatibility = "TRUE"
++ethernet7.present = "TRUE"
++ethernet8.virtualDev = "vmxnet3"
++ethernet8.networkName = "VM Network"
++ethernet8.addressType = "vpx"
++ethernet8.generatedAddress = "00:1a:4a:16:21:78"
++ethernet8.uptCompatibility = "TRUE"
++ethernet8.present = "TRUE"
++ethernet9.virtualDev = "vmxnet3"
++ethernet9.networkName = "VM Network"
++ethernet9.addressType = "vpx"
++ethernet9.generatedAddress = "00:1a:4a:16:21:81"
++ethernet9.uptCompatibility = "TRUE"
++ethernet9.present = "TRUE"
++ethernet1.pciSlotNumber = "34"
++ethernet2.pciSlotNumber = "224"
++ethernet3.pciSlotNumber = "256"
++ethernet4.pciSlotNumber = "1184"
++ethernet5.pciSlotNumber = "1216"
++ethernet6.pciSlotNumber = "1248"
++ethernet7.pciSlotNumber = "1280"
++ethernet8.pciSlotNumber = "2208"
++ethernet9.pciSlotNumber = "2240"
+diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.xml
+new file mode 100644
+index 0000000000..c85ccf3649
+--- /dev/null
++++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-8.xml
+@@ -0,0 +1,89 @@
++<domain type='vmware'>
++  <name>RHEL7_10_NICs</name>
++  <uuid>42359420-99dc-4261-5264-ba58ddae20e4</uuid>
++  <memory unit='KiB'>2097152</memory>
++  <currentMemory unit='KiB'>2097152</currentMemory>
++  <vcpu placement='static'>8</vcpu>
++  <cputune>
++    <shares>8000</shares>
++  </cputune>
++  <os>
++    <type arch='x86_64'>hvm</type>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <disk type='file' device='disk'>
++      <source file='[datastore] directory/RHEL7_6.vmdk'/>
++      <target dev='sda' bus='scsi'/>
++      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
++    </disk>
++    <disk type='file' device='disk'>
++      <source file='[datastore] directory/RHEL7_6_1.vmdk'/>
++      <target dev='sdb' bus='scsi'/>
++      <transient/>
++      <address type='drive' controller='0' bus='0' target='0' unit='1'/>
++    </disk>
++    <disk type='file' device='disk'>
++      <source file='[5669422e-699d77db-c144-00e0815e303e] block4/block4.vmdk'/>
++      <target dev='sdc' bus='scsi'/>
++      <address type='drive' controller='0' bus='0' target='0' unit='2'/>
++    </disk>
++    <controller type='scsi' index='0' model='vmpvscsi'/>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:01:55'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:85'/>
++      <source bridge='VM Network'/>
++      <model type='e1000'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:82'/>
++      <source bridge='VM Network'/>
++      <model type='e1000e'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:69'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:80'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:a3'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:a8'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:a9'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:78'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <interface type='bridge'>
++      <mac address='00:1a:4a:16:21:81'/>
++      <source bridge='VM Network'/>
++      <model type='vmxnet3'/>
++    </interface>
++    <video>
++      <model type='vmvga' vram='8192' primary='yes'/>
++    </video>
++  </devices>
++</domain>
+diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
+index 00385dfa71..fd0d9fbea4 100644
+--- a/tests/vmx2xmltest.c
++++ b/tests/vmx2xmltest.c
+@@ -268,6 +268,7 @@ mymain(void)
+     DO_TEST("esx-in-the-wild-5", "esx-in-the-wild-5");
+     DO_TEST("esx-in-the-wild-6", "esx-in-the-wild-6");
+     DO_TEST("esx-in-the-wild-7", "esx-in-the-wild-7");
++    DO_TEST("esx-in-the-wild-8", "esx-in-the-wild-8");
+ 
+     DO_TEST("gsx-in-the-wild-1", "gsx-in-the-wild-1");
+     DO_TEST("gsx-in-the-wild-2", "gsx-in-the-wild-2");
+-- 
+2.17.0
+
diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec
index ebe7b59..12479c1 100644
--- a/SPECS/libvirt.spec
+++ b/SPECS/libvirt.spec
@@ -240,7 +240,7 @@
 Summary: Library providing a simple virtualization API
 Name: libvirt
 Version: 3.9.0
-Release: 14%{?dist}.2%{?extra_release}
+Release: 14%{?dist}.4%{?extra_release}
 License: LGPLv2+
 Group: Development/Libraries
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
@@ -441,6 +441,21 @@ Patch187: libvirt-conf-move-generated-member-from-virMacAddr-to-virDomainNetDef.
 Patch188: libvirt-virDomainDeviceValidateAliasForHotplug-Use-correct-domain-defintion.patch
 Patch189: libvirt-conf-Check-for-user-aliases-duplicates-only.patch
 Patch190: libvirt-virDomainDeviceDefValidateAliasesIterator-Ignore-some-hostdevs.patch
+Patch191: libvirt-qemu_cgroup-Fix-rc-argument-on-virDomainAuditCgroupPath-calls.patch
+Patch192: libvirt-util-Introduce-virStringListMerge.patch
+Patch193: libvirt-util-Introduce-virDevMapperGetTargets.patch
+Patch194: libvirt-qemu_cgroup-Handle-device-mapper-targets-properly.patch
+Patch195: libvirt-lxc-Drop-useless-check-in-live-device-update.patch
+Patch196: libvirt-Pass-oldDev-to-virDomainDefCompatibleDevice-on-device-update.patch
+Patch197: libvirt-qemu-Fix-updating-device-with-boot-order.patch
+Patch198: libvirt-conf-Fix-crash-in-virDomainDefCompatibleDevice.patch
+Patch199: libvirt-vmx-check-for-present-enabled-devices-earlier.patch
+Patch200: libvirt-vmx-allocate-space-for-network-interfaces-if-needed.patch
+Patch201: libvirt-internal-add-STRCASEPREFIX.patch
+Patch202: libvirt-vmx-convert-any-amount-of-NICs.patch
+Patch203: libvirt-qemu-Use-dynamic-buffer-for-storing-PTY-aliases.patch
+Patch204: libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-monitor-CVE-2018-5748.patch
+Patch205: libvirt-qemu-avoid-denial-of-service-reading-from-QEMU-guest-agent-CVE-2018-1064.patch
 
 Requires: libvirt-daemon = %{version}-%{release}
 Requires: libvirt-daemon-config-network = %{version}-%{release}
@@ -2354,6 +2369,25 @@ exit 0
 
 
 %changelog
+* Fri Apr 13 2018 Jiri Denemark <jdenemar@redhat.com> - 3.9.0-14.el7_5.4
+- lxc: Drop useless check in live device update (rhbz#1557922)
+- Pass oldDev to virDomainDefCompatibleDevice on device update (rhbz#1557922)
+- qemu: Fix updating device with boot order (rhbz#1557922)
+- conf: Fix crash in virDomainDefCompatibleDevice (rhbz#1557922)
+- vmx: check for present/enabled devices earlier (rhbz#1566524)
+- vmx: allocate space for network interfaces if needed (rhbz#1566524)
+- internal: add STRCASEPREFIX (rhbz#1566524)
+- vmx: convert any amount of NICs (rhbz#1566524)
+- qemu: Use dynamic buffer for storing PTY aliases (rhbz#1566525)
+- qemu: avoid denial of service reading from QEMU monitor (CVE-2018-5748) (CVE-2018-5748)
+- qemu: avoid denial of service reading from QEMU guest agent (CVE-2018-1064) (CVE-2018-1064)
+
+* Fri Apr 13 2018 Jiri Denemark <jdenemar@redhat.com> - 3.9.0-14.el7_5.3
+- qemu_cgroup: Fix 'rc' argument on virDomainAuditCgroupPath() calls (rhbz#1564996)
+- util: Introduce virStringListMerge (rhbz#1564996)
+- util: Introduce virDevMapperGetTargets (rhbz#1564996)
+- qemu_cgroup: Handle device mapper targets properly (rhbz#1564996)
+
 * Tue Mar 20 2018 Jiri Denemark <jdenemar@redhat.com> - 3.9.0-14.el7_5.2
 - virDomainDeviceDefValidateAliasesIterator: Ignore some hostdevs (rhbz#1558655)