From 0a26adabe1e85f6f17d14e63ab98091fde99cb7b35fdd74b8f40a099ad6899d4 Mon Sep 17 00:00:00 2001 From: James Fehlig Date: Tue, 13 Aug 2013 16:50:35 +0000 Subject: [PATCH] - Fix memory corruption in legacy Xen driver 0e671a16-CVE-2013-4239.patch bnc#834598 - Upstream patches to fix dumpxml in legacy Xen driver 9d0557b9-legacy-xen-double-free.patch, d7a45bf2-legacy-xen-dumpxml.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=294 --- 0e671a16-CVE-2013-4239.patch | 60 +++++++ 9d0557b9-legacy-xen-double-free.patch | 24 +++ d7a45bf2-legacy-xen-dumpxml.patch | 238 ++++++++++++++++++++++++++ fix-pci-attach-xen-driver.patch | 4 +- libvirt.changes | 10 ++ libvirt.spec | 6 + libvirtd-init-script.patch | 6 +- xen-name-for-devid.patch | 8 +- 8 files changed, 347 insertions(+), 9 deletions(-) create mode 100644 0e671a16-CVE-2013-4239.patch create mode 100644 9d0557b9-legacy-xen-double-free.patch create mode 100644 d7a45bf2-legacy-xen-dumpxml.patch diff --git a/0e671a16-CVE-2013-4239.patch b/0e671a16-CVE-2013-4239.patch new file mode 100644 index 0000000..e00f799 --- /dev/null +++ b/0e671a16-CVE-2013-4239.patch @@ -0,0 +1,60 @@ +commit 0e671a1646df543eab683b38f6644f70d12fbee1 +Author: Jim Fehlig +Date: Mon Aug 5 10:27:23 2013 -0600 + + xen: fix memory corruption in legacy driver + + Commit 632180d1 introduced memory corruption in xenDaemonListDefinedDomains + by starting to populate the names array at index -1, causing all sorts + of havoc in libvirtd such as aborts like the following + + *** Error in `/usr/sbin/libvirtd': double free or corruption (out): 0x00007fffe00ccf20 *** + ======= Backtrace: ========= + /lib64/libc.so.6(+0x7abf6)[0x7ffff3fa0bf6] + /lib64/libc.so.6(+0x7b973)[0x7ffff3fa1973] + /lib64/libc.so.6(xdr_array+0xde)[0x7ffff403cbae] + /usr/sbin/libvirtd(+0x50251)[0x5555555a4251] + /lib64/libc.so.6(xdr_free+0x15)[0x7ffff403ccd5] + /usr/lib64/libvirt.so.0(+0x1fad34)[0x7ffff76b1d34] + /usr/lib64/libvirt.so.0(virNetServerProgramDispatch+0x1fc)[0x7ffff76b16f1] + /usr/lib64/libvirt.so.0(+0x1f214a)[0x7ffff76a914a] + /usr/lib64/libvirt.so.0(+0x1f222d)[0x7ffff76a922d] + /usr/lib64/libvirt.so.0(+0xbcc4f)[0x7ffff7573c4f] + /usr/lib64/libvirt.so.0(+0xbc5e5)[0x7ffff75735e5] + /lib64/libpthread.so.0(+0x7e0f)[0x7ffff48f7e0f] + /lib64/libc.so.6(clone+0x6d)[0x7ffff400e7dd] + + Fix by initializing ret to 0 and only setting to error on failure path. + +Index: libvirt-1.1.1/src/xen/xend_internal.c +=================================================================== +--- libvirt-1.1.1.orig/src/xen/xend_internal.c ++++ libvirt-1.1.1/src/xen/xend_internal.c +@@ -2896,7 +2896,7 @@ xenDaemonListDefinedDomains(virConnectPt + { + struct sexpr *root = NULL; + size_t i; +- int ret = -1; ++ int ret = 0; + struct sexpr *_for_i, *node; + + if (maxnames == 0) +@@ -2919,16 +2919,15 @@ xenDaemonListDefinedDomains(virConnectPt + break; + } + +- ret = 0; +- + cleanup: + sexpr_free(root); + return ret; + + error: +- for (i = 0; ret != -1 && i < ret; ++i) ++ for (i = 0; i < ret; ++i) + VIR_FREE(names[i]); + ++ ret = -1; + goto cleanup; + } + diff --git a/9d0557b9-legacy-xen-double-free.patch b/9d0557b9-legacy-xen-double-free.patch new file mode 100644 index 0000000..7d84377 --- /dev/null +++ b/9d0557b9-legacy-xen-double-free.patch @@ -0,0 +1,24 @@ +commit 9d0557b9655fe4a3f31af2e1cc2f33de8acfaa7d +Author: Stefan Bader +Date: Wed Jul 31 11:59:21 2013 +0200 + + xen: Avoid double free of virDomainDef in xenDaemonCreateXML + + The virDomainDef is allocated by the caller and also used after + calling to xenDaemonCreateXML. So it must not get freed by the + callee. + + Signed-off-by: Stefan Bader + +Index: libvirt-1.1.1/src/xen/xend_internal.c +=================================================================== +--- libvirt-1.1.1.orig/src/xen/xend_internal.c ++++ libvirt-1.1.1/src/xen/xend_internal.c +@@ -2171,7 +2171,6 @@ xenDaemonCreateXML(virConnectPtr conn, v + if (xenDaemonDomainResume(conn, def) < 0) + goto error; + +- virDomainDefFree(def); + return 0; + + error: diff --git a/d7a45bf2-legacy-xen-dumpxml.patch b/d7a45bf2-legacy-xen-dumpxml.patch new file mode 100644 index 0000000..d4ea3aa --- /dev/null +++ b/d7a45bf2-legacy-xen-dumpxml.patch @@ -0,0 +1,238 @@ +commit d7a45bf22368161869963b92a0a1d5599590fdf5 +Author: Stefan Bader +Date: Tue Aug 6 12:28:58 2013 +0100 + + xen: Use internal interfaces in xenDomainUsedCpus + + Since commit 95e18efd most public interfaces (xenUnified...) obtain + a virDomainDefPtr via xenGetDomainDefFor...() which take the unified + lock. + This is already taken before calling xenDomainUsedCpus(), so we get + a deadlock for active guests. Avoid this by splitting up + xenUnifiedDomainGetVcpusFlags() and xenUnifiedDomainGetVcpus() into + public and private function calls (which get the virDomainDefPtr passed) + and use those in xenDomainUsedCpus(). + + xenDomainUsedCpus + ... + nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom); + return xenUnifiedDomainGetVcpusFlags(...) + ... + if (!(def = xenGetDomainDefForDom(dom))) + return xenGetDomainDefForUUID(dom->conn, dom->uuid); + ... + ret = xenHypervisorLookupDomainByUUID(conn, uuid); + ... + xenUnifiedLock(priv); + name = xenStoreDomainGetName(conn, id); + xenUnifiedUnlock(priv); + ... + if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu, + ... + if (!(def = xenGetDomainDefForDom(dom))) + [again like above] + + Signed-off-by: Stefan Bader + +Index: libvirt-1.1.1/src/xen/xen_driver.c +=================================================================== +--- libvirt-1.1.1.orig/src/xen/xen_driver.c ++++ libvirt-1.1.1/src/xen/xen_driver.c +@@ -73,12 +73,19 @@ + + static int + xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info); ++ + static int +-xenUnifiedDomainGetMaxVcpus(virDomainPtr dom); ++xenUnifiedDomainGetVcpusFlagsInternal(virDomainPtr dom, ++ virDomainDefPtr def, ++ unsigned int flags); ++ + static int +-xenUnifiedDomainGetVcpus(virDomainPtr dom, +- virVcpuInfoPtr info, int maxinfo, +- unsigned char *cpumaps, int maplen); ++xenUnifiedDomainGetVcpusInternal(virDomainPtr dom, ++ virDomainDefPtr def, ++ virVcpuInfoPtr info, ++ int maxinfo, ++ unsigned char *cpumaps, ++ int maplen); + + + static bool is_privileged = false; +@@ -173,6 +180,7 @@ xenNumaInit(virConnectPtr conn) { + /** + * xenDomainUsedCpus: + * @dom: the domain ++ * @def: the domain definition + * + * Analyze which set of CPUs are used by the domain and + * return a string providing the ranges. +@@ -181,7 +189,7 @@ xenNumaInit(virConnectPtr conn) { + * NULL if the domain uses all CPU or in case of error. + */ + char * +-xenDomainUsedCpus(virDomainPtr dom) ++xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def) + { + char *res = NULL; + int ncpus; +@@ -202,7 +210,9 @@ xenDomainUsedCpus(virDomainPtr dom) + + if (priv->nbNodeCpus <= 0) + return NULL; +- nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom); ++ nb_vcpu = xenUnifiedDomainGetVcpusFlagsInternal(dom, def, ++ (VIR_DOMAIN_VCPU_LIVE | ++ VIR_DOMAIN_VCPU_MAXIMUM)); + if (nb_vcpu <= 0) + return NULL; + if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0) +@@ -217,8 +227,8 @@ xenDomainUsedCpus(virDomainPtr dom) + VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0) + goto done; + +- if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu, +- cpumap, cpumaplen)) >= 0) { ++ if ((ncpus = xenUnifiedDomainGetVcpusInternal(dom, def, cpuinfo, nb_vcpu, ++ cpumap, cpumaplen)) >= 0) { + for (n = 0; n < ncpus; n++) { + for (m = 0; m < priv->nbNodeCpus; m++) { + bool used; +@@ -1416,54 +1426,62 @@ cleanup: + } + + static int +-xenUnifiedDomainGetVcpus(virDomainPtr dom, +- virVcpuInfoPtr info, int maxinfo, +- unsigned char *cpumaps, int maplen) ++xenUnifiedDomainGetVcpusInternal(virDomainPtr dom, ++ virDomainDefPtr def, ++ virVcpuInfoPtr info, ++ int maxinfo, ++ unsigned char *cpumaps, ++ int maplen) + { + xenUnifiedPrivatePtr priv = dom->conn->privateData; +- virDomainDefPtr def = NULL; + int ret = -1; + +- if (!(def = xenGetDomainDefForDom(dom))) +- goto cleanup; +- +- if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0) +- goto cleanup; +- + if (dom->id < 0) { + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get VCPUs of inactive domain")); +- goto cleanup; + } else { +- ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo, cpumaps, maplen); ++ ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo, ++ cpumaps, maplen); + } + } else { +- ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps, maplen); ++ ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps, ++ maplen); + } + +-cleanup: +- virDomainDefFree(def); + return ret; + } + + static int +-xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) ++xenUnifiedDomainGetVcpus(virDomainPtr dom, ++ virVcpuInfoPtr info, int maxinfo, ++ unsigned char *cpumaps, int maplen) + { +- xenUnifiedPrivatePtr priv = dom->conn->privateData; + virDomainDefPtr def = NULL; + int ret = -1; + +- virCheckFlags(VIR_DOMAIN_VCPU_LIVE | +- VIR_DOMAIN_VCPU_CONFIG | +- VIR_DOMAIN_VCPU_MAXIMUM, -1); +- + if (!(def = xenGetDomainDefForDom(dom))) + goto cleanup; + +- if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def) < 0) ++ if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0) + goto cleanup; + ++ ret = xenUnifiedDomainGetVcpusInternal(dom, def, info, maxinfo, cpumaps, ++ maplen); ++ ++cleanup: ++ virDomainDefFree(def); ++ return ret; ++} ++ ++static int ++xenUnifiedDomainGetVcpusFlagsInternal(virDomainPtr dom, ++ virDomainDefPtr def, ++ unsigned int flags) ++{ ++ xenUnifiedPrivatePtr priv = dom->conn->privateData; ++ int ret = -1; ++ + if (dom->id < 0) { + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) + ret = xenXMDomainGetVcpusFlags(dom->conn, def, flags); +@@ -1476,6 +1494,27 @@ xenUnifiedDomainGetVcpusFlags(virDomainP + ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags); + } + ++ return ret; ++} ++ ++static int ++xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) ++{ ++ virDomainDefPtr def = NULL; ++ int ret = -1; ++ ++ virCheckFlags(VIR_DOMAIN_VCPU_LIVE | ++ VIR_DOMAIN_VCPU_CONFIG | ++ VIR_DOMAIN_VCPU_MAXIMUM, -1); ++ ++ if (!(def = xenGetDomainDefForDom(dom))) ++ goto cleanup; ++ ++ if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def) < 0) ++ goto cleanup; ++ ++ ret = xenUnifiedDomainGetVcpusFlagsInternal(dom, def, flags); ++ + cleanup: + virDomainDefFree(def); + return ret; +@@ -1507,7 +1546,7 @@ xenUnifiedDomainGetXMLDesc(virDomainPtr + } else { + char *cpus; + xenUnifiedLock(priv); +- cpus = xenDomainUsedCpus(dom); ++ cpus = xenDomainUsedCpus(dom, minidef); + xenUnifiedUnlock(priv); + def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus); + VIR_FREE(cpus); +Index: libvirt-1.1.1/src/xen/xen_driver.h +=================================================================== +--- libvirt-1.1.1.orig/src/xen/xen_driver.h ++++ libvirt-1.1.1/src/xen/xen_driver.h +@@ -187,7 +187,7 @@ struct _xenUnifiedPrivate { + + typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr; + +-char *xenDomainUsedCpus(virDomainPtr dom); ++char *xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def); + + virDomainXMLOptionPtr xenDomainXMLConfInit(void); + diff --git a/fix-pci-attach-xen-driver.patch b/fix-pci-attach-xen-driver.patch index 923406b..6eb5ef7 100644 --- a/fix-pci-attach-xen-driver.patch +++ b/fix-pci-attach-xen-driver.patch @@ -12,7 +12,7 @@ Index: libvirt-1.1.1/src/xen/xend_internal.c =================================================================== --- libvirt-1.1.1.orig/src/xen/xend_internal.c +++ libvirt-1.1.1/src/xen/xend_internal.c -@@ -2207,6 +2207,7 @@ xenDaemonAttachDeviceFlags(virConnectPtr +@@ -2206,6 +2206,7 @@ xenDaemonAttachDeviceFlags(virConnectPtr virBuffer buf = VIR_BUFFER_INITIALIZER; char class[8], ref[80]; char *target = NULL; @@ -20,7 +20,7 @@ Index: libvirt-1.1.1/src/xen/xend_internal.c virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); -@@ -2305,8 +2306,18 @@ xenDaemonAttachDeviceFlags(virConnectPtr +@@ -2304,8 +2305,18 @@ xenDaemonAttachDeviceFlags(virConnectPtr } sexpr = virBufferContentAndReset(&buf); diff --git a/libvirt.changes b/libvirt.changes index 24ed9de..411751e 100644 --- a/libvirt.changes +++ b/libvirt.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Tue Aug 13 10:47:37 MDT 2013 - jfehlig@suse.com + +- Fix memory corruption in legacy Xen driver + 0e671a16-CVE-2013-4239.patch + bnc#834598 +- Upstream patches to fix dumpxml in legacy Xen driver + 9d0557b9-legacy-xen-double-free.patch, + d7a45bf2-legacy-xen-dumpxml.patch + ------------------------------------------------------------------- Wed Jul 31 16:53:28 MDT 2013 - jfehlig@suse.com diff --git a/libvirt.spec b/libvirt.spec index e18ecc3..041c133 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -405,6 +405,9 @@ Source2: libvirtd-relocation-server.fw Source99: baselibs.conf # Upstream patches Patch0: bcef0f01-libxl-console.patch +Patch1: 9d0557b9-legacy-xen-double-free.patch +Patch2: d7a45bf2-legacy-xen-dumpxml.patch +Patch3: 0e671a16-CVE-2013-4239.patch # Need to go upstream Patch100: xen-name-for-devid.patch Patch101: clone.patch @@ -904,6 +907,9 @@ of recent versions of Linux (and other OSes). %prep %setup -q %patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 %patch100 -p1 %patch101 %patch102 -p1 diff --git a/libvirtd-init-script.patch b/libvirtd-init-script.patch index f78ffe7..3b8e1e1 100644 --- a/libvirtd-init-script.patch +++ b/libvirtd-init-script.patch @@ -1,9 +1,9 @@ Adjust libvirtd sysconfig file to conform to SUSE standards -Index: libvirt-1.1.0/daemon/libvirtd.sysconf +Index: libvirt-1.1.1/daemon/libvirtd.sysconf =================================================================== ---- libvirt-1.1.0.orig/daemon/libvirtd.sysconf -+++ libvirt-1.1.0/daemon/libvirtd.sysconf +--- libvirt-1.1.1.orig/daemon/libvirtd.sysconf ++++ libvirt-1.1.1/daemon/libvirtd.sysconf @@ -1,16 +1,25 @@ +## Path: System/Virtualization/libvirt + diff --git a/xen-name-for-devid.patch b/xen-name-for-devid.patch index 4fe71fe..581667c 100644 --- a/xen-name-for-devid.patch +++ b/xen-name-for-devid.patch @@ -27,7 +27,7 @@ Index: libvirt-1.1.1/src/xen/xend_internal.c virDomainDeviceDefPtr dev, char *class, char *ref, int ref_len); -@@ -3316,18 +3316,18 @@ xenDaemonDomainBlockPeek(virConnectPtr c +@@ -3314,18 +3314,18 @@ xenDaemonDomainBlockPeek(virConnectPtr c * Returns 0 in case of success, -1 in case of failure. */ static int @@ -50,7 +50,7 @@ Index: libvirt-1.1.1/src/xen/xend_internal.c if (dev->data.disk->driverName && STREQ(dev->data.disk->driverName, "tap")) strcpy(class, "tap"); -@@ -3337,19 +3337,17 @@ virDomainXMLDevID(virConnectPtr conn, +@@ -3335,19 +3335,17 @@ virDomainXMLDevID(virConnectPtr conn, else strcpy(class, "vbd"); @@ -81,7 +81,7 @@ Index: libvirt-1.1.1/src/xen/xend_internal.c } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { char mac[VIR_MAC_STRING_BUFLEN]; virDomainNetDefPtr netdef = dev->data.net; -@@ -3357,16 +3355,22 @@ virDomainXMLDevID(virConnectPtr conn, +@@ -3355,16 +3353,22 @@ virDomainXMLDevID(virConnectPtr conn, strcpy(class, "vif"); @@ -114,7 +114,7 @@ Index: libvirt-1.1.1/src/xen/xend_internal.c } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { -@@ -3382,17 +3386,44 @@ virDomainXMLDevID(virConnectPtr conn, +@@ -3380,17 +3384,44 @@ virDomainXMLDevID(virConnectPtr conn, strcpy(class, "pci");