Accepting request 41177 from Virtualization

Copy from Virtualization/libvirt based on submit request 41177 from user jfehlig

OBS-URL: https://build.opensuse.org/request/show/41177
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libvirt?expand=0&rev=54
This commit is contained in:
OBS User autobuild 2010-06-05 10:51:51 +00:00 committed by Git OBS Bridge
commit a1333eabfa
13 changed files with 898 additions and 15 deletions

29
bitmap-alloc.patch Normal file
View File

@ -0,0 +1,29 @@
commit ce49cfb48ad5e9cac79819d0ccde4394c237af25
Author: Eric Blake <eblake@redhat.com>
Date: Wed Jun 2 09:03:57 2010 -0600
bitmap: reject zero-size bitmap
* src/util/bitmap.c (virBitmapAlloc): Tighten sanity check.
diff --git a/src/util/bitmap.c b/src/util/bitmap.c
index 69094a5..44edb49 100644
--- a/src/util/bitmap.c
+++ b/src/util/bitmap.c
@@ -1,6 +1,7 @@
/*
* bitmap.h: Simple bitmap operations
*
+ * Copyright (C) 2010 Red Hat, Inc.
* Copyright (C) 2010 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -58,7 +59,7 @@ virBitmapPtr virBitmapAlloc(size_t size)
virBitmapPtr bitmap;
size_t sz;
- if (SIZE_MAX - VIR_BITMAP_BITS_PER_UNIT < size)
+ if (SIZE_MAX - VIR_BITMAP_BITS_PER_UNIT < size || size == 0)
return NULL;
sz = (size + VIR_BITMAP_BITS_PER_UNIT - 1) /

59
bitmap-fixes.patch Normal file
View File

@ -0,0 +1,59 @@
If VM startup fails early enough (can't find a referenced USB device),
libvirtd will crash trying to clear the VNC port bit, since port = 0,
which overflows us out of the bitmap bounds.
Fix this by being more defensive in the bitmap operations, and only
clearing a previously set VNC port.
v2: Add safety check to all relevant bitmap ops.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
src/qemu/qemu_driver.c | 2 +-
src/util/bitmap.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
===================================================================
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
@@ -3635,7 +3635,7 @@ retry:
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport &&
- vm->def->graphics[0]->data.vnc.port != -1) {
+ vm->def->graphics[0]->data.vnc.port >= QEMU_VNC_PORT_MIN) {
if (virBitmapClearBit(driver->reservedVNCPorts,
vm->def->graphics[0]->data.vnc.port - \
QEMU_VNC_PORT_MIN) < 0) {
Index: libvirt-0.8.1/src/util/bitmap.c
===================================================================
--- libvirt-0.8.1.orig/src/util/bitmap.c
+++ libvirt-0.8.1/src/util/bitmap.c
@@ -101,7 +101,7 @@ void virBitmapFree(virBitmapPtr bitmap)
*/
int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
{
- if (b > bitmap->size - 1)
+ if (bitmap->size <= b)
return -1;
bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] |= (1 << VIR_BITMAP_BIT_OFFSET(b));
@@ -119,7 +119,7 @@ int virBitmapSetBit(virBitmapPtr bitmap,
*/
int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
{
- if (b > bitmap->size - 1)
+ if (bitmap->size <= b)
return -1;
bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &= ~(1 << VIR_BITMAP_BIT_OFFSET(b));
@@ -141,7 +141,7 @@ int virBitmapGetBit(virBitmapPtr bitmap,
{
uint32_t bit;
- if (b > bitmap->size - 1)
+ if (bitmap->size <= b)
return -1;
bit = bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &

View File

@ -1,3 +1,21 @@
-------------------------------------------------------------------
Fri Jun 4 13:16:31 MDT 2010 - jfehlig@novell.com
- Allocate buffer to hold xend content
bnc#609738
xend-buff-size.patch
- Add upstream fixes to bitmap code that was introduced to fix
bnc#594024
bitmap-alloc.patch
bitmap-fixes.patch
-------------------------------------------------------------------
Tue Jun 1 13:52:21 MDT 2010 - jfehlig@novell.com
- Fix race in VNC port reservation with qemu/KVM domains
bnc#594024
vnc-race-{1,2,3}.patch
-------------------------------------------------------------------
Wed May 12 11:29:44 MDT 2010 - jfehlig@novell.com

View File

@ -118,7 +118,7 @@ License: LGPLv2.1+
Group: Development/Libraries/C and C++
AutoReqProv: yes
Version: 0.8.1
Release: 1
Release: 2
Summary: A C toolkit to interract with the virtualization capabilities of Linux
# The client side, i.e. shared libs and virsh are in a subpackage
Requires: %{name}-client = %{version}-%{release}
@ -143,6 +143,13 @@ Source0: %{name}-%{version}.tar.bz2
Source1: libvirtd.init
# Upstream patches
Patch0: remote-rm-unused-field.patch
Patch1: vnc-race-1.patch
Patch2: vnc-race-2.patch
Patch3: vnc-race-3.patch
Patch4: bitmap-alloc.patch
Patch5: bitmap-fixes.patch
Patch6: xend-content-buf.patch
Patch7: xend-content-buf-fix.patch
# Need to go upstream
Patch100: xen-name-for-devid.patch
Patch101: socat.patch
@ -257,6 +264,13 @@ Authors:
%prep
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch100 -p1
%patch101 -p1
%patch102
@ -428,7 +442,7 @@ rm -rf $RPM_BUILD_ROOT
%{_sysconfdir}/libvirt/nwfilter/*.xml
%config /etc/init.d/libvirtd
%{_sbindir}/rclibvirtd
%config %{_sysconfdir}/libvirt/libvirtd.conf
%config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
%config %{_sysconfdir}/libvirt/qemu/networks/default.xml
%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/network/
%dir %{_localstatedir}/lib/libvirt/
@ -492,7 +506,7 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/libvirt/schemas/storageencryption.rng
%{_datadir}/libvirt/cpu_map.xml
%{_datadir}/libvirt/schemas/nwfilter.rng
%config %{_sysconfdir}/sasl2/libvirt.conf
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
%files devel
%defattr(-, root, root)

281
vnc-race-1.patch Normal file
View File

@ -0,0 +1,281 @@
commit 2f32d7afd5bd71f79c0e756c87813702065c6d1a
Author: Jim Fehlig <jfehlig@novell.com>
Date: Thu May 20 22:23:48 2010 -0600
Add simple bitmap operations to utils
V2:
- Move bitmap impl to src/util/bitmap.[ch]
- Use CHAR_BIT instead of explicit '8'
- Use size_t instead of unsigned int
- Fix calculation of bitmap size in virBitmapAlloc
- Ensure bit is within range of map in the set, clear, and get
operations
- Use bool in virBitmapGetBit
- Add virBitmapFree to free-like funcs in cfg.mk
V3:
- Check for overflow in virBitmapAlloc
- Fix copy and paste bug in virBitmapAlloc
- Use size_t in prototypes
- Add ATTRIBUTE_NONNULL in prototypes where appropriate
and remove NULL check from impl
V4:
- Add ATTRIBUTE_RETURN_CHECK in prototypes where appropriate.
Index: libvirt-0.8.1/src/Makefile.am
===================================================================
--- libvirt-0.8.1.orig/src/Makefile.am
+++ libvirt-0.8.1/src/Makefile.am
@@ -50,6 +50,7 @@ augeastest_DATA =
# helper APIs for various purposes
UTIL_SOURCES = \
util/authhelper.c util/authhelper.h \
+ util/bitmap.c util/bitmap.h \
util/bridge.c util/bridge.h \
util/buf.c util/buf.h \
util/conf.c util/conf.h \
Index: libvirt-0.8.1/src/libvirt_private.syms
===================================================================
--- libvirt-0.8.1.orig/src/libvirt_private.syms
+++ libvirt-0.8.1/src/libvirt_private.syms
@@ -4,6 +4,14 @@
#
+# bitmap.h
+virBitmapAlloc;
+virBitmapFree;
+virBitmapSetBit;
+virBitmapClearBit;
+virBitmapGetBit;
+
+
# buf.h
virBufferVSprintf;
virBufferEscapeString;
Index: libvirt-0.8.1/src/util/bitmap.c
===================================================================
--- /dev/null
+++ libvirt-0.8.1/src/util/bitmap.c
@@ -0,0 +1,151 @@
+/*
+ * bitmap.h: Simple bitmap operations
+ *
+ * Copyright (C) 2010 Novell, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Jim Fehlig <jfehlig@novell.com>
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "bitmap.h"
+#include "memory.h"
+
+
+struct _virBitmap {
+ size_t size;
+ uint32_t *map;
+};
+
+
+#define VIR_BITMAP_BITS_PER_UNIT (sizeof(uint32_t) * CHAR_BIT)
+#define VIR_BITMAP_UNIT_OFFSET(b) ((b) / VIR_BITMAP_BITS_PER_UNIT)
+#define VIR_BITMAP_BIT_OFFSET(b) ((b) % VIR_BITMAP_BITS_PER_UNIT)
+
+
+/**
+ * virBitmapAlloc:
+ * @size: number of bits
+ *
+ * Allocate a bitmap capable of containing @size bits.
+ *
+ * Returns a pointer to the allocated bitmap or NULL if
+ * memory cannot be allocated.
+ */
+virBitmapPtr virBitmapAlloc(size_t size)
+{
+ virBitmapPtr bitmap;
+ size_t sz;
+
+ if (SIZE_MAX - VIR_BITMAP_BITS_PER_UNIT < size)
+ return NULL;
+
+ sz = (size + VIR_BITMAP_BITS_PER_UNIT - 1) /
+ VIR_BITMAP_BITS_PER_UNIT;
+
+ if (VIR_ALLOC(bitmap) < 0)
+ return NULL;
+
+ if (VIR_ALLOC_N(bitmap->map, sz) < 0) {
+ VIR_FREE(bitmap);
+ return NULL;
+ }
+
+ return bitmap;
+}
+
+/**
+ * virBitmapFree:
+ * @bitmap: previously allocated bitmap
+ *
+ * Free @bitmap previously allocated by virBitmapAlloc.
+ */
+void virBitmapFree(virBitmapPtr bitmap)
+{
+ if (bitmap) {
+ VIR_FREE(bitmap->map);
+ VIR_FREE(bitmap);
+ }
+}
+
+/**
+ * virBitmapSetBit:
+ * @bitmap: Pointer to bitmap
+ * @b: bit position to set
+ *
+ * Set bit position @b in @bitmap
+ *
+ * Returns 0 on if bit is successfully set, -1 on error.
+ */
+int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
+{
+ if (b > bitmap->size - 1)
+ return -1;
+
+ bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] |= (1 << VIR_BITMAP_BIT_OFFSET(b));
+ return 0;
+}
+
+/**
+ * virBitmapClearBit:
+ * @bitmap: Pointer to bitmap
+ * @b: bit position to clear
+ *
+ * Clear bit position @b in @bitmap
+ *
+ * Returns 0 on if bit is successfully clear, -1 on error.
+ */
+int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
+{
+ if (b > bitmap->size - 1)
+ return -1;
+
+ bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &= ~(1 << VIR_BITMAP_BIT_OFFSET(b));
+ return 0;
+}
+
+/**
+ * virBitmapGetBit:
+ * @bitmap: Pointer to bitmap
+ * @b: bit position to get
+ * @result: bool pointer to receive bit setting
+ *
+ * Get setting of bit position @b in @bitmap and store in @result
+ *
+ * On success, @result will contain the setting of @b and 0 is
+ * returned. On failure, -1 is returned and @result is unchanged.
+ */
+int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
+{
+ uint32_t bit;
+
+ if (b > bitmap->size - 1)
+ return -1;
+
+ bit = bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)] &
+ (1 << VIR_BITMAP_BIT_OFFSET(b));
+
+ *result = bit != 0;
+ return 0;
+}
Index: libvirt-0.8.1/src/util/bitmap.h
===================================================================
--- /dev/null
+++ libvirt-0.8.1/src/util/bitmap.h
@@ -0,0 +1,63 @@
+/*
+ * bitmap.h: Simple bitmap operations
+ *
+ * Copyright (C) 2010 Novell, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Jim Fehlig <jfehlig@novell.com>
+ */
+
+#ifndef __BITMAP_H__
+# define __BITMAP_H__
+
+#include "internal.h"
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+
+typedef struct _virBitmap virBitmap;
+typedef virBitmap *virBitmapPtr;
+
+/*
+ * Allocate a bitmap capable of containing @size bits.
+ */
+virBitmapPtr virBitmapAlloc(size_t size) ATTRIBUTE_RETURN_CHECK;
+
+/*
+ * Free previously allocated bitmap
+ */
+void virBitmapFree(virBitmapPtr bitmap);
+
+/*
+ * Set bit position @b in @bitmap
+ */
+int virBitmapSetBit(virBitmapPtr bitmap, size_t b)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+/*
+ * Clear bit position @b in @bitmap
+ */
+int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+/*
+ * Get setting of bit position @b in @bitmap and store in @result
+ */
+int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK;
+
+#endif

29
vnc-race-2.patch Normal file
View File

@ -0,0 +1,29 @@
commit c020f6203e3735a531135bc4321415ce5520fbde
Author: Jim Fehlig <jfehlig@novell.com>
Date: Thu May 20 22:25:16 2010 -0600
Add defines for QEMU_VNC_PORT_{MIN,MAX} and use them
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
===================================================================
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
@@ -89,6 +89,9 @@
#define VIR_FROM_THIS VIR_FROM_QEMU
+#define QEMU_VNC_PORT_MIN 5900
+#define QEMU_VNC_PORT_MAX 65535
+
/* Only 1 job is allowed at any time
* A job includes *all* monitor commands, even those just querying
* information, not merely actions */
@@ -2607,7 +2610,7 @@ qemuInitPCIAddresses(struct qemud_driver
static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
int i;
- for (i = 5900 ; i < 65535 ; i++) {
+ for (i = QEMU_VNC_PORT_MIN; i < QEMU_VNC_PORT_MAX; i++) {
int fd;
int reuse = 1;
struct sockaddr_in addr;

130
vnc-race-3.patch Normal file
View File

@ -0,0 +1,130 @@
commit ba196952f57f2cb22be75fa5a4f363035a111103
Author: Jim Fehlig <jfehlig@novell.com>
Date: Fri May 21 07:52:09 2010 -0600
Fix race in finding available vnc port
The qemu driver contains a subtle race in the logic to find next
available vnc port. Currently it iterates through all available ports
and returns the first for which bind(2) succeeds. However it is possible
that a previously issued port has not yet been bound by qemu, resulting
in the same port used for a subsequent domain.
This patch addresses the race by using a simple bitmap to "reserve" the
ports allocated by libvirt.
V2:
- Put port bitmap in struct qemud_driver
- Initialize bitmap in qemudStartup
V3:
- Check for failure of virBitmapGetBit
- Additional check for port != -1 before calling virbitmapClearBit
V4:
- Check for failure of virBitmap{Set,Clear}Bit
Index: libvirt-0.8.1/src/qemu/qemu_conf.h
===================================================================
--- libvirt-0.8.1.orig/src/qemu/qemu_conf.h
+++ libvirt-0.8.1/src/qemu/qemu_conf.h
@@ -39,6 +39,7 @@
# include "pci.h"
# include "cpu_conf.h"
# include "driver.h"
+# include "bitmap.h"
# define qemudDebug(fmt, ...) do {} while(0)
@@ -153,6 +154,8 @@ struct qemud_driver {
char *saveImageFormat;
pciDeviceList *activePciHostdevs;
+
+ virBitmapPtr reservedVNCPorts;
};
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
Index: libvirt-0.8.1/src/qemu/qemu_driver.c
===================================================================
--- libvirt-0.8.1.orig/src/qemu/qemu_driver.c
+++ libvirt-0.8.1/src/qemu/qemu_driver.c
@@ -1479,6 +1479,11 @@ qemudStartup(int privileged) {
virEventAddTimeout(-1, qemuDomainEventFlush, qemu_driver, NULL)) < 0)
goto error;
+ /* Allocate bitmap for vnc port reservation */
+ if ((qemu_driver->reservedVNCPorts =
+ virBitmapAlloc(QEMU_VNC_PORT_MAX - QEMU_VNC_PORT_MIN)) == NULL)
+ goto out_of_memory;
+
if (privileged) {
if (virAsprintf(&qemu_driver->logDir,
"%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
@@ -1775,6 +1780,7 @@ qemudShutdown(void) {
virCapabilitiesFree(qemu_driver->caps);
virDomainObjListDeinit(&qemu_driver->domains);
+ virBitmapFree(qemu_driver->reservedVNCPorts);
VIR_FREE(qemu_driver->securityDriverName);
VIR_FREE(qemu_driver->logDir);
@@ -2607,13 +2613,22 @@ qemuInitPCIAddresses(struct qemud_driver
return ret;
}
-static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
+static int qemudNextFreeVNCPort(struct qemud_driver *driver) {
int i;
for (i = QEMU_VNC_PORT_MIN; i < QEMU_VNC_PORT_MAX; i++) {
int fd;
int reuse = 1;
struct sockaddr_in addr;
+ bool used = false;
+
+ if (virBitmapGetBit(driver->reservedVNCPorts,
+ i - QEMU_VNC_PORT_MIN, &used) < 0)
+ VIR_DEBUG("virBitmapGetBit failed on bit %d", i - QEMU_VNC_PORT_MIN);
+
+ if (used)
+ continue;
+
addr.sin_family = AF_INET;
addr.sin_port = htons(i);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -2629,6 +2644,12 @@ static int qemudNextFreeVNCPort(struct q
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
/* Not in use, lets grab it */
close(fd);
+ /* Add port to bitmap of reserved ports */
+ if (virBitmapSetBit(driver->reservedVNCPorts,
+ i - QEMU_VNC_PORT_MIN) < 0) {
+ VIR_DEBUG("virBitmapSetBit failed on bit %d",
+ i - QEMU_VNC_PORT_MIN);
+ }
return i;
}
close(fd);
@@ -3608,6 +3629,21 @@ retry:
qemudRemoveDomainStatus(driver, vm);
+ /* Remove VNC port from port reservation bitmap, but only if it was
+ reserved by the driver (autoport=yes)
+ */
+ if ((vm->def->ngraphics == 1) &&
+ vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ vm->def->graphics[0]->data.vnc.autoport &&
+ vm->def->graphics[0]->data.vnc.port != -1) {
+ if (virBitmapClearBit(driver->reservedVNCPorts,
+ vm->def->graphics[0]->data.vnc.port - \
+ QEMU_VNC_PORT_MIN) < 0) {
+ VIR_DEBUG("virBitmapClearBit failed on bit %d",
+ vm->def->graphics[0]->data.vnc.port - QEMU_VNC_PORT_MIN);
+ }
+ }
+
vm->pid = -1;
vm->def->id = -1;
vm->state = VIR_DOMAIN_SHUTOFF;

View File

@ -17,7 +17,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
===================================================================
--- libvirt-0.8.1.orig/src/xen/xend_internal.c
+++ libvirt-0.8.1/src/xen/xend_internal.c
@@ -91,6 +91,7 @@ xenDaemonFormatSxprOnePCI(virDomainHostd
@@ -92,6 +92,7 @@ xenDaemonFormatSxprOnePCI(virDomainHostd
static int
virDomainXMLDevID(virDomainPtr domain,
@ -25,7 +25,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
virDomainDeviceDefPtr dev,
char *class,
char *ref,
@@ -4164,7 +4165,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr
@@ -4178,7 +4179,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr
sexpr = virBufferContentAndReset(&buf);
@ -34,7 +34,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
/* device doesn't exist, define it */
ret = xend_op(domain->conn, domain->name, "op", "device_create",
"config", sexpr, NULL);
@@ -4281,7 +4282,7 @@ xenDaemonUpdateDeviceFlags(virDomainPtr
@@ -4295,7 +4296,7 @@ xenDaemonUpdateDeviceFlags(virDomainPtr
sexpr = virBufferContentAndReset(&buf);
@ -43,7 +43,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
virXendError(VIR_ERR_OPERATION_INVALID, "%s",
_("requested device does not exist"));
goto cleanup;
@@ -4373,7 +4374,7 @@ xenDaemonDetachDeviceFlags(virDomainPtr
@@ -4387,7 +4388,7 @@ xenDaemonDetachDeviceFlags(virDomainPtr
def, xml, VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
@ -52,7 +52,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
goto cleanup;
if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
@@ -6121,6 +6122,7 @@ error:
@@ -6135,6 +6136,7 @@ error:
*/
static int
virDomainXMLDevID(virDomainPtr domain,
@ -60,7 +60,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
virDomainDeviceDefPtr dev,
char *class,
char *ref,
@@ -6129,27 +6131,33 @@ virDomainXMLDevID(virDomainPtr domain,
@@ -6143,27 +6145,33 @@ virDomainXMLDevID(virDomainPtr domain,
xenUnifiedPrivatePtr priv = domain->conn->privateData;
char *xref;
char *tmp;

View File

@ -2,7 +2,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
===================================================================
--- libvirt-0.8.1.orig/src/xen/xend_internal.c
+++ libvirt-0.8.1/src/xen/xend_internal.c
@@ -5531,7 +5531,10 @@ xenDaemonFormatSxprDisk(virConnectPtr co
@@ -5545,7 +5545,10 @@ xenDaemonFormatSxprDisk(virConnectPtr co
} else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
virBufferVSprintf(buf, "(dev '%s:cdrom')", def->dst);
} else {

View File

@ -2,7 +2,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
===================================================================
--- libvirt-0.8.1.orig/src/xen/xend_internal.c
+++ libvirt-0.8.1/src/xen/xend_internal.c
@@ -1596,7 +1596,8 @@ xenDaemonParseSxprDisks(virDomainDefPtr
@@ -1610,7 +1610,8 @@ xenDaemonParseSxprDisks(virDomainDefPtr
but blktap disks ended up in a differently named
(device (tap ....)) block.... */
if (sexpr_lookup(node, "device/vbd") ||
@ -12,7 +12,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
char *offset;
const char *src = NULL;
const char *dst = NULL;
@@ -1607,10 +1608,14 @@ xenDaemonParseSxprDisks(virDomainDefPtr
@@ -1621,10 +1622,14 @@ xenDaemonParseSxprDisks(virDomainDefPtr
src = sexpr_node(node, "device/vbd/uname");
dst = sexpr_node(node, "device/vbd/dev");
mode = sexpr_node(node, "device/vbd/mode");

View File

@ -0,0 +1,79 @@
commit b1eb7f2e987d21b1711e86e5cb63a69abfce82f1
Author: Jim Fehlig <jfehlig@linux-ypgk.site>
Date: Fri Jun 4 10:04:03 2010 -0600
Fixes for commit 211dd1e9
Fixes for issues in commit 211dd1e9 noted by by Jim Meyering.
1. Allocate content buffer of size content_length + 1 to ensure
NUL-termination.
2. Limit content buffer size to 64k
3. Fix whitespace issue
V2:
- Add comment to clarify allocation of content buffer
- Add ATTRIBUTE_NONNULL where appropriate
- User NULLSTR macro
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 0c1a738..51cad92 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -68,6 +68,7 @@
# define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
#endif
+#define XEND_RCV_BUF_MAX_LEN 65536
#ifndef PROXY
static int
@@ -310,7 +311,7 @@ istartswith(const char *haystack, const char *needle)
* Returns the HTTP return code and @content is set to the
* allocated memory containing HTTP content.
*/
-static int
+static int ATTRIBUTE_NONNULL (2)
xend_req(int fd, char **content)
{
char buffer[4096];
@@ -330,7 +331,19 @@ xend_req(int fd, char **content)
if (content_length > 0) {
ssize_t ret;
- if (VIR_ALLOC_N(*content, content_length) < 0 ) {
+ if (content_length > XEND_RCV_BUF_MAX_LEN) {
+ virXendError(VIR_ERR_INTERNAL_ERROR,
+ _("Xend returned HTTP Content-Length of %d, "
+ "which exceeds maximum of %d"),
+ content_length,
+ XEND_RCV_BUF_MAX_LEN);
+ return -1;
+ }
+
+ /* Allocate one byte beyond the end of the largest buffer we will read.
+ Combined with the fact that VIR_ALLOC_N zeros the returned buffer,
+ this guarantees that "content" will always be NUL-terminated. */
+ if (VIR_ALLOC_N(*content, content_length + 1) < 0 ) {
virReportOOMError();
return -1;
}
@@ -353,7 +366,7 @@ xend_req(int fd, char **content)
*
* Returns the HTTP return code or -1 in case or error.
*/
-static int
+static int ATTRIBUTE_NONNULL(3)
xend_get(virConnectPtr xend, const char *path,
char **content)
{
@@ -379,8 +392,7 @@ xend_get(virConnectPtr xend, const char *path,
((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
virXendError(VIR_ERR_GET_FAILED,
_("%d status from xen daemon: %s:%s"),
- ret, path,
- content ? *content: "NULL");
+ ret, path, NULLSTR(*content));
}
return ret;

244
xend-content-buf.patch Normal file
View File

@ -0,0 +1,244 @@
commit 211dd1e9c54a9ba92e2e648acacbc18981374073
Author: Jim Fehlig <jfehlig@novell.com>
Date: Wed Jun 2 18:07:17 2010 -0600
Allocate buffer to hold xend response
There are cases when a response from xend can exceed 4096 bytes, in
which case anything beyond 4096 is ignored. This patch changes the
current fixed-size, stack-allocated buffer to a dynamically allocated
buffer based on Content-Length in HTTP header.
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index e763bad..0c1a738 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -302,17 +302,19 @@ istartswith(const char *haystack, const char *needle)
* xend_req:
* @fd: the file descriptor
* @content: the buffer to store the content
- * @n_content: the size of the buffer
*
* Read the HTTP response from a Xen Daemon request.
+ * If the response contains content, memory is allocated to
+ * hold the content.
*
- * Returns the HTTP return code.
+ * Returns the HTTP return code and @content is set to the
+ * allocated memory containing HTTP content.
*/
static int
-xend_req(int fd, char *content, size_t n_content)
+xend_req(int fd, char **content)
{
char buffer[4096];
- int content_length = -1;
+ int content_length = 0;
int retcode = 0;
while (sreads(fd, buffer, sizeof(buffer)) > 0) {
@@ -325,19 +327,17 @@ xend_req(int fd, char *content, size_t n_content)
retcode = atoi(buffer + 9);
}
- if (content_length > -1) {
+ if (content_length > 0) {
ssize_t ret;
- if ((unsigned int) content_length > (n_content + 1))
- content_length = n_content - 1;
+ if (VIR_ALLOC_N(*content, content_length) < 0 ) {
+ virReportOOMError();
+ return -1;
+ }
- ret = sread(fd, content, content_length);
+ ret = sread(fd, *content, content_length);
if (ret < 0)
return -1;
-
- content[ret] = 0;
- } else {
- content[0] = 0;
}
return retcode;
@@ -348,7 +348,6 @@ xend_req(int fd, char *content, size_t n_content)
* @xend: pointer to the Xen Daemon structure
* @path: the path used for the HTTP request
* @content: the buffer to store the content
- * @n_content: the size of the buffer
*
* Do an HTTP GET RPC with the Xen Daemon
*
@@ -356,7 +355,7 @@ xend_req(int fd, char *content, size_t n_content)
*/
static int
xend_get(virConnectPtr xend, const char *path,
- char *content, size_t n_content)
+ char **content)
{
int ret;
int s = do_connect(xend);
@@ -373,14 +372,15 @@ xend_get(virConnectPtr xend, const char *path,
"Accept-Encoding: identity\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n" "\r\n");
- ret = xend_req(s, content, n_content);
+ ret = xend_req(s, content);
close(s);
if (((ret < 0) || (ret >= 300)) &&
((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
virXendError(VIR_ERR_GET_FAILED,
_("%d status from xen daemon: %s:%s"),
- ret, path, content);
+ ret, path,
+ content ? *content: "NULL");
}
return ret;
@@ -392,8 +392,6 @@ xend_get(virConnectPtr xend, const char *path,
* @xend: pointer to the Xen Daemon structure
* @path: the path used for the HTTP request
* @ops: the information sent for the POST
- * @content: the buffer to store the content
- * @n_content: the size of the buffer
*
* Do an HTTP POST RPC with the Xen Daemon, this usually makes changes at the
* Xen level.
@@ -401,10 +399,10 @@ xend_get(virConnectPtr xend, const char *path,
* Returns the HTTP return code or -1 in case or error.
*/
static int
-xend_post(virConnectPtr xend, const char *path, const char *ops,
- char *content, size_t n_content)
+xend_post(virConnectPtr xend, const char *path, const char *ops)
{
char buffer[100];
+ char *err_buf = NULL;
int ret;
int s = do_connect(xend);
@@ -425,26 +423,28 @@ xend_post(virConnectPtr xend, const char *path, const char *ops,
swrites(s, "\r\n\r\n");
swrites(s, ops);
- ret = xend_req(s, content, n_content);
+ ret = xend_req(s, &err_buf);
close(s);
if ((ret < 0) || (ret >= 300)) {
virXendError(VIR_ERR_POST_FAILED,
- _("xend_post: error from xen daemon: %s"), content);
- } else if ((ret == 202) && (strstr(content, "failed") != NULL)) {
+ _("xend_post: error from xen daemon: %s"), err_buf);
+ } else if ((ret == 202) && err_buf && (strstr(err_buf, "failed") != NULL)) {
virXendError(VIR_ERR_POST_FAILED,
- _("xend_post: error from xen daemon: %s"), content);
+ _("xend_post: error from xen daemon: %s"), err_buf);
ret = -1;
- } else if (((ret >= 200) && (ret <= 202)) && (strstr(content, "xend.err") != NULL)) {
+ } else if (((ret >= 200) && (ret <= 202)) && err_buf &&
+ (strstr(err_buf, "xend.err") != NULL)) {
/* This is to catch case of things like 'virsh dump Domain-0 foo'
* which returns a success code, but the word 'xend.err'
* in body to indicate error :-(
*/
virXendError(VIR_ERR_POST_FAILED,
- _("xend_post: error from xen daemon: %s"), content);
+ _("xend_post: error from xen daemon: %s"), err_buf);
ret = -1;
}
+ VIR_FREE(err_buf);
return ret;
}
#endif /* ! PROXY */
@@ -487,8 +487,6 @@ http2unix(int ret)
* xend_op_ext:
* @xend: pointer to the Xen Daemon structure
* @path: path for the object
- * @error: buffer for the error output
- * @n_error: size of @error
* @key: the key for the operation
* @ap: input values to pass to the operation
*
@@ -497,8 +495,7 @@ http2unix(int ret)
* Returns 0 in case of success, -1 in case of failure.
*/
static int
-xend_op_ext(virConnectPtr xend, const char *path, char *error,
- size_t n_error, const char *key, va_list ap)
+xend_op_ext(virConnectPtr xend, const char *path, const char *key, va_list ap)
{
const char *k = key, *v;
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -524,7 +521,7 @@ xend_op_ext(virConnectPtr xend, const char *path, char *error,
}
content = virBufferContentAndReset(&buf);
- ret = http2unix(xend_post(xend, path, content, error, n_error));
+ ret = http2unix(xend_post(xend, path, content));
VIR_FREE(content);
return ret;
@@ -535,8 +532,6 @@ xend_op_ext(virConnectPtr xend, const char *path, char *error,
* xend_op:
* @xend: pointer to the Xen Daemon structure
* @name: the domain name target of this operation
- * @error: buffer for the error output
- * @n_error: size of @error
* @key: the key for the operation
* @ap: input values to pass to the operation
* @...: input values to pass to the operation
@@ -550,14 +545,13 @@ static int ATTRIBUTE_SENTINEL
xend_op(virConnectPtr xend, const char *name, const char *key, ...)
{
char buffer[1024];
- char error[1024];
va_list ap;
int ret;
snprintf(buffer, sizeof(buffer), "/xend/domain/%s", name);
va_start(ap, key);
- ret = xend_op_ext(xend, buffer, error, sizeof(error), key, ap);
+ ret = xend_op_ext(xend, buffer, key, ap);
va_end(ap);
return ret;
@@ -581,21 +575,29 @@ static struct sexpr *sexpr_get(virConnectPtr xend, const char *fmt, ...)
static struct sexpr *
sexpr_get(virConnectPtr xend, const char *fmt, ...)
{
- char buffer[4096];
+ char *buffer = NULL;
char path[1024];
va_list ap;
int ret;
+ struct sexpr *res = NULL;
va_start(ap, fmt);
vsnprintf(path, sizeof(path), fmt, ap);
va_end(ap);
- ret = xend_get(xend, path, buffer, sizeof(buffer));
+ ret = xend_get(xend, path, &buffer);
ret = http2unix(ret);
if (ret == -1)
- return NULL;
+ goto cleanup;
+
+ if (buffer == NULL)
+ goto cleanup;
+
+ res = string2sexpr(buffer);
- return string2sexpr(buffer);
+cleanup:
+ VIR_FREE(buffer);
+ return res;
}
/**

View File

@ -2,7 +2,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
===================================================================
--- libvirt-0.8.1.orig/src/xen/xend_internal.c
+++ libvirt-0.8.1/src/xen/xend_internal.c
@@ -1602,20 +1602,24 @@ xenDaemonParseSxprDisks(virDomainDefPtr
@@ -1616,20 +1616,24 @@ xenDaemonParseSxprDisks(virDomainDefPtr
const char *src = NULL;
const char *dst = NULL;
const char *mode = NULL;
@ -27,7 +27,7 @@ Index: libvirt-0.8.1/src/xen/xend_internal.c
}
if (VIR_ALLOC(disk) < 0)
@@ -1740,7 +1744,12 @@ xenDaemonParseSxprDisks(virDomainDefPtr
@@ -1754,7 +1758,12 @@ xenDaemonParseSxprDisks(virDomainDefPtr
if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
goto no_memory;