From e6dfe8de0c79c6e33f32d28ad693090959172fa6 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 14 2018 13:03:08 +0000 Subject: import libvirt-3.9.0-14.el7_5.4 --- 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 +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 +(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 +Reviewed-by: Ján Tomko +--- + 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: +From: John Ferlan +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 +(cherry picked from commit 5535856f0e31aa6abf4cda11b5c53c0f164680f0) + +https://bugzilla.redhat.com/show_bug.cgi?id=1557922 + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +--- + 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: +From: Pino Toscano +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 +(cherry picked from commit e508e04b108709af0ca2c4d6728440b0edc3cc4b) + +https: //bugzilla.redhat.com/show_bug.cgi?id=1566524 +Signed-off-by: Pino Toscano +Reviewed-by: Ján Tomko +--- + 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 +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 +(cherry picked from commit e3497f3fc895c427ce35188f3ddb2bb47a853be9) + +https://bugzilla.redhat.com/show_bug.cgi?id=1557922 + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +--- + 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: +From: Jiri Denemark +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 +element to an inactive domain with global 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 +(cherry picked from commit edae027cfe02be4863dcef1e7f0ea0564766e312) + +https://bugzilla.redhat.com/show_bug.cgi?id=1557922 + +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +--- + 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: +From: Michal Privoznik +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 +(cherry picked from commit c4c32cb300beba41ecbca3ee4884c65630bde861) +Signed-off-by: Michal Privoznik +Reviewed-by: Ján Tomko +Reviewed-by: Erik Skultety +--- + 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: +From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= +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é +(cherry picked from commit fbf31e1a4cd19d6f6e33e0937a009775cd7d9513) +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +--- + 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" +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 +(cherry picked from commit bc251ea91bcfddd2622fce6bce701a438b2e7276) +Signed-off-by: Jiri Denemark +Reviewed-by: Ján Tomko +--- + 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: +From: Eduardo Habkost +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 +Signed-off-by: Michal Privoznik +(cherry picked from commit 9a22251bbe6a4ff8dab90da53a1c0df82d8d29fc) +Signed-off-by: Michal Privoznik +Reviewed-by: Andrea Bolognani +Reviewed-by: Ján Tomko +--- + 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 +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 +(cherry picked from commit 6dd84f6850ca4379203d1e7b999430ed59041208) +Signed-off-by: Michal Privoznik +Reviewed-by: Andrea Bolognani +Reviewed-by: Ján Tomko +--- + 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: +From: Michal Privoznik +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 +(cherry picked from commit fd9d1e686db64fa9481b9eab4dabafa46713e2cf) +Signed-off-by: Michal Privoznik + +Conflicts: src/util/Makefile.inc.am: src/Makefile split is not backported + yet (9cd0bdd1a178a76dbce4) +Signed-off-by: Michal Privoznik +Reviewed-by: Andrea Bolognani +Reviewed-by: Ján Tomko +--- + 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 ++ * . ++ * ++ * Authors: ++ * Michal Privoznik ++ */ ++ ++#include ++ ++#ifdef MAJOR_IN_MKDEV ++# include ++#elif MAJOR_IN_SYSMACROS ++# include ++#endif ++ ++#ifdef WITH_DEVMAPPER ++# include ++#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 ++ * . ++ * ++ * Authors: ++ * Michal Privoznik ++ */ ++ ++#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: +From: Michal Privoznik +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 +(cherry picked from commit 72bf14d3456373130cd47157c0062e9125318716) +Signed-off-by: Michal Privoznik +Reviewed-by: Andrea Bolognani +Reviewed-by: Ján Tomko +--- + 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 +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 +(cherry picked from commit 6d394989fda53b53f0a21522bebe44ea01a40de9) + +https: //bugzilla.redhat.com/show_bug.cgi?id=1566524 +Signed-off-by: Pino Toscano +Reviewed-by: Ján Tomko +--- + 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 +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 +(cherry picked from commit 5d5430e1fc6f853f79da39fbef08e97bebffc8eb) + +https: //bugzilla.redhat.com/show_bug.cgi?id=1566524 +Signed-off-by: Pino Toscano +Reviewed-by: Ján Tomko +--- + 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 +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 +(cherry picked from commit 5c744a2d445c01fdb9d83a9c3857ba6c0091d834) + +https://bugzilla.redhat.com/show_bug.cgi?id=1566524 + +Signed-off-by: Pino Toscano +Reviewed-by: Ján Tomko +--- + 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 @@ ++ ++ RHEL7_10_NICs ++ 42359420-99dc-4261-5264-ba58ddae20e4 ++ 2097152 ++ 2097152 ++ 8 ++ ++ 8000 ++ ++ ++ hvm ++ ++ ++ destroy ++ restart ++ destroy ++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++
++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +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 - 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 - 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 - 3.9.0-14.el7_5.2 - virDomainDeviceDefValidateAliasesIterator: Ignore some hostdevs (rhbz#1558655)