Compare commits

..

14 Commits

Author SHA1 Message Date
Daniel P. Berrange
40a867daeb Misc important fixes from BZ
- Fix crash when attaching/detaching non-existant PCI device (rhbz #510907)
- Fix QEMU guest name/uuid uniqueness checks (rhbz #507405)
- Fix to use correct pci_add/del syntax for QEMU (rhbz #499669)
- Relabel disks before hotplugging them to guest (rhbz #496442)
- Correctly handle 8-bit high bytes when escaping XML (rhbz #479517)
2009-08-05 15:48:14 +00:00
Mark McLoughlin
60e1b2cda5 * Fri Jul 3 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-13.fc11
- Fix libvirtd crash with bad capabilities data (bug #505635)
- Don't unnecessarily try to change a file context (bug #507555)
2009-07-03 10:05:41 +00:00
Mark McLoughlin
c8361aee7d * Fri Jun 5 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-12.fc11
- Use the correct QEMU machine type for ppc (bug #502862)
- Fix crash with TLS connections (bug #503066)
- Fix broken networking with newer qemu releases (bug #503275)
- Remove the qemu BuildRequires
2009-06-05 11:47:31 +00:00
Mark McLoughlin
bda88aaa38 * Mon May 25 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-11.fc11
- Bring up the bridge, even if it doesn't have an IP address (bug #501912)
2009-05-25 15:23:17 +00:00
Mark McLoughlin
ca4d795c85 * Fri May 22 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-10.fc11
- Don't log monitor output to domain log file (bug #499584)
2009-05-22 09:24:30 +00:00
Mark McLoughlin
e2e196d813 * Thu May 21 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-9.fc11
- Fix qemu argv detection with latest qemu (bug #501923)
- Fix XML attribute escaping (bug #499791)
- Fix serious event handling issues causing guests to be destroyed (bug #499698)
2009-05-21 12:07:19 +00:00
Cole Robinson
a5a2a38a5e Don't try to label a disk with no path (e.g. empty cdrom) (bug #499569) 2009-05-11 02:28:23 +00:00
Mark McLoughlin
30f098460c * Thu May 7 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-7.fc11
- Enable migration for qemu 0.10 (bug #499704)
2009-05-07 19:08:42 +00:00
Cole Robinson
7017c99a1e Refresh qemu caps when getCapabilities is called (bug #460649) 2009-05-06 16:32:34 +00:00
Mark McLoughlin
1c41ce6f30 * Wed May 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-5.fc11
- Fix handling of <hostdev managed='yes'> (bug #499386)
2009-05-06 15:51:47 +00:00
Daniel P. Berrange
c6db79d97f Fix labelling of shared/readonly disks (rhbz #493692) 2009-05-05 13:01:15 +00:00
Daniel Veillard
7b7f8cc27f - Fix missing directories in spec (#496945 and gtk-doc)
Daniel
2009-04-28 10:57:59 +00:00
Mark McLoughlin
a9cc41b082 * Thu Apr 16 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-2.fc11
- Fix qemu drive format specification (#496092)
2009-04-16 15:26:45 +00:00
Jesse Keating
ce1593f88f Initialize branch F-11 for libvirt 2009-04-15 07:13:06 +00:00
41 changed files with 2198 additions and 5223 deletions

View File

@@ -3,3 +3,6 @@
i686
x86_64
libvirt-*.tar.gz
libvirt-0.6.0.tar.gz
libvirt-0.6.1.tar.gz
libvirt-0.6.2.tar.gz

View File

@@ -4,7 +4,7 @@ NAME := libvirt
SPECFILE = $(firstword $(wildcard *.spec))
define find-makefile-common
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
endef
MAKEFILE_COMMON := $(shell $(find-makefile-common))

2
branch
View File

@@ -1 +1 @@
F-13
F-11

View File

@@ -0,0 +1,27 @@
From 934b71abf1b908f720811a44ad5411cfc1a4ca37 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Thu, 28 May 2009 13:15:57 +0000
Subject: [PATCH 1/1] Avoid broken networking with new QEMU/KVM >= 86
---
src/qemu_conf.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 93dc0b7..a04d216 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -658,8 +658,8 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
}
snprintf(tapfdstr, sizeof(tapfdstr),
- "tap,fd=%d,script=,vlan=%d,ifname=%s",
- tapfd, vlan, net->ifname);
+ "tap,fd=%d,vlan=%d",
+ tapfd, vlan);
if (!(retval = strdup(tapfdstr)))
goto no_memory;
--
1.6.0.6

View File

@@ -0,0 +1,48 @@
From 4db7474b0c1907e877d7206edeb4d73962971096 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Tue, 12 May 2009 15:31:22 +0000
Subject: [PATCH 1/1] * src/network_driver.c: enable bridges which are not up
without an IP address, patch by Ludwig Nussel
Daniel
---
src/network_driver.c | 9 +++------
1 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/network_driver.c b/src/network_driver.c
index a17a769..a163b15 100644
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -836,8 +836,7 @@ static int networkStartNetworkDaemon(virConnectPtr conn,
goto err_delbr;
}
- if (network->def->ipAddress &&
- (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
+ if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
virReportSystemError(conn, err,
_("failed to bring the bridge '%s' up"),
network->def->bridge);
@@ -878,8 +877,7 @@ static int networkStartNetworkDaemon(virConnectPtr conn,
networkRemoveIptablesRules(driver, network);
err_delbr1:
- if (network->def->ipAddress &&
- (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
+ if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
char ebuf[1024];
networkLog(NETWORK_WARN, _("Failed to bring down bridge '%s' : %s\n"),
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
@@ -920,8 +918,7 @@ static int networkShutdownNetworkDaemon(virConnectPtr conn,
networkRemoveIptablesRules(driver, network);
char ebuf[1024];
- if (network->def->ipAddress &&
- (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
+ if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
networkLog(NETWORK_WARN, _("Failed to bring down bridge '%s' : %s\n"),
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
}
--
1.6.0.6

View File

@@ -0,0 +1,24 @@
commit 8feb499ba2c3625632210c997b49f5df515c05d4
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Tue Aug 4 18:13:09 2009 +0100
Fix escaping of 8-bit high characters
Fix https://bugzilla.redhat.com/show_bug.cgi?id=479517
* src/buf.c: Cast to 'unsigned char' before doing compare to
avoid rejecting 8-bit high characters
diff --git a/src/buf.c b/src/buf.c
index 259175d..c802aa2 100644
--- a/src/buf.c
+++ b/src/buf.c
@@ -304,7 +304,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
*out++ = 'o';
*out++ = 's';
*out++ = ';';
- } else if ((*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
+ } else if (((unsigned char)*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
(*cur == '\r')) {
/*
* default case, just copy !

View File

@@ -0,0 +1,204 @@
From fbd16cecc72494e8a9450f38197221f2f50c9d0e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
Date: Thu, 16 Apr 2009 15:56:27 +0000
Subject: [PATCH 1/1] Don't log monitor output to domain log file.
It's logged via the logging system already. Prefix monitor debug output with vm
name.
---
src/qemu_driver.c | 60 +++++++++++++++++++++-------------------------------
1 files changed, 24 insertions(+), 36 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 79ee072..f5b5fa5 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1710,27 +1710,11 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
goto error;
}
}
-
- /* Log, but ignore failures to write logfile for VM */
- if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
- char ebuf[1024];
- VIR_WARN(_("Unable to log VM console data: %s\n"),
- virStrerror(errno, ebuf, sizeof ebuf));
- }
-
*reply = buf;
return 0;
error:
- if (buf) {
- /* Log, but ignore failures to write logfile for VM */
- if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
- char ebuf[1024];
- VIR_WARN(_("Unable to log VM console data: %s\n"),
- virStrerror(errno, ebuf, sizeof ebuf));
- }
- VIR_FREE(buf);
- }
+ VIR_FREE(buf);
return -1;
}
@@ -2463,7 +2447,7 @@ static int qemudDomainGetMemoryBalloon(virConnectPtr conn,
goto cleanup;
}
- DEBUG ("balloon reply: '%s'", reply);
+ DEBUG ("%s: balloon reply: '%s'", vm->def->name, reply);
if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) {
unsigned int memMB;
char *end;
@@ -2517,7 +2501,7 @@ static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
/* If the command failed qemu prints: 'unknown command'
* No message is printed on success it seems */
- DEBUG ("balloon reply: %s", reply);
+ DEBUG ("%s: balloon reply: %s",vm->def->name, reply);
if (strstr(reply, "\nunknown command:")) {
/* Don't set error - it is expected memory balloon fails on many qemu */
ret = 0;
@@ -2812,7 +2796,7 @@ static int qemudDomainSave(virDomainPtr dom,
goto cleanup;
}
- DEBUG ("migrate reply: %s", info);
+ DEBUG ("%s: migrate reply: %s", vm->def->name, info);
/* If the command isn't supported then qemu prints:
* unknown command: migrate" */
@@ -3658,7 +3642,7 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
/* If the command failed qemu prints:
* device not found, device is locked ...
* No message is printed on success it seems */
- DEBUG ("ejectable media change reply: %s", reply);
+ DEBUG ("%s: ejectable media change reply: %s", vm->def->name, reply);
if (strstr(reply, "\ndevice ")) {
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("changing cdrom media failed: %s"), reply);
@@ -3719,7 +3703,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
return -1;
}
- DEBUG ("pci_add reply: %s", reply);
+ DEBUG ("%s: pci_add reply: %s", vm->def->name, reply);
/* If the command succeeds qemu prints:
* OK bus 0... */
#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
@@ -3787,7 +3771,7 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
return -1;
}
- DEBUG ("attach_usb reply: %s", reply);
+ DEBUG ("%s: attach_usb reply: %s",vm->def->name, reply);
/* If the command failed qemu prints:
* Could not add ... */
if (strstr(reply, "Could not add ")) {
@@ -3841,7 +3825,7 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
return -1;
}
- DEBUG ("attach_usb reply: %s", reply);
+ DEBUG ("%s: attach_usb reply: %s", vm->def->name, reply);
/* If the command failed qemu prints:
* Could not add ... */
if (strstr(reply, "Could not add ")) {
@@ -3980,7 +3964,7 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
goto cleanup;
}
- DEBUG ("pci_del reply: %s", reply);
+ DEBUG ("%s: pci_del reply: %s",vm->def->name, reply);
/* If the command fails due to a wrong slot qemu prints: invalid slot,
* nothing is printed on success */
if (strstr(reply, "invalid slot")) {
@@ -4210,7 +4194,7 @@ qemudDomainBlockStats (virDomainPtr dom,
"%s", _("'info blockstats' command failed"));
goto cleanup;
}
- DEBUG ("info blockstats reply: %s", info);
+ DEBUG ("%s: info blockstats reply: %s", vm->def->name, info);
/* If the command isn't supported then qemu prints the supported
* info commands, so the output starts "info ". Since this is
@@ -4251,21 +4235,25 @@ qemudDomainBlockStats (virDomainPtr dom,
if (STRPREFIX (p, "rd_bytes=")) {
p += 9;
if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
- DEBUG ("error reading rd_bytes: %s", p);
+ DEBUG ("%s: error reading rd_bytes: %s",
+ vm->def->name, p);
} else if (STRPREFIX (p, "wr_bytes=")) {
p += 9;
if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
- DEBUG ("error reading wr_bytes: %s", p);
+ DEBUG ("%s: error reading wr_bytes: %s",
+ vm->def->name, p);
} else if (STRPREFIX (p, "rd_operations=")) {
p += 14;
if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
- DEBUG ("error reading rd_req: %s", p);
+ DEBUG ("%s: error reading rd_req: %s",
+ vm->def->name, p);
} else if (STRPREFIX (p, "wr_operations=")) {
p += 14;
if (virStrToLong_ll (p, &dummy, 10, &stats->wr_req) == -1)
- DEBUG ("error reading wr_req: %s", p);
+ DEBUG ("%s: error reading wr_req: %s",
+ vm->def->name, p);
} else
- DEBUG ("unknown block stat near %s", p);
+ DEBUG ("%s: unknown block stat near %s", vm->def->name, p);
/* Skip to next label. */
p = strchr (p, ' ');
@@ -4477,7 +4465,7 @@ qemudDomainMemoryPeek (virDomainPtr dom,
goto cleanup;
}
- DEBUG ("memsave reply: %s", info);
+ DEBUG ("%s: memsave reply: %s", vm->def->name, info);
/* Read the memory file into buffer. */
if (saferead (fd, buffer, size) == (ssize_t) -1) {
@@ -4794,7 +4782,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
"%s", _("off-line migration specified, but suspend operation failed"));
goto cleanup;
}
- DEBUG ("stop reply: %s", info);
+ DEBUG ("%s: stop reply: %s", vm->def->name, info);
VIR_FREE(info);
paused = 1;
@@ -4811,7 +4799,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource);
qemudMonitorCommand (vm, cmd, &info);
- DEBUG ("migrate_set_speed reply: %s", info);
+ DEBUG ("%s: migrate_set_speed reply: %s", vm->def->name, info);
VIR_FREE (info);
}
@@ -4830,7 +4818,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
goto cleanup;
}
- DEBUG ("migrate reply: %s", info);
+ DEBUG ("%s: migrate reply: %s", vm->def->name, info);
/* Now check for "fail" in the output string */
if (strstr(info, "fail") != NULL) {
@@ -4869,7 +4857,7 @@ cleanup:
vm->def->name);
}
else {
- DEBUG ("cont reply: %s", info);
+ DEBUG ("%s: cont reply: %s", vm->def->name, info);
VIR_FREE(info);
}
--
1.6.0.6

View File

@@ -0,0 +1,47 @@
From ae4523336ac06e3ff7cc7b416fad9e57998c6b54 Mon Sep 17 00:00:00 2001
From: Tim Waugh <twaugh@redhat.com>
Date: Fri, 3 Jul 2009 10:29:01 +0100
Subject: [PATCH 2/3] Don't unnecessarily try to change a file context
As pointed out by Tim Waugh here:
https://bugzilla.redhat.com/507555
We shouldn't bother trying to set the context of a file if it already
matches what we want.
(Fixed to use STREQ() and not use tabs, as pointed out by danpb)
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
src/security_selinux.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/src/security_selinux.c b/src/security_selinux.c
index db1c27d..c2015a1 100644
--- a/src/security_selinux.c
+++ b/src/security_selinux.c
@@ -280,10 +280,19 @@ static int
SELinuxSetFilecon(virConnectPtr conn, const char *path, char *tcon)
{
char ebuf[1024];
+ security_context_t econ;
VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
- if(setfilecon(path, tcon) < 0) {
+ if (setfilecon(path, tcon) < 0) {
+ if (getfilecon(path, &econ) >= 0) {
+ if (STREQ(tcon, econ)) {
+ freecon(econ);
+ /* It's alright, there's nothing to change anyway. */
+ return 0;
+ }
+ freecon(econ);
+ }
virSecurityReportError(conn, VIR_ERR_ERROR,
_("%s: unable to set security context "
"'\%s\' on %s: %s."), __func__,
--
1.6.2.5

View File

@@ -0,0 +1,45 @@
From: "Daniel P. Berrange" <berrange@redhat.com>
To: libvir-list@redhat.com
Date: Thu, 30 Apr 2009 15:09:05 +0100
Subject: [libvirt] PATCH: Enable migration with QEMU >= 0.10.0
The KVM migration code was added to QEMU for the 0.10.0 release, so we
should enable this in libvirt now.
Daniel
diff -r be7993675e07 src/qemu_conf.c
--- a/src/qemu_conf.c Thu Apr 30 14:49:27 2009 +0100
+++ b/src/qemu_conf.c Thu Apr 30 15:08:45 2009 +0100
@@ -472,16 +472,13 @@ int qemudExtractVersionInfo(const char *
/*
* Handling of -incoming arg with varying features
- * -incoming tcp (kvm >= 79)
- * -incoming exec (kvm >= 80)
+ * -incoming tcp (kvm >= 79, qemu >= 0.10.0)
+ * -incoming exec (kvm >= 80, qemu >= 0.10.0)
* -incoming stdio (all earlier kvm)
*
* NB, there was a pre-kvm-79 'tcp' support, but it
* was broken, because it blocked the monitor console
* while waiting for data, so pretend it doesn't exist
- *
- * XXX when next QEMU release after 0.9.1 arrives,
- * we'll need to add MIGRATE_QEMU_TCP/EXEC here too
*/
if (kvm_version >= 79) {
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
@@ -489,6 +486,9 @@ int qemudExtractVersionInfo(const char *
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
} else if (kvm_version > 0) {
flags |= QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO;
+ } else if (version >= 10000) {
+ flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
+ flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
}
if (retversion)
--

View File

@@ -0,0 +1,144 @@
From e7be6cc841a5652b73ddd2ccd3769c7f8bbad13d Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 12 May 2009 16:41:49 +0000
Subject: [PATCH 1/2] Fix interrupting of main event thread & protect against accidental uniniitalized variables
---
qemud/event.c | 42 +++++++++++++++++++++++++++++++++++-------
1 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/qemud/event.c b/qemud/event.c
index 65f548e..754f2b1 100644
--- a/qemud/event.c
+++ b/qemud/event.c
@@ -84,10 +84,10 @@ struct virEventLoop {
static struct virEventLoop eventLoop;
/* Unique ID for the next FD watch to be registered */
-static int nextWatch = 0;
+static int nextWatch = 1;
/* Unique ID for the next timer to be registered */
-static int nextTimer = 0;
+static int nextTimer = 1;
static void virEventLock(void)
{
@@ -143,15 +143,22 @@ int virEventAddHandleImpl(int fd, int events,
void virEventUpdateHandleImpl(int watch, int events) {
int i;
+ EVENT_DEBUG("Update handle w=%d e=%d", watch, events);
+
+ if (watch <= 0) {
+ VIR_WARN("Ignoring invalid update watch %d", watch);
+ return;
+ }
+
virEventLock();
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].watch == watch) {
eventLoop.handles[i].events =
virEventHandleTypeToPollEvent(events);
+ virEventInterruptLocked();
break;
}
}
- virEventInterruptLocked();
virEventUnlock();
}
@@ -164,6 +171,12 @@ void virEventUpdateHandleImpl(int watch, int events) {
int virEventRemoveHandleImpl(int watch) {
int i;
EVENT_DEBUG("Remove handle %d", watch);
+
+ if (watch <= 0) {
+ VIR_WARN("Ignoring invalid remove watch %d", watch);
+ return -1;
+ }
+
virEventLock();
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].deleted)
@@ -172,11 +185,11 @@ int virEventRemoveHandleImpl(int watch) {
if (eventLoop.handles[i].watch == watch) {
EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
eventLoop.handles[i].deleted = 1;
+ virEventInterruptLocked();
virEventUnlock();
return 0;
}
}
- virEventInterruptLocked();
virEventUnlock();
return -1;
}
@@ -232,6 +245,12 @@ void virEventUpdateTimeoutImpl(int timer, int frequency) {
struct timeval tv;
int i;
EVENT_DEBUG("Updating timer %d timeout with %d ms freq", timer, frequency);
+
+ if (timer <= 0) {
+ VIR_WARN("Ignoring invalid update timer %d", timer);
+ return;
+ }
+
if (gettimeofday(&tv, NULL) < 0) {
return;
}
@@ -244,10 +263,10 @@ void virEventUpdateTimeoutImpl(int timer, int frequency) {
frequency >= 0 ? frequency +
(((unsigned long long)tv.tv_sec)*1000) +
(((unsigned long long)tv.tv_usec)/1000) : 0;
+ virEventInterruptLocked();
break;
}
}
- virEventInterruptLocked();
virEventUnlock();
}
@@ -260,6 +279,12 @@ void virEventUpdateTimeoutImpl(int timer, int frequency) {
int virEventRemoveTimeoutImpl(int timer) {
int i;
EVENT_DEBUG("Remove timer %d", timer);
+
+ if (timer <= 0) {
+ VIR_WARN("Ignoring invalid remove timer %d", timer);
+ return -1;
+ }
+
virEventLock();
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
if (eventLoop.timeouts[i].deleted)
@@ -267,11 +292,11 @@ int virEventRemoveTimeoutImpl(int timer) {
if (eventLoop.timeouts[i].timer == timer) {
eventLoop.timeouts[i].deleted = 1;
+ virEventInterruptLocked();
virEventUnlock();
return 0;
}
}
- virEventInterruptLocked();
virEventUnlock();
return -1;
}
@@ -617,9 +642,12 @@ static int virEventInterruptLocked(void)
char c = '\0';
if (!eventLoop.running ||
- pthread_self() == eventLoop.leader)
+ pthread_self() == eventLoop.leader) {
+ VIR_DEBUG("Skip interrupt, %d %d", eventLoop.running, (int)eventLoop.leader);
return 0;
+ }
+ VIR_DEBUG0("Interrupting");
if (safewrite(eventLoop.wakeupfd[1], &c, sizeof(c)) != sizeof(c))
return -1;
return 0;
--
1.6.0.6

View File

@@ -0,0 +1,197 @@
From 6483ee77ed12f037d68a6adc690624fa1b508dc0 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 12 May 2009 16:43:04 +0000
Subject: [PATCH 2/2] Fix watch/timer event deletion
---
qemud/event.c | 112 ++++++++++++++++++++++++++-------------------------------
1 files changed, 51 insertions(+), 61 deletions(-)
diff --git a/qemud/event.c b/qemud/event.c
index 754f2b1..a57d967 100644
--- a/qemud/event.c
+++ b/qemud/event.c
@@ -313,7 +313,7 @@ static int virEventCalculateTimeout(int *timeout) {
EVENT_DEBUG("Calculate expiry of %d timers", eventLoop.timeoutsCount);
/* Figure out if we need a timeout */
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
- if (eventLoop.timeouts[i].deleted || eventLoop.timeouts[i].frequency < 0)
+ if (eventLoop.timeouts[i].frequency < 0)
continue;
EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt);
@@ -350,32 +350,26 @@ static int virEventCalculateTimeout(int *timeout) {
* file handles. The caller must free the returned data struct
* returns: the pollfd array, or NULL on error
*/
-static int virEventMakePollFDs(struct pollfd **retfds) {
+static struct pollfd *virEventMakePollFDs(void) {
struct pollfd *fds;
- int i, nfds = 0;
+ int i;
- for (i = 0 ; i < eventLoop.handlesCount ; i++) {
- if (eventLoop.handles[i].deleted)
- continue;
- nfds++;
- }
- *retfds = NULL;
/* Setup the poll file handle data structs */
- if (VIR_ALLOC_N(fds, nfds) < 0)
- return -1;
+ if (VIR_ALLOC_N(fds, eventLoop.handlesCount) < 0)
+ return NULL;
- for (i = 0, nfds = 0 ; i < eventLoop.handlesCount ; i++) {
- if (eventLoop.handles[i].deleted)
- continue;
- fds[nfds].fd = eventLoop.handles[i].fd;
- fds[nfds].events = eventLoop.handles[i].events;
- fds[nfds].revents = 0;
+ for (i = 0 ; i < eventLoop.handlesCount ; i++) {
+ EVENT_DEBUG("Prepare n=%d w=%d, f=%d e=%d", i,
+ eventLoop.handles[i].watch,
+ eventLoop.handles[i].fd,
+ eventLoop.handles[i].events);
+ fds[i].fd = eventLoop.handles[i].fd;
+ fds[i].events = eventLoop.handles[i].events;
+ fds[i].revents = 0;
//EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events);
- nfds++;
}
- *retfds = fds;
- return nfds;
+ return fds;
}
@@ -435,26 +429,30 @@ static int virEventDispatchTimeouts(void) {
* Returns 0 upon success, -1 if an error occurred
*/
static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
- int i, n;
+ int i;
- for (i = 0, n = 0 ; i < eventLoop.handlesCount && n < nfds ; i++) {
+ /* NB, use nfds not eventLoop.handlesCount, because new
+ * fds might be added on end of list, and they're not
+ * in the fds array we've got */
+ for (i = 0 ; i < nfds ; i++) {
if (eventLoop.handles[i].deleted) {
- EVENT_DEBUG("Skip deleted %d", eventLoop.handles[i].fd);
+ EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i,
+ eventLoop.handles[i].watch, eventLoop.handles[i].fd);
continue;
}
- if (fds[n].revents) {
+ if (fds[i].revents) {
virEventHandleCallback cb = eventLoop.handles[i].cb;
void *opaque = eventLoop.handles[i].opaque;
- int hEvents = virPollEventToEventHandleType(fds[n].revents);
- EVENT_DEBUG("Dispatch %d %d %p", fds[n].fd,
- fds[n].revents, eventLoop.handles[i].opaque);
+ int hEvents = virPollEventToEventHandleType(fds[i].revents);
+ EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
+ fds[i].fd, eventLoop.handles[i].watch,
+ fds[i].revents, eventLoop.handles[i].opaque);
virEventUnlock();
(cb)(eventLoop.handles[i].watch,
- fds[n].fd, hEvents, opaque);
+ fds[i].fd, hEvents, opaque);
virEventLock();
}
- n++;
}
return 0;
@@ -545,22 +543,21 @@ static int virEventCleanupHandles(void) {
* at least one file handle has an event, or a timer expires
*/
int virEventRunOnce(void) {
- struct pollfd *fds;
+ struct pollfd *fds = NULL;
int ret, timeout, nfds;
virEventLock();
eventLoop.running = 1;
eventLoop.leader = pthread_self();
- if ((nfds = virEventMakePollFDs(&fds)) < 0) {
- virEventUnlock();
- return -1;
- }
- if (virEventCalculateTimeout(&timeout) < 0) {
- VIR_FREE(fds);
- virEventUnlock();
- return -1;
- }
+ if (virEventCleanupTimeouts() < 0 ||
+ virEventCleanupHandles() < 0)
+ goto error;
+
+ if (!(fds = virEventMakePollFDs()) ||
+ virEventCalculateTimeout(&timeout) < 0)
+ goto error;
+ nfds = eventLoop.handlesCount;
virEventUnlock();
@@ -572,38 +569,31 @@ int virEventRunOnce(void) {
if (errno == EINTR) {
goto retry;
}
- VIR_FREE(fds);
- return -1;
+ goto error_unlocked;
}
virEventLock();
- if (virEventDispatchTimeouts() < 0) {
- VIR_FREE(fds);
- virEventUnlock();
- return -1;
- }
+ if (virEventDispatchTimeouts() < 0)
+ goto error;
if (ret > 0 &&
- virEventDispatchHandles(nfds, fds) < 0) {
- VIR_FREE(fds);
- virEventUnlock();
- return -1;
- }
- VIR_FREE(fds);
-
- if (virEventCleanupTimeouts() < 0) {
- virEventUnlock();
- return -1;
- }
+ virEventDispatchHandles(nfds, fds) < 0)
+ goto error;
- if (virEventCleanupHandles() < 0) {
- virEventUnlock();
- return -1;
- }
+ if (virEventCleanupTimeouts() < 0 ||
+ virEventCleanupHandles() < 0)
+ goto error;
eventLoop.running = 0;
virEventUnlock();
+ VIR_FREE(fds);
return 0;
+
+error:
+ virEventUnlock();
+error_unlocked:
+ VIR_FREE(fds);
+ return -1;
}
static void virEventHandleWakeup(int watch ATTRIBUTE_UNUSED,
--
1.6.0.6

View File

@@ -0,0 +1,130 @@
From 80965bff6d46dea1808c8bbf02f50f0e289a0e65 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 29 Jun 2009 10:41:56 +0000
Subject: [PATCH] Fix crash in QEMU driver with bad capabilities data
---
src/qemu_driver.c | 80 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 54 insertions(+), 26 deletions(-)
diff -up libvirt-0.6.2/src/qemu_driver.c.bad-caps libvirt-0.6.2/src/qemu_driver.c
--- libvirt-0.6.2/src/qemu_driver.c.bad-caps 2009-07-03 10:07:03.275252815 +0100
+++ libvirt-0.6.2/src/qemu_driver.c 2009-07-03 10:08:52.143502961 +0100
@@ -360,12 +360,43 @@ next:
return 0;
}
+
+static int
+qemudSecurityCapsInit(virSecurityDriverPtr secdrv,
+ virCapsPtr caps)
+{
+ const char *doi, *model;
+
+ doi = virSecurityDriverGetDOI(secdrv);
+ model = virSecurityDriverGetModel(secdrv);
+
+ caps->host.secModel.model = strdup(model);
+ if (!caps->host.secModel.model) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to copy secModel model: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ return -1;
+ }
+
+ caps->host.secModel.doi = strdup(doi);
+ if (!caps->host.secModel.doi) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to copy secModel DOI: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ return -1;
+ }
+
+ VIR_DEBUG("Initialized caps for security driver \"%s\" with "
+ "DOI \"%s\"", model, doi);
+
+ return 0;
+}
+
+
static int
qemudSecurityInit(struct qemud_driver *qemud_drv)
{
int ret;
- const char *doi, *model;
- virCapsPtr caps;
virSecurityDriverPtr security_drv;
ret = virSecurityDriverStartup(&security_drv,
@@ -381,36 +412,17 @@ qemudSecurityInit(struct qemud_driver *q
}
qemud_drv->securityDriver = security_drv;
- doi = virSecurityDriverGetDOI(security_drv);
- model = virSecurityDriverGetModel(security_drv);
- VIR_DEBUG("Initialized security driver \"%s\" with "
- "DOI \"%s\"", model, doi);
+ VIR_INFO("Initialized security driver %s", security_drv->name);
/*
* Add security policy host caps now that the security driver is
* initialized.
*/
- caps = qemud_drv->caps;
-
- caps->host.secModel.model = strdup(model);
- if (!caps->host.secModel.model) {
- char ebuf[1024];
- VIR_ERROR(_("Failed to copy secModel model: %s"),
- virStrerror(errno, ebuf, sizeof ebuf));
- return -1;
- }
+ return qemudSecurityCapsInit(security_drv, qemud_drv->caps);
+}
- caps->host.secModel.doi = strdup(doi);
- if (!caps->host.secModel.doi) {
- char ebuf[1024];
- VIR_ERROR(_("Failed to copy secModel DOI: %s"),
- virStrerror(errno, ebuf, sizeof ebuf));
- return -1;
- }
- return 0;
-}
/**
* qemudStartup:
@@ -1852,13 +1864,29 @@ static int qemudGetNodeInfo(virConnectPt
static char *qemudGetCapabilities(virConnectPtr conn) {
struct qemud_driver *driver = conn->privateData;
+ virCapsPtr caps;
char *xml = NULL;
qemuDriverLock(driver);
+ if ((caps = qemudCapsInit()) == NULL) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
+ if (qemu_driver->securityDriver &&
+ qemudSecurityCapsInit(qemu_driver->securityDriver, caps) < 0) {
+ virCapabilitiesFree(caps);
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
virCapabilitiesFree(qemu_driver->caps);
- if ((qemu_driver->caps = qemudCapsInit()) == NULL ||
- (xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
+ qemu_driver->caps = caps;
+
+ if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
virReportOOMError(conn);
+
+cleanup:
qemuDriverUnlock(driver);
return xml;

View File

@@ -0,0 +1,13 @@
diff -rup libvirt-0.6.2/src/security_selinux.c new/src/security_selinux.c
--- libvirt-0.6.2/src/security_selinux.c 2009-05-10 22:04:25.000000000 -0400
+++ new/src/security_selinux.c 2009-05-10 22:06:09.000000000 -0400
@@ -338,6 +338,9 @@ SELinuxSetSecurityImageLabel(virConnectP
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+ if (!disk->src)
+ return 0;
+
if (disk->shared) {
return SELinuxSetFilecon(conn, disk->src, default_image_context);
} else if (disk->readonly) {

View File

@@ -0,0 +1,82 @@
From 2b3fcdc378e7bec5c1a78b81632756e92930fd24 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 11 May 2009 15:14:24 +0000
Subject: [PATCH 1/1] Fix QEMU ARGV detection with kvm >= 85
---
src/qemu_conf.c | 18 ++++++++++++++----
src/qemu_driver.c | 12 ++----------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 9cb71eb..a57d3ab 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -431,18 +431,28 @@ int qemudExtractVersionInfo(const char *qemu,
return -1;
char *help = NULL;
- enum { MAX_HELP_OUTPUT_SIZE = 8192 };
+ enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
- if (len < 0)
+ if (len < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("Unable to read QEMU help output"));
goto cleanup2;
+ }
if (sscanf(help, "QEMU PC emulator version %u.%u.%u (kvm-%u)",
&major, &minor, &micro, &kvm_version) != 4)
kvm_version = 0;
- if (!kvm_version && sscanf(help, "QEMU PC emulator version %u.%u.%u",
- &major, &minor, &micro) != 3)
+ if (!kvm_version &&
+ sscanf(help, "QEMU PC emulator version %u.%u.%u",
+ &major, &minor, &micro) != 3) {
+ char *eol = strchr(help, '\n');
+ if (eol) *eol = '\0';
+ qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse QEMU version number in '%s'"),
+ help);
goto cleanup2;
+ }
version = (major * 1000 * 1000) + (minor * 1000) + micro;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 30642d5..bd60b29 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1391,12 +1391,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (qemudExtractVersionInfo(emulator,
NULL,
- &qemuCmdFlags) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Cannot determine QEMU argv syntax %s"),
- emulator);
+ &qemuCmdFlags) < 0)
goto cleanup;
- }
if (qemuPrepareHostDevices(conn, vm->def) < 0)
goto cleanup;
@@ -3715,12 +3711,8 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
if (qemudExtractVersionInfo(vm->def->emulator,
NULL,
- &qemuCmdFlags) < 0) {
- qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Cannot determine QEMU argv syntax %s"),
- vm->def->emulator);
+ &qemuCmdFlags) < 0)
return -1;
- }
if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
if (!(devname = qemudDiskDeviceName(conn, newdisk)))
--
1.6.0.6

View File

@@ -0,0 +1,37 @@
commit 1795bfe4a177a5eff1b3b0a16d56df6f371c0f8e
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Mon Jul 6 16:01:55 2009 +0100
Fix SELinux denial during hotplug
* src/qemu_driver.c: Relabel disk images *before* running QEMU
hotplug monitor commands
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 5a0ab12..342ba01 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4225,10 +4225,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+ if (driver->securityDriver)
+ driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev);
break;
case VIR_DOMAIN_DISK_DEVICE_DISK:
+ if (driver->securityDriver)
+ driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev);
} else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
@@ -4240,8 +4244,6 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
virDomainDiskBusTypeToString(dev->data.disk->bus));
goto cleanup;
}
- if (driver->securityDriver)
- driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
break;
default:

View File

@@ -0,0 +1,125 @@
commit 326ecb78145cfeb7706ef0dcd521b19d934950e7
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Mon Jul 6 15:58:55 2009 +0100
Fix PCI device hotplug/unplug with newer QEMU
* src/qemu_driver.c: Try new monitor syntax for hotplug first. If
that fails fallback to old KVM specific syntax
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 2e55045..5a0ab12 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4004,6 +4004,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
char *cmd, *reply, *s;
char *safe_path;
const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
+ int tryOldSyntax = 0;
for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
@@ -4018,14 +4019,15 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
return -1;
}
+try_command:
safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
if (!safe_path) {
virReportOOMError(conn);
return -1;
}
- ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
- safe_path, type);
+ ret = virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
+ (tryOldSyntax ? "0": "pci_addr=auto"), safe_path, type);
VIR_FREE(safe_path);
if (ret == -1) {
virReportOOMError(conn);
@@ -4041,17 +4043,27 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
DEBUG ("%s: pci_add reply: %s", vm->def->name, reply);
/* If the command succeeds qemu prints:
- * OK bus 0... */
-#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
- if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
- char* dummy = s;
- s += strlen(PCI_ATTACH_OK_MSG);
+ * OK bus 0, slot XXX...
+ * or
+ * OK domain 0, bus 0, slot XXX
+ */
+ if ((s = strstr(reply, "OK ")) &&
+ (s = strstr(s, "slot "))) {
+ char *dummy = s;
+ s += strlen("slot ");
if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
VIR_WARN("%s", _("Unable to parse slot number\n"));
+ /* XXX not neccessarily always going to end up in domain 0 / bus 0 :-( */
+ /* XXX this slotnum is not persistant across restarts :-( */
+ } else if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
+ VIR_FREE(reply);
+ VIR_FREE(cmd);
+ tryOldSyntax = 1;
+ goto try_command;
} else {
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
- _("adding %s disk failed"), type);
+ _("adding %s disk failed: %s"), type, reply);
VIR_FREE(reply);
VIR_FREE(cmd);
return -1;
@@ -4268,6 +4280,7 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
char *cmd = NULL;
char *reply = NULL;
virDomainDiskDefPtr detach = NULL;
+ int tryOldSyntax = 0;
for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
@@ -4289,9 +4302,17 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
goto cleanup;
}
- if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
- virReportOOMError(conn);
- goto cleanup;
+try_command:
+ if (tryOldSyntax) {
+ if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&cmd, "pci_del pci_addr=0:0:%d", detach->slotnum) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
}
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
@@ -4301,12 +4322,19 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
}
DEBUG ("%s: pci_del reply: %s",vm->def->name, reply);
+
+ if (!tryOldSyntax &&
+ strstr(reply, "extraneous characters")) {
+ tryOldSyntax = 1;
+ goto try_command;
+ }
/* If the command fails due to a wrong slot qemu prints: invalid slot,
* nothing is printed on success */
- if (strstr(reply, "invalid slot")) {
+ if (strstr(reply, "invalid slot") ||
+ strstr(reply, "Invalid pci address")) {
qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
- _("failed to detach disk %s: invalid slot %d"),
- detach->dst, detach->slotnum);
+ _("failed to detach disk %s: invalid slot %d: %s"),
+ detach->dst, detach->slotnum, reply);
goto cleanup;
}

View File

@@ -0,0 +1,54 @@
From c3b3f6005d45552d01823504925eb587889cf25a Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Fri, 29 May 2009 14:34:35 +0000
Subject: [PATCH 1/1] Avoid double-free in daemon client cleanup code
---
qemud/qemud.c | 22 +++++++++++++++++-----
1 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/qemud/qemud.c b/qemud/qemud.c
index 1375560..783dc69 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -1397,7 +1397,10 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
* jobs have finished, then clean it up elsehwere
*/
void qemudDispatchClientFailure(struct qemud_client *client) {
- virEventRemoveHandleImpl(client->watch);
+ if (client->watch != -1) {
+ virEventRemoveHandleImpl(client->watch);
+ client->watch = -1;
+ }
/* Deregister event delivery callback */
if(client->conn) {
@@ -1406,12 +1406,21 @@ void qemudDispatchClientFailure(struct qemud_client *client) {
}
#if HAVE_SASL
- if (client->saslconn) sasl_dispose(&client->saslconn);
+ if (client->saslconn) {
+ sasl_dispose(&client->saslconn);
+ client->saslconn = NULL;
+ }
free(client->saslUsername);
+ client->saslUsername = NULL;
#endif
- if (client->tlssession) gnutls_deinit (client->tlssession);
- close(client->fd);
- client->fd = -1;
+ if (client->tlssession) {
+ gnutls_deinit (client->tlssession);
+ client->tlssession = NULL;
+ }
+ if (client->fd != -1) {
+ close(client->fd);
+ client->fd = -1;
+ }
}
--
1.6.0.6

View File

@@ -0,0 +1,52 @@
commit 2d1f2e706c8b13571e1227df1c69b2302da35d5a
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Mon Jul 6 15:45:04 2009 +0100
Fix problem with QEMU monitor welcome prompt confusing libvirt
after a libvirtd daemon restart with active guests
* src/qemu_driver: Read and dicard pending monitor data
before issuing new monitor commands.
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index e2b7acb..2e55045 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1744,6 +1744,28 @@ cleanup:
qemuDriverUnlock(driver);
}
+
+/* Throw away any data available on the monitor
+ * This is done before executing a command, in order
+ * to allow re-synchronization if something went badly
+ * wrong in the past. it also deals with problem of
+ * QEMU *sometimes* re-printing its initial greeting
+ * when we reconnect to the monitor after restarts.
+ */
+static void
+qemuMonitorDiscardPendingData(virDomainObjPtr vm) {
+ char buf[1024];
+ int ret = 0;
+
+ /* Monitor is non-blocking, so just loop till we
+ * get -1 or 0. Don't bother with detecting
+ * errors, since we'll deal with that better later */
+ do {
+ ret = read(vm->monitor, buf, sizeof (buf)-1);
+ } while (ret > 0);
+}
+
+
static int
qemudMonitorCommandExtra(const virDomainObjPtr vm,
const char *cmd,
@@ -1755,6 +1777,8 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
size_t cmdlen = strlen(cmd);
size_t extralen = extra ? strlen(extra) : 0;
+ qemuMonitorDiscardPendingData(vm);
+
if (safewrite(vm->monitor, cmd, cmdlen) != cmdlen)
return -1;
if (safewrite(vm->monitor, "\r", 1) != 1)

View File

@@ -0,0 +1,22 @@
commit 4a7acedd3c59a6a750576cb8680bc3f08fe0b52c
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Thu Jul 16 13:23:32 2009 +0100
Fix free of unitialized data upon PCI open fail
diff --git a/src/pci.c b/src/pci.c
index 3ffa0aa..4030a14 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -834,10 +834,8 @@ pciReadDeviceID(pciDevice *dev, const char *id_name)
dev->name, id_name);
/* ID string is '0xNNNN\n' ... i.e. 7 bytes */
- if (virFileReadAll(path, 7, &id_str) < 7) {
- VIR_FREE(id_str);
+ if (virFileReadAll(path, 7, &id_str) < 0)
return NULL;
- }
/* Check for 0x suffix */
if (id_str[0] != '0' || id_str[1] != 'x') {

View File

@@ -0,0 +1,26 @@
From 0ae4c67ff5f1d24698c5cfc8a9719d333c892644 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Thu, 16 Apr 2009 11:23:55 +0100
Subject: [PATCH 1/3] qemu -drive takes format= not fmt=
Seems like a simple typo - it has been "format=" since the flag
was introduced, but we added it as "fmt=".
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
src/qemu_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index f36c927..6f9e610 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -1135,7 +1135,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
virBufferAddLit(&opt, ",boot=on");
if (disk->driverType)
- virBufferVSprintf(&opt, ",fmt=%s", disk->driverType);
+ virBufferVSprintf(&opt, ",format=%s", disk->driverType);
if (disk->cachemode) {
const char *mode =

View File

@@ -0,0 +1,160 @@
diff -rupN libvirt-0.6.2/src/qemu_driver.c libvirt-0.6.2.new/src/qemu_driver.c
--- libvirt-0.6.2/src/qemu_driver.c 2009-08-05 16:25:22.000000000 +0100
+++ libvirt-0.6.2.new/src/qemu_driver.c 2009-08-05 16:27:48.000000000 +0100
@@ -2174,22 +2174,37 @@ static virDomainPtr qemudDomainCreate(vi
if (virSecurityDriverVerify(conn, def) < 0)
goto cleanup;
- vm = virDomainFindByName(&driver->domains, def->name);
- if (vm) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
- _("domain '%s' is already defined"),
- def->name);
- goto cleanup;
- }
+ /* See if a VM with matching UUID already exists */
vm = virDomainFindByUUID(&driver->domains, def->uuid);
if (vm) {
- char uuidstr[VIR_UUID_STRING_BUFLEN];
+ /* UUID matches, but if names don't match, refuse it */
+ if (STRNEQ(vm->def->name, def->name)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ vm->def->name, uuidstr);
+ goto cleanup;
+ }
- virUUIDFormat(def->uuid, uuidstr);
- qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
- _("domain with uuid '%s' is already defined"),
- uuidstr);
- goto cleanup;
+ /* UUID & name match, but if VM is already active, refuse it */
+ if (virDomainIsActive(vm)) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain is already active as '%s'"), vm->def->name);
+ goto cleanup;
+ }
+ virDomainObjUnlock(vm);
+ } else {
+ /* UUID does not match, but if a name matches, refuse it */
+ vm = virDomainFindByName(&driver->domains, def->name);
+ if (vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ def->name, uuidstr);
+ goto cleanup;
+ }
}
if (!(vm = virDomainAssignDef(conn,
@@ -2368,6 +2383,11 @@ static int qemudDomainDestroy(virDomainP
_("no domain with matching id %d"), dom->id);
goto cleanup;
}
+ if (!virDomainIsActive(vm)) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
qemudShutdownVMDaemon(dom->conn, driver, vm);
event = virDomainEventNewFromObj(vm,
@@ -3272,17 +3292,36 @@ static int qemudDomainRestore(virConnect
goto cleanup;
}
- /* Ensure the name and UUID don't already exist in an active VM */
+ /* See if a VM with matching UUID already exists */
vm = virDomainFindByUUID(&driver->domains, def->uuid);
- if (!vm)
- vm = virDomainFindByName(&driver->domains, def->name);
if (vm) {
+ /* UUID matches, but if names don't match, refuse it */
+ if (STRNEQ(vm->def->name, def->name)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ vm->def->name, uuidstr);
+ goto cleanup;
+ }
+
+ /* UUID & name match, but if VM is already active, refuse it */
if (virDomainIsActive(vm)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain is already active as '%s'"), vm->def->name);
goto cleanup;
- } else {
- virDomainObjUnlock(vm);
+ }
+ virDomainObjUnlock(vm);
+ } else {
+ /* UUID does not match, but if a name matches, refuse it */
+ vm = virDomainFindByName(&driver->domains, def->name);
+ if (vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ def->name, uuidstr);
+ goto cleanup;
}
}
@@ -3470,18 +3509,41 @@ static virDomainPtr qemudDomainDefine(vi
if (virSecurityDriverVerify(conn, def) < 0)
goto cleanup;
- vm = virDomainFindByName(&driver->domains, def->name);
+ /* See if a VM with matching UUID already exists */
+ vm = virDomainFindByUUID(&driver->domains, def->uuid);
if (vm) {
+ /* UUID matches, but if names don't match, refuse it */
+ if (STRNEQ(vm->def->name, def->name)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ vm->def->name, uuidstr);
+ goto cleanup;
+ }
+
+ /* UUID & name match */
virDomainObjUnlock(vm);
newVM = 0;
+ } else {
+ /* UUID does not match, but if a name matches, refuse it */
+ vm = virDomainFindByName(&driver->domains, def->name);
+ if (vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ def->name, uuidstr);
+ goto cleanup;
+ }
}
if (!(vm = virDomainAssignDef(conn,
&driver->domains,
def))) {
- virDomainDefFree(def);
goto cleanup;
}
+ def = NULL;
vm->persistent = 1;
if (virDomainSaveConfig(conn,
@@ -3503,6 +3565,7 @@ static virDomainPtr qemudDomainDefine(vi
if (dom) dom->id = vm->def->id;
cleanup:
+ virDomainDefFree(def);
if (vm)
virDomainObjUnlock(vm);
if (event)

View File

@@ -0,0 +1,57 @@
From daf3db93457427c25325781af684758c0341a6aa Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Fri, 29 May 2009 13:32:06 +0000
Subject: [PATCH 1/1] PPC Qemu Machine Type update
* src/qemu_conf.c docs/schemas/domain.rng
tests/capabilityschemadata/caps-qemu-kvm.xml: PPC Qemu Machine Type
changed from g3bw to g3beige some time ago, patch by Thomas Baker
Daniel
---
docs/schemas/domain.rng | 2 +-
src/qemu_conf.c | 2 +-
tests/capabilityschemadata/caps-qemu-kvm.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 204c633..11cf04a 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -184,7 +184,7 @@
</attribute>
<attribute name="machine">
<choice>
- <value>g3bw</value>
+ <value>g3beige</value>
<value>mac99</value>
<value>prep</value>
</choice>
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 18156cd..d54f2ca 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -192,7 +192,7 @@ static const char *const arch_info_hvm_sparc_machines[] = {
"sun4m"
};
static const char *const arch_info_hvm_ppc_machines[] = {
- "g3bw", "mac99", "prep"
+ "g3beige", "mac99", "prep"
};
static const char *const arch_info_xen_x86_machines[] = {
diff --git a/tests/capabilityschemadata/caps-qemu-kvm.xml b/tests/capabilityschemadata/caps-qemu-kvm.xml
index fd8523e..893f9ed 100644
--- a/tests/capabilityschemadata/caps-qemu-kvm.xml
+++ b/tests/capabilityschemadata/caps-qemu-kvm.xml
@@ -81,7 +81,7 @@
<arch name='ppc'>
<wordsize>32</wordsize>
<emulator>/usr/bin/qemu-system-ppc</emulator>
- <machine>g3bw</machine>
+ <machine>g3beige</machine>
<machine>mac99</machine>
<machine>prep</machine>
<domain type='qemu'>
--
1.6.0.6

View File

@@ -0,0 +1,76 @@
diff -rup libvirt-0.6.2/src/security_selinux.c libvirt-0.6.2.new/src/security_selinux.c
--- libvirt-0.6.2/src/security_selinux.c 2009-04-03 15:36:56.000000000 +0100
+++ libvirt-0.6.2.new/src/security_selinux.c 2009-05-05 13:39:42.000000000 +0100
@@ -24,11 +24,12 @@
#include "virterror_internal.h"
#include "util.h"
#include "memory.h"
-
+#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
static char default_domain_context[1024];
+static char default_content_context[1024];
static char default_image_context[1024];
#define SECURITY_SELINUX_VOID_DOI "0"
#define SECURITY_SELINUX_NAME "selinux"
@@ -148,8 +149,13 @@ SELinuxInitialize(virConnectPtr conn)
close(fd);
ptr = strchrnul(default_image_context, '\n');
- *ptr = '\0';
-
+ if (*ptr == '\n') {
+ *ptr = '\0';
+ strcpy(default_content_context, ptr+1);
+ ptr = strchrnul(default_content_context, '\n');
+ if (*ptr == '\n')
+ *ptr = '\0';
+ }
return 0;
}
@@ -275,6 +281,8 @@ SELinuxSetFilecon(virConnectPtr conn, co
{
char ebuf[1024];
+ VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
+
if(setfilecon(path, tcon) < 0) {
virSecurityReportError(conn, VIR_ERR_ERROR,
_("%s: unable to set security context "
@@ -299,6 +307,8 @@ SELinuxRestoreSecurityImageLabel(virConn
char *newpath = NULL;
const char *path = disk->src;
+ /* Don't restore labels on readoly/shared disks, because
+ * other VMs may still be accessing these */
if (disk->readonly || disk->shared)
return 0;
@@ -328,8 +338,13 @@ SELinuxSetSecurityImageLabel(virConnectP
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
- if (secdef->imagelabel)
+ if (disk->shared) {
+ return SELinuxSetFilecon(conn, disk->src, default_image_context);
+ } else if (disk->readonly) {
+ return SELinuxSetFilecon(conn, disk->src, default_content_context);
+ } else if (secdef->imagelabel) {
return SELinuxSetFilecon(conn, disk->src, secdef->imagelabel);
+ }
return 0;
}
@@ -403,9 +418,6 @@ SELinuxSetSecurityLabel(virConnectPtr co
if (secdef->imagelabel) {
for (i = 0 ; i < vm->def->ndisks ; i++) {
- if (vm->def->disks[i]->readonly ||
- vm->def->disks[i]->shared) continue;
-
if (SELinuxSetSecurityImageLabel(conn, vm, vm->def->disks[i]) < 0)
return -1;
}

View File

@@ -0,0 +1,33 @@
--- src/qemu_conf.c.orig 2009-04-02 11:50:10.000000000 +0200
+++ src/qemu_conf.c 2009-04-03 17:46:59.000000000 +0200
@@ -779,6 +779,20 @@ int qemudBuildCommandLine(virConnectPtr
char domid[50];
char *pidfile;
const char *cpu = NULL;
+ int skipSound = 0;
+
+ if (driver->securityDriver &&
+ driver->securityDriver->name &&
+ STREQ(driver->securityDriver->name, "selinux") &&
+ getuid() == 0) {
+ static int soundWarned = 0;
+ skipSound = 1;
+ if (vm->def->nsounds &&
+ !soundWarned) {
+ soundWarned = 1;
+ VIR_WARN0("Sound cards for VMs are disabled while SELinux security model is active");
+ }
+ }
uname_normalize(&ut);
@@ -1425,7 +1439,8 @@ int qemudBuildCommandLine(virConnectPtr
}
/* Add sound hardware */
- if (vm->def->nsounds) {
+ if (vm->def->nsounds &&
+ !skipSound) {
int size = 100;
char *modstr;
if (VIR_ALLOC_N(modstr, size+1) < 0)

View File

@@ -0,0 +1,47 @@
From 7f7a4403860f56d5a1ad65bfd16f5bf97a971d45 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Wed, 13 May 2009 16:19:59 +0000
Subject: [PATCH 1/1] * src/buf.c: avoid an XML attribute escaping bug #499791
daniel
---
src/buf.c | 16 +++++++++++++++-
1 files changed, 15 insertions(+), 1 deletions(-)
diff --git a/src/buf.c b/src/buf.c
index cdcdac9..259175d 100644
--- a/src/buf.c
+++ b/src/buf.c
@@ -266,7 +266,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
return;
len = strlen(str);
- if (VIR_ALLOC_N(escaped, 5 * len + 1) < 0) {
+ if (VIR_ALLOC_N(escaped, 6 * len + 1) < 0) {
virBufferNoMemory(buf);
return;
}
@@ -290,6 +290,20 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
*out++ = 'm';
*out++ = 'p';
*out++ = ';';
+ } else if (*cur == '"') {
+ *out++ = '&';
+ *out++ = 'q';
+ *out++ = 'u';
+ *out++ = 'o';
+ *out++ = 't';
+ *out++ = ';';
+ } else if (*cur == '\'') {
+ *out++ = '&';
+ *out++ = 'a';
+ *out++ = 'p';
+ *out++ = 'o';
+ *out++ = 's';
+ *out++ = ';';
} else if ((*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
(*cur == '\r')) {
/*
--
1.6.0.6

View File

@@ -0,0 +1,45 @@
From 3d7771e0570e09096ad9391a857dad48b150bc0c Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Wed, 6 May 2009 16:33:28 +0100
Subject: [PATCH] Fix qemu driver's interpretation of <hostdev managed='yes'/>
This change:
Tue Mar 3 08:55:13 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
Don't try to detach & reset PCI devices while running test
suite for XML-> ARGV conversion.
* src/qemu_driver.c: Add qemuPrepareHostDevices() helper to
detach and reset PCI devices.
* src/qemu_conf.c: Don't detach & reset PCI devices while
building the command line argv
accidentally did this:
- if (hostdev->managed) {
+ if (!hostdev->managed) {
Which results in managed='yes' not causing the device to be
detached when the guest is starting.
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
src/qemu_driver.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 5898026..59312c0 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1215,7 +1215,7 @@ static int qemuPrepareHostDevices(virConnectPtr conn,
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
- if (!hostdev->managed) {
+ if (hostdev->managed) {
pciDevice *dev = pciGetDevice(conn,
hostdev->source.subsys.u.pci.domain,
hostdev->source.subsys.u.pci.bus,
--
1.6.0.6

View File

@@ -0,0 +1,76 @@
commit 0e51348cb9aeafe5e2fd6469a4bde0baa1eb8720
Author: Cole Robinson <crobinso@redhat.com>
Date: Mon May 4 15:06:03 2009 -0400
Refresh QEMU driver capabilities for each getCapabilities call.
Also fix up a couple issues where caps are accessed without locking
the driver structure.
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 23ea961..790dac6 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1885,10 +1885,12 @@ static int qemudGetNodeInfo(virConnectPtr conn,
static char *qemudGetCapabilities(virConnectPtr conn) {
struct qemud_driver *driver = conn->privateData;
- char *xml;
+ char *xml = NULL;
qemuDriverLock(driver);
- if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
+ virCapabilitiesFree(qemu_driver->caps);
+ if ((qemu_driver->caps = qemudCapsInit()) == NULL ||
+ (xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
virReportOOMError(conn);
qemuDriverUnlock(driver);
@@ -3169,20 +3171,26 @@ cleanup:
return ret;
}
-static int qemudNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel)
+static int qemudNodeGetSecurityModel(virConnectPtr conn,
+ virSecurityModelPtr secmodel)
{
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
char *p;
+ int ret = 0;
- if (!driver->securityDriver)
- return -2;
+ qemuDriverLock(driver);
+ if (!driver->securityDriver) {
+ ret = -2;
+ goto cleanup;
+ }
p = driver->caps->host.secModel.model;
if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("security model string exceeds max %d bytes"),
VIR_SECURITY_MODEL_BUFLEN-1);
- return -1;
+ ret = -1;
+ goto cleanup;
}
strcpy(secmodel->model, p);
@@ -3191,10 +3199,14 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr sec
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("security DOI string exceeds max %d bytes"),
VIR_SECURITY_DOI_BUFLEN-1);
- return -1;
+ ret = -1;
+ goto cleanup;
}
strcpy(secmodel->doi, p);
- return 0;
+
+cleanup:
+ qemuDriverUnlock(driver);
+ return ret;
}
/* TODO: check seclabel restore */

View File

@@ -1,356 +0,0 @@
From 953440bd12608a20007ee5da5ab69fbbe910bd28 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 14 Jun 2010 15:53:59 +0100
Subject: [PATCH 01/11] Extract the backing store format as well as name, if available
When QEMU opens a backing store for a QCow2 file, it will
normally auto-probe for the format of the backing store,
rather than assuming it has the same format as the referencing
file. There is a QCow2 extension that allows an explicit format
for the backing store to be embedded in the referencing file.
This closes the auto-probing security hole in QEMU.
This backing store format can be useful for libvirt users
of virStorageFileGetMetadata, so extract this data and report
it.
QEMU does not require disk image backing store files to be in
the same format the file linkee. It will auto-probe the disk
format for the backing store when opening it. If the backing
store was intended to be a raw file this could be a security
hole, because a guest may have written data into its disk that
then makes the backing store look like a qcow2 file. If it can
trick QEMU into thinking the raw file is a qcow2 file, it can
access arbitrary files on the host by adding further backing
store links.
To address this, callers of virStorageFileGetMeta need to be
told of the backing store format. If no format is declared,
they can make a decision whether to allow format probing or
not.
---
src/util/storage_file.c | 206 +++++++++++++++++++++++++++++++++++++++++------
src/util/storage_file.h | 2 +
2 files changed, 183 insertions(+), 25 deletions(-)
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index 0adea40..80f743e 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -78,12 +78,33 @@ struct FileTypeInfo {
int qcowCryptOffset; /* Byte offset from start of file
* where to find encryption mode,
* -1 if encryption is not used */
- int (*getBackingStore)(char **res, const unsigned char *buf, size_t buf_size);
+ int (*getBackingStore)(char **res, int *format,
+ const unsigned char *buf, size_t buf_size);
};
-static int cowGetBackingStore(char **, const unsigned char *, size_t);
-static int qcowXGetBackingStore(char **, const unsigned char *, size_t);
-static int vmdk4GetBackingStore(char **, const unsigned char *, size_t);
+static int cowGetBackingStore(char **, int *,
+ const unsigned char *, size_t);
+static int qcow1GetBackingStore(char **, int *,
+ const unsigned char *, size_t);
+static int qcow2GetBackingStore(char **, int *,
+ const unsigned char *, size_t);
+static int vmdk4GetBackingStore(char **, int *,
+ const unsigned char *, size_t);
+
+#define QCOWX_HDR_VERSION (4)
+#define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4)
+#define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8)
+#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4)
+
+#define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1)
+#define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8)
+
+#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8)
+#define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8)
+
+#define QCOW2_HDR_EXTENSION_END 0
+#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
+
static struct FileTypeInfo const fileTypeInfo[] = {
@@ -119,11 +140,11 @@ static struct FileTypeInfo const fileTypeInfo[] = {
/* QCow */
{ VIR_STORAGE_FILE_QCOW, "QFI", NULL,
LV_BIG_ENDIAN, 4, 1,
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcowXGetBackingStore },
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore },
/* QCow 2 */
{ VIR_STORAGE_FILE_QCOW2, "QFI", NULL,
LV_BIG_ENDIAN, 4, 2,
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcowXGetBackingStore },
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore },
/* VMDK 3 */
/* XXX Untested
{ VIR_STORAGE_FILE_VMDK, "COWD", NULL,
@@ -142,11 +163,14 @@ static struct FileTypeInfo const fileTypeInfo[] = {
static int
cowGetBackingStore(char **res,
+ int *format,
const unsigned char *buf,
size_t buf_size)
{
#define COW_FILENAME_MAXLEN 1024
*res = NULL;
+ *format = VIR_STORAGE_FILE_AUTO;
+
if (buf_size < 4+4+ COW_FILENAME_MAXLEN)
return BACKING_STORE_INVALID;
if (buf[4+4] == '\0') /* cow_header_v2.backing_file[0] */
@@ -160,31 +184,98 @@ cowGetBackingStore(char **res,
return BACKING_STORE_OK;
}
+
+static int
+qcow2GetBackingStoreFormat(int *format,
+ const unsigned char *buf,
+ size_t buf_size,
+ size_t extension_start,
+ size_t extension_end)
+{
+ size_t offset = extension_start;
+
+ /*
+ * The extensions take format of
+ *
+ * int32: magic
+ * int32: length
+ * byte[length]: payload
+ *
+ * Unknown extensions can be ignored by skipping
+ * over "length" bytes in the data stream.
+ */
+ while (offset < (buf_size-8) &&
+ offset < (extension_end-8)) {
+ unsigned int magic =
+ (buf[offset] << 24) +
+ (buf[offset+1] << 16) +
+ (buf[offset+2] << 8) +
+ (buf[offset+3]);
+ unsigned int len =
+ (buf[offset+4] << 24) +
+ (buf[offset+5] << 16) +
+ (buf[offset+6] << 8) +
+ (buf[offset+7]);
+
+ offset += 8;
+
+ if ((offset + len) < offset)
+ break;
+
+ if ((offset + len) > buf_size)
+ break;
+
+ switch (magic) {
+ case QCOW2_HDR_EXTENSION_END:
+ goto done;
+
+ case QCOW2_HDR_EXTENSION_BACKING_FORMAT:
+ if (buf[offset+len] != '\0')
+ break;
+ *format = virStorageFileFormatTypeFromString(
+ ((const char *)buf)+offset);
+ break;
+ }
+
+ offset += len;
+ }
+
+done:
+
+ return 0;
+}
+
+
static int
qcowXGetBackingStore(char **res,
+ int *format,
const unsigned char *buf,
- size_t buf_size)
+ size_t buf_size,
+ bool isQCow2)
{
unsigned long long offset;
unsigned long size;
*res = NULL;
- if (buf_size < 4+4+8+4)
+ if (format)
+ *format = VIR_STORAGE_FILE_AUTO;
+
+ if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4)
return BACKING_STORE_INVALID;
- offset = (((unsigned long long)buf[4+4] << 56)
- | ((unsigned long long)buf[4+4+1] << 48)
- | ((unsigned long long)buf[4+4+2] << 40)
- | ((unsigned long long)buf[4+4+3] << 32)
- | ((unsigned long long)buf[4+4+4] << 24)
- | ((unsigned long long)buf[4+4+5] << 16)
- | ((unsigned long long)buf[4+4+6] << 8)
- | buf[4+4+7]); /* QCowHeader.backing_file_offset */
+ offset = (((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET] << 56)
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+1] << 48)
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+2] << 40)
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+3] << 32)
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+4] << 24)
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+5] << 16)
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+6] << 8)
+ | buf[QCOWX_HDR_BACKING_FILE_OFFSET+7]); /* QCowHeader.backing_file_offset */
if (offset > buf_size)
return BACKING_STORE_INVALID;
- size = ((buf[4+4+8] << 24)
- | (buf[4+4+8+1] << 16)
- | (buf[4+4+8+2] << 8)
- | buf[4+4+8+3]); /* QCowHeader.backing_file_size */
+ size = ((buf[QCOWX_HDR_BACKING_FILE_SIZE] << 24)
+ | (buf[QCOWX_HDR_BACKING_FILE_SIZE+1] << 16)
+ | (buf[QCOWX_HDR_BACKING_FILE_SIZE+2] << 8)
+ | buf[QCOWX_HDR_BACKING_FILE_SIZE+3]); /* QCowHeader.backing_file_size */
if (size == 0)
return BACKING_STORE_OK;
if (offset + size > buf_size || offset + size < offset)
@@ -197,12 +288,63 @@ qcowXGetBackingStore(char **res,
}
memcpy(*res, buf + offset, size);
(*res)[size] = '\0';
+
+ /*
+ * Traditionally QCow2 files had a layout of
+ *
+ * [header]
+ * [backingStoreName]
+ *
+ * Although the backingStoreName typically followed
+ * the header immediately, this was not required by
+ * the format. By specifying a higher byte offset for
+ * the backing file offset in the header, it was
+ * possible to leave space between the header and
+ * start of backingStore.
+ *
+ * This hack is now used to store extensions to the
+ * qcow2 format:
+ *
+ * [header]
+ * [extensions]
+ * [backingStoreName]
+ *
+ * Thus the file region to search for extensions is
+ * between the end of the header (QCOW2_HDR_TOTAL_SIZE)
+ * and the start of the backingStoreName (offset)
+ */
+ if (isQCow2)
+ qcow2GetBackingStoreFormat(format, buf, buf_size, QCOW2_HDR_TOTAL_SIZE, offset);
+
return BACKING_STORE_OK;
}
static int
+qcow1GetBackingStore(char **res,
+ int *format,
+ const unsigned char *buf,
+ size_t buf_size)
+{
+ /* QCow1 doesn't have the extensions capability
+ * used to store backing format */
+ *format = VIR_STORAGE_FILE_AUTO;
+ return qcowXGetBackingStore(res, NULL, buf, buf_size, false);
+}
+
+static int
+qcow2GetBackingStore(char **res,
+ int *format,
+ const unsigned char *buf,
+ size_t buf_size)
+{
+ return qcowXGetBackingStore(res, format, buf, buf_size, true);
+}
+
+
+static int
vmdk4GetBackingStore(char **res,
+ int *format,
const unsigned char *buf,
size_t buf_size)
{
@@ -212,6 +354,14 @@ vmdk4GetBackingStore(char **res,
size_t len;
*res = NULL;
+ /*
+ * Technically this should have been VMDK, since
+ * VMDK spec / VMWare impl only support VMDK backed
+ * by VMDK. QEMU isn't following this though and
+ * does probing on VMDK backing files, hence we set
+ * AUTO
+ */
+ *format = VIR_STORAGE_FILE_AUTO;
if (buf_size <= 0x200)
return BACKING_STORE_INVALID;
@@ -358,9 +508,12 @@ virStorageFileGetMetadataFromFD(const char *path,
/* Validation passed, we know the file format now */
meta->format = fileTypeInfo[i].type;
if (fileTypeInfo[i].getBackingStore != NULL) {
- char *base;
+ char *backing;
+ int backingFormat;
- switch (fileTypeInfo[i].getBackingStore(&base, head, len)) {
+ switch (fileTypeInfo[i].getBackingStore(&backing,
+ &backingFormat,
+ head, len)) {
case BACKING_STORE_OK:
break;
@@ -370,13 +523,16 @@ virStorageFileGetMetadataFromFD(const char *path,
case BACKING_STORE_ERROR:
return -1;
}
- if (base != NULL) {
- meta->backingStore = absolutePathFromBaseFile(path, base);
- VIR_FREE(base);
+ if (backing != NULL) {
+ meta->backingStore = absolutePathFromBaseFile(path, backing);
+ VIR_FREE(backing);
if (meta->backingStore == NULL) {
virReportOOMError();
return -1;
}
+ meta->backingStoreFormat = backingFormat;
+ } else {
+ meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
}
}
return 0;
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
index 58533ee..6328ba7 100644
--- a/src/util/storage_file.h
+++ b/src/util/storage_file.h
@@ -28,6 +28,7 @@
# include <stdbool.h>
enum virStorageFileFormat {
+ VIR_STORAGE_FILE_AUTO = -1,
VIR_STORAGE_FILE_RAW = 0,
VIR_STORAGE_FILE_DIR,
VIR_STORAGE_FILE_BOCHS,
@@ -47,6 +48,7 @@ VIR_ENUM_DECL(virStorageFileFormat);
typedef struct _virStorageFileMetadata {
int format;
char *backingStore;
+ int backingStoreFormat;
unsigned long long capacity;
bool encrypted;
} virStorageFileMetadata;
--
1.7.1.1

View File

@@ -1,159 +0,0 @@
From cab428b1d4d432965cee6f5afb67265557706715 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 14 Jun 2010 16:39:32 +0100
Subject: [PATCH 02/11] Remove 'type' field from FileTypeInfo struct
Instead of including a field in FileTypeInfo struct for the
disk format, rely on the array index matching the format.
Use verify() to assert the correct number of elements in the
array.
* src/util/storage_file.c: remove type field from FileTypeInfo
---
src/util/storage_file.c | 108 +++++++++++++++++++++++-----------------------
1 files changed, 54 insertions(+), 54 deletions(-)
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index 80f743e..df0e3a1 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -58,7 +58,6 @@ enum {
/* Either 'magic' or 'extension' *must* be provided */
struct FileTypeInfo {
- int type; /* One of the constants above */
const char *magic; /* Optional string of file magic
* to check at head of file */
const char *extension; /* Optional file extension to check */
@@ -108,58 +107,59 @@ static int vmdk4GetBackingStore(char **, int *,
static struct FileTypeInfo const fileTypeInfo[] = {
- /* Bochs */
- /* XXX Untested
- { VIR_STORAGE_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
- LV_LITTLE_ENDIAN, 64, 0x20000,
- 32+16+16+4+4+4+4+4, 8, 1, -1, NULL },*/
- /* CLoop */
- /* XXX Untested
- { VIR_STORAGE_VOL_CLOOP, "#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", NULL,
- LV_LITTLE_ENDIAN, -1, 0,
- -1, 0, 0, -1, NULL }, */
- /* Cow */
- { VIR_STORAGE_FILE_COW, "OOOM", NULL,
- LV_BIG_ENDIAN, 4, 2,
- 4+4+1024+4, 8, 1, -1, cowGetBackingStore },
- /* DMG */
- /* XXX QEMU says there's no magic for dmg, but we should check... */
- { VIR_STORAGE_FILE_DMG, NULL, ".dmg",
- 0, -1, 0,
- -1, 0, 0, -1, NULL },
- /* XXX there's probably some magic for iso we can validate too... */
- { VIR_STORAGE_FILE_ISO, NULL, ".iso",
- 0, -1, 0,
- -1, 0, 0, -1, NULL },
- /* Parallels */
- /* XXX Untested
- { VIR_STORAGE_FILE_PARALLELS, "WithoutFreeSpace", NULL,
- LV_LITTLE_ENDIAN, 16, 2,
- 16+4+4+4+4, 4, 512, -1, NULL },
- */
- /* QCow */
- { VIR_STORAGE_FILE_QCOW, "QFI", NULL,
- LV_BIG_ENDIAN, 4, 1,
- QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore },
- /* QCow 2 */
- { VIR_STORAGE_FILE_QCOW2, "QFI", NULL,
- LV_BIG_ENDIAN, 4, 2,
- QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore },
- /* VMDK 3 */
- /* XXX Untested
- { VIR_STORAGE_FILE_VMDK, "COWD", NULL,
- LV_LITTLE_ENDIAN, 4, 1,
- 4+4+4, 4, 512, -1, NULL },
- */
- /* VMDK 4 */
- { VIR_STORAGE_FILE_VMDK, "KDMV", NULL,
- LV_LITTLE_ENDIAN, 4, 1,
- 4+4+4, 8, 512, -1, vmdk4GetBackingStore },
- /* Connectix / VirtualPC */
- { VIR_STORAGE_FILE_VPC, "conectix", NULL,
- LV_BIG_ENDIAN, 12, 0x10000,
- 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL},
+ [VIR_STORAGE_FILE_RAW] = { NULL, NULL, LV_LITTLE_ENDIAN, -1, 0, 0, 0, 0, 0, NULL },
+ [VIR_STORAGE_FILE_DIR] = { NULL, NULL, LV_LITTLE_ENDIAN, -1, 0, 0, 0, 0, 0, NULL },
+ [VIR_STORAGE_FILE_BOCHS] = {
+ /*"Bochs Virtual HD Image", */ /* Untested */ NULL,
+ NULL,
+ LV_LITTLE_ENDIAN, 64, 0x20000,
+ 32+16+16+4+4+4+4+4, 8, 1, -1, NULL
+ },
+ [VIR_STORAGE_FILE_CLOOP] = {
+ /*"#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", */ /* Untested */ NULL,
+ NULL,
+ LV_LITTLE_ENDIAN, -1, 0,
+ -1, 0, 0, -1, NULL
+ },
+ [VIR_STORAGE_FILE_COW] = {
+ "OOOM", NULL,
+ LV_BIG_ENDIAN, 4, 2,
+ 4+4+1024+4, 8, 1, -1, cowGetBackingStore
+ },
+ [VIR_STORAGE_FILE_DMG] = {
+ NULL, /* XXX QEMU says there's no magic for dmg, but we should check... */
+ ".dmg",
+ 0, -1, 0,
+ -1, 0, 0, -1, NULL
+ },
+ [VIR_STORAGE_FILE_ISO] = {
+ NULL, /* XXX there's probably some magic for iso we can validate too... */
+ ".iso",
+ 0, -1, 0,
+ -1, 0, 0, -1, NULL
+ },
+ [VIR_STORAGE_FILE_QCOW] = {
+ "QFI", NULL,
+ LV_BIG_ENDIAN, 4, 1,
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore,
+ },
+ [VIR_STORAGE_FILE_QCOW2] = {
+ "QFI", NULL,
+ LV_BIG_ENDIAN, 4, 2,
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore,
+ },
+ [VIR_STORAGE_FILE_VMDK] = {
+ "KDMV", NULL,
+ LV_LITTLE_ENDIAN, 4, 1,
+ 4+4+4, 8, 512, -1, vmdk4GetBackingStore
+ },
+ [VIR_STORAGE_FILE_VPC] = {
+ "conectix", NULL,
+ LV_BIG_ENDIAN, 12, 0x10000,
+ 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL
+ },
};
+verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST);
static int
cowGetBackingStore(char **res,
@@ -506,7 +506,7 @@ virStorageFileGetMetadataFromFD(const char *path,
}
/* Validation passed, we know the file format now */
- meta->format = fileTypeInfo[i].type;
+ meta->format = i;
if (fileTypeInfo[i].getBackingStore != NULL) {
char *backing;
int backingFormat;
@@ -546,7 +546,7 @@ virStorageFileGetMetadataFromFD(const char *path,
if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
continue;
- meta->format = fileTypeInfo[i].type;
+ meta->format = i;
return 0;
}
--
1.7.1.1

View File

@@ -1,585 +0,0 @@
From 57482ca0be29e9e92e242c9acb577e0b770c01d1 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 15 Jun 2010 14:58:10 +0100
Subject: [PATCH 03/11] Refactor virStorageFileGetMetadataFromFD to separate functionality
The virStorageFileGetMetadataFromFD did two jobs in one. First
it probed for storage type, then it extracted metadata for the
type. It is desirable to be able to separate these jobs, allowing
probing without querying metadata, and querying metadata without
probing.
To prepare for this, split out probing code into a new pair of
methods
virStorageFileProbeFormatFromFD
virStorageFileProbeFormat
* src/util/storage_file.c, src/util/storage_file.h,
src/libvirt_private.syms: Introduce virStorageFileProbeFormat
and virStorageFileProbeFormatFromFD
---
src/libvirt_private.syms | 2 +
src/util/storage_file.c | 460 +++++++++++++++++++++++++++++++++-------------
src/util/storage_file.h | 4 +
3 files changed, 335 insertions(+), 131 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 778ceb1..4607f49 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -628,6 +628,8 @@ virStorageGenerateQcowPassphrase;
# storage_file.h
virStorageFileFormatTypeToString;
virStorageFileFormatTypeFromString;
+virStorageFileProbeFormat;
+virStorageFileProbeFormatFromFD;
virStorageFileGetMetadata;
virStorageFileGetMetadataFromFD;
virStorageFileIsSharedFS;
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index df0e3a1..221268b 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -104,6 +104,9 @@ static int vmdk4GetBackingStore(char **, int *,
#define QCOW2_HDR_EXTENSION_END 0
#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
+/* VMDK needs at least this to find backing store,
+ * other formats are less */
+#define STORAGE_MAX_HEAD (20*512)
static struct FileTypeInfo const fileTypeInfo[] = {
@@ -349,9 +352,14 @@ vmdk4GetBackingStore(char **res,
size_t buf_size)
{
static const char prefix[] = "parentFileNameHint=\"";
-
- char desc[20*512 + 1], *start, *end;
+ char *desc, *start, *end;
size_t len;
+ int ret = BACKING_STORE_ERROR;
+
+ if (VIR_ALLOC_N(desc, STORAGE_MAX_HEAD + 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
*res = NULL;
/*
@@ -363,29 +371,42 @@ vmdk4GetBackingStore(char **res,
*/
*format = VIR_STORAGE_FILE_AUTO;
- if (buf_size <= 0x200)
- return BACKING_STORE_INVALID;
+ if (buf_size <= 0x200) {
+ ret = BACKING_STORE_INVALID;
+ goto cleanup;
+ }
len = buf_size - 0x200;
- if (len > sizeof(desc) - 1)
- len = sizeof(desc) - 1;
+ if (len > STORAGE_MAX_HEAD)
+ len = STORAGE_MAX_HEAD;
memcpy(desc, buf + 0x200, len);
desc[len] = '\0';
start = strstr(desc, prefix);
- if (start == NULL)
- return BACKING_STORE_OK;
+ if (start == NULL) {
+ ret = BACKING_STORE_OK;
+ goto cleanup;
+ }
start += strlen(prefix);
end = strchr(start, '"');
- if (end == NULL)
- return BACKING_STORE_INVALID;
- if (end == start)
- return BACKING_STORE_OK;
+ if (end == NULL) {
+ ret = BACKING_STORE_INVALID;
+ goto cleanup;
+ }
+ if (end == start) {
+ ret = BACKING_STORE_OK;
+ goto cleanup;
+ }
*end = '\0';
*res = strdup(start);
if (*res == NULL) {
virReportOOMError();
- return BACKING_STORE_ERROR;
+ goto cleanup;
}
- return BACKING_STORE_OK;
+
+ ret = BACKING_STORE_OK;
+
+cleanup:
+ VIR_FREE(desc);
+ return ret;
}
/**
@@ -411,148 +432,325 @@ absolutePathFromBaseFile(const char *base_file, const char *path)
return res;
}
-/**
- * Probe the header of a file to determine what type of disk image
- * it is, and info about its capacity if available.
- */
-int
-virStorageFileGetMetadataFromFD(const char *path,
- int fd,
- virStorageFileMetadata *meta)
+
+static bool
+virStorageFileMatchesMagic(int format,
+ unsigned char *buf,
+ size_t buflen)
{
- unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
- int len, i;
+ int mlen;
- memset(meta, 0, sizeof (*meta));
+ if (fileTypeInfo[format].magic == NULL)
+ return false;
- /* If all else fails, call it a raw file */
- meta->format = VIR_STORAGE_FILE_RAW;
+ /* Validate magic data */
+ mlen = strlen(fileTypeInfo[format].magic);
+ if (mlen > buflen)
+ return false;
- if ((len = read(fd, head, sizeof(head))) < 0) {
- virReportSystemError(errno, _("cannot read header '%s'"), path);
- return -1;
+ if (memcmp(buf, fileTypeInfo[format].magic, mlen) != 0)
+ return false;
+
+ return true;
+}
+
+
+static bool
+virStorageFileMatchesExtension(int format,
+ const char *path)
+{
+ if (fileTypeInfo[format].extension == NULL)
+ return false;
+
+ if (virFileHasSuffix(path, fileTypeInfo[format].extension))
+ return true;
+
+ return false;
+}
+
+
+static bool
+virStorageFileMatchesVersion(int format,
+ unsigned char *buf,
+ size_t buflen)
+{
+ int version;
+
+ /* Validate version number info */
+ if (fileTypeInfo[format].versionOffset == -1)
+ return false;
+
+ if ((fileTypeInfo[format].versionOffset + 4) > buflen)
+ return false;
+
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN) {
+ version =
+ (buf[fileTypeInfo[format].versionOffset+3] << 24) |
+ (buf[fileTypeInfo[format].versionOffset+2] << 16) |
+ (buf[fileTypeInfo[format].versionOffset+1] << 8) |
+ (buf[fileTypeInfo[format].versionOffset]);
+ } else {
+ version =
+ (buf[fileTypeInfo[format].versionOffset] << 24) |
+ (buf[fileTypeInfo[format].versionOffset+1] << 16) |
+ (buf[fileTypeInfo[format].versionOffset+2] << 8) |
+ (buf[fileTypeInfo[format].versionOffset+3]);
}
+ if (version != fileTypeInfo[format].versionNumber)
+ return false;
- /* First check file magic */
- for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
- int mlen;
-
- if (fileTypeInfo[i].magic == NULL)
- continue;
-
- /* Validate magic data */
- mlen = strlen(fileTypeInfo[i].magic);
- if (mlen > len)
- continue;
- if (memcmp(head, fileTypeInfo[i].magic, mlen) != 0)
- continue;
-
- /* Validate version number info */
- if (fileTypeInfo[i].versionNumber != -1) {
- int version;
-
- if (fileTypeInfo[i].endian == LV_LITTLE_ENDIAN) {
- version = (head[fileTypeInfo[i].versionOffset+3] << 24) |
- (head[fileTypeInfo[i].versionOffset+2] << 16) |
- (head[fileTypeInfo[i].versionOffset+1] << 8) |
- head[fileTypeInfo[i].versionOffset];
- } else {
- version = (head[fileTypeInfo[i].versionOffset] << 24) |
- (head[fileTypeInfo[i].versionOffset+1] << 16) |
- (head[fileTypeInfo[i].versionOffset+2] << 8) |
- head[fileTypeInfo[i].versionOffset+3];
- }
- if (version != fileTypeInfo[i].versionNumber)
- continue;
- }
+ return true;
+}
- /* Optionally extract capacity from file */
- if (fileTypeInfo[i].sizeOffset != -1) {
- if (fileTypeInfo[i].endian == LV_LITTLE_ENDIAN) {
- meta->capacity =
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+7] << 56) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+6] << 48) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+5] << 40) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+4] << 32) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+3] << 24) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+2] << 16) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+1] << 8) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset]);
- } else {
- meta->capacity =
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset] << 56) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+1] << 48) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+2] << 40) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+3] << 32) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+4] << 24) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+5] << 16) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+6] << 8) |
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+7]);
- }
- /* Avoid unlikely, but theoretically possible overflow */
- if (meta->capacity > (ULLONG_MAX / fileTypeInfo[i].sizeMultiplier))
- continue;
- meta->capacity *= fileTypeInfo[i].sizeMultiplier;
- }
- if (fileTypeInfo[i].qcowCryptOffset != -1) {
- int crypt_format;
+static int
+virStorageFileGetMetadataFromBuf(int format,
+ const char *path,
+ unsigned char *buf,
+ size_t buflen,
+ virStorageFileMetadata *meta)
+{
+ /* XXX we should consider moving virStorageBackendUpdateVolInfo
+ * code into this method, for non-magic files
+ */
+ if (!fileTypeInfo[format].magic) {
+ return 0;
+ }
- crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
- (head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
- (head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
- head[fileTypeInfo[i].qcowCryptOffset+3];
- meta->encrypted = crypt_format != 0;
+ /* Optionally extract capacity from file */
+ if (fileTypeInfo[format].sizeOffset != -1) {
+ if ((fileTypeInfo[format].sizeOffset + 8) > buflen)
+ return 1;
+
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN) {
+ meta->capacity =
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+7] << 56) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+6] << 48) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+5] << 40) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+4] << 32) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+3] << 24) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+2] << 16) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+1] << 8) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset]);
+ } else {
+ meta->capacity =
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset] << 56) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+1] << 48) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+2] << 40) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+3] << 32) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+4] << 24) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+5] << 16) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+6] << 8) |
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+7]);
}
+ /* Avoid unlikely, but theoretically possible overflow */
+ if (meta->capacity > (ULLONG_MAX / fileTypeInfo[format].sizeMultiplier))
+ return 1;
+ meta->capacity *= fileTypeInfo[format].sizeMultiplier;
+ }
- /* Validation passed, we know the file format now */
- meta->format = i;
- if (fileTypeInfo[i].getBackingStore != NULL) {
- char *backing;
- int backingFormat;
+ if (fileTypeInfo[format].qcowCryptOffset != -1) {
+ int crypt_format;
- switch (fileTypeInfo[i].getBackingStore(&backing,
- &backingFormat,
- head, len)) {
- case BACKING_STORE_OK:
- break;
+ crypt_format =
+ (buf[fileTypeInfo[format].qcowCryptOffset] << 24) |
+ (buf[fileTypeInfo[format].qcowCryptOffset+1] << 16) |
+ (buf[fileTypeInfo[format].qcowCryptOffset+2] << 8) |
+ (buf[fileTypeInfo[format].qcowCryptOffset+3]);
+ meta->encrypted = crypt_format != 0;
+ }
- case BACKING_STORE_INVALID:
- continue;
+ if (fileTypeInfo[format].getBackingStore != NULL) {
+ char *backing;
+ int backingFormat;
+ int ret = fileTypeInfo[format].getBackingStore(&backing,
+ &backingFormat,
+ buf, buflen);
+ if (ret == BACKING_STORE_INVALID)
+ return 1;
+
+ if (ret == BACKING_STORE_ERROR)
+ return -1;
- case BACKING_STORE_ERROR:
+ if (backing != NULL) {
+ meta->backingStore = absolutePathFromBaseFile(path, backing);
+ VIR_FREE(backing);
+ if (meta->backingStore == NULL) {
+ virReportOOMError();
return -1;
}
- if (backing != NULL) {
- meta->backingStore = absolutePathFromBaseFile(path, backing);
- VIR_FREE(backing);
- if (meta->backingStore == NULL) {
- virReportOOMError();
- return -1;
- }
- meta->backingStoreFormat = backingFormat;
- } else {
- meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
- }
+ meta->backingStoreFormat = backingFormat;
+ } else {
+ meta->backingStore = NULL;
+ meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+virStorageFileProbeFormatFromBuf(const char *path,
+ unsigned char *buf,
+ size_t buflen)
+{
+ int format = VIR_STORAGE_FILE_RAW;
+ int i;
+
+ /* First check file magic */
+ for (i = 0 ; i < VIR_STORAGE_FILE_LAST ; i++) {
+ if (virStorageFileMatchesMagic(i, buf, buflen) &&
+ virStorageFileMatchesVersion(i, buf, buflen)) {
+ format = i;
+ goto cleanup;
}
- return 0;
}
/* No magic, so check file extension */
- for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
- if (fileTypeInfo[i].extension == NULL)
- continue;
+ for (i = 0 ; i < VIR_STORAGE_FILE_LAST ; i++) {
+ if (virStorageFileMatchesExtension(i, path)) {
+ format = i;
+ goto cleanup;
+ }
+ }
- if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
- continue;
+cleanup:
+ return format;
+}
- meta->format = i;
- return 0;
+
+/**
+ * virStorageFileProbeFormatFromFD:
+ *
+ * Probe for the format of 'fd' (which is an open file descriptor
+ * pointing to 'path'), returning the detected disk format.
+ *
+ * Callers are advised never to trust the returned 'format'
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
+ * malicious guest can turn a file into any other non-raw
+ * format at will.
+ *
+ * Best option: Don't use this function
+ */
+int
+virStorageFileProbeFormatFromFD(const char *path, int fd)
+{
+ unsigned char *head;
+ ssize_t len = STORAGE_MAX_HEAD;
+ int ret = -1;
+
+ if (VIR_ALLOC_N(head, len) < 0) {
+ virReportOOMError();
+ return -1;
}
- return 0;
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
+ virReportSystemError(errno, _("cannot set to start of '%s'"), path);
+ goto cleanup;
+ }
+
+ if ((len = read(fd, head, len)) < 0) {
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
+ goto cleanup;
+ }
+
+ ret = virStorageFileProbeFormatFromBuf(path, head, len);
+
+cleanup:
+ VIR_FREE(head);
+ return ret;
+}
+
+
+/**
+ * virStorageFileProbeFormat:
+ *
+ * Probe for the format of 'path', returning the detected
+ * disk format.
+ *
+ * Callers are advised never to trust the returned 'format'
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
+ * malicious guest can turn a raw file into any other non-raw
+ * format at will.
+ *
+ * Best option: Don't use this function
+ */
+int
+virStorageFileProbeFormat(const char *path)
+{
+ int fd, ret;
+
+ if ((fd = open(path, O_RDONLY)) < 0) {
+ virReportSystemError(errno, _("cannot open file '%s'"), path);
+ return -1;
+ }
+
+ ret = virStorageFileProbeFormatFromFD(path, fd);
+
+ close(fd);
+
+ return ret;
}
+/**
+ * virStorageFileGetMetadataFromFD:
+ *
+ * Probe for the format of 'fd' (which is an open file descriptor
+ * for the file 'path'), filling 'meta' with the detected
+ * format and other associated metadata.
+ *
+ * Callers are advised never to trust the returned 'meta->format'
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
+ * malicious guest can turn a raw file into any other non-raw
+ * format at will.
+ */
+int
+virStorageFileGetMetadataFromFD(const char *path,
+ int fd,
+ virStorageFileMetadata *meta)
+{
+ unsigned char *head;
+ ssize_t len = STORAGE_MAX_HEAD;
+ int ret = -1;
+
+ if (VIR_ALLOC_N(head, len) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ memset(meta, 0, sizeof (*meta));
+
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
+ virReportSystemError(errno, _("cannot set to start of '%s'"), path);
+ goto cleanup;
+ }
+
+ if ((len = read(fd, head, len)) < 0) {
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
+ goto cleanup;
+ }
+
+ meta->format = virStorageFileProbeFormatFromBuf(path, head, len);
+
+ ret = virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta);
+
+cleanup:
+ VIR_FREE(head);
+ return ret;
+}
+
+/**
+ * virStorageFileGetMetadata:
+ *
+ * Probe for the format of 'path', filling 'meta' with the detected
+ * format and other associated metadata.
+ *
+ * Callers are advised never to trust the returned 'meta->format'
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
+ * malicious guest can turn a raw file into any other non-raw
+ * format at will.
+ */
int
virStorageFileGetMetadata(const char *path,
virStorageFileMetadata *meta)
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
index 6328ba7..3420d44 100644
--- a/src/util/storage_file.h
+++ b/src/util/storage_file.h
@@ -57,6 +57,10 @@ typedef struct _virStorageFileMetadata {
# define DEV_BSIZE 512
# endif
+int virStorageFileProbeFormat(const char *path);
+int virStorageFileProbeFormatFromFD(const char *path,
+ int fd);
+
int virStorageFileGetMetadata(const char *path,
virStorageFileMetadata *meta);
int virStorageFileGetMetadataFromFD(const char *path,
--
1.7.1.1

View File

@@ -1,285 +0,0 @@
From 726a63a437efd96510ce316bf30d16f213d4db27 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 15 Jun 2010 16:15:51 +0100
Subject: [PATCH 04/11] Require format to be passed into virStorageFileGetMetadata
Require the disk image to be passed into virStorageFileGetMetadata.
If this is set to VIR_STORAGE_FILE_AUTO, then the format will be
resolved using probing. This makes it easier to control when
probing will be used
* src/qemu/qemu_driver.c, src/qemu/qemu_security_dac.c,
src/security/security_selinux.c, src/security/virt-aa-helper.c:
Set VIR_STORAGE_FILE_AUTO when calling virStorageFileGetMetadata.
* src/storage/storage_backend_fs.c: Probe for disk format before
calling virStorageFileGetMetadata.
* src/util/storage_file.h, src/util/storage_file.c: Remove format
from virStorageFileMeta struct & require it to be passed into
method.
---
src/qemu/qemu_driver.c | 27 +++++++++++++++++---
src/qemu/qemu_security_dac.c | 4 ++-
src/security/security_selinux.c | 4 ++-
src/security/virt-aa-helper.c | 4 ++-
src/storage/storage_backend_fs.c | 11 ++++++--
src/util/storage_file.c | 50 +++++++++++++++++++++++++------------
src/util/storage_file.h | 3 +-
7 files changed, 76 insertions(+), 27 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 487bfa3..97f2990 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3069,7 +3069,9 @@ static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
}
}
- rc = virStorageFileGetMetadata(path, &meta);
+ rc = virStorageFileGetMetadata(path,
+ VIR_STORAGE_FILE_AUTO,
+ &meta);
if (rc < 0)
VIR_WARN("Unable to lookup parent image for %s", path);
@@ -3119,7 +3121,9 @@ static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
}
}
- rc = virStorageFileGetMetadata(path, &meta);
+ rc = virStorageFileGetMetadata(path,
+ VIR_STORAGE_FILE_AUTO,
+ &meta);
if (rc < 0)
VIR_WARN("Unable to lookup parent image for %s", path);
@@ -9614,6 +9618,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
virDomainDiskDefPtr disk = NULL;
struct stat sb;
int i;
+ int format;
virCheckFlags(0, -1);
@@ -9658,7 +9663,21 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
}
/* Probe for magic formats */
- if (virStorageFileGetMetadataFromFD(path, fd, &meta) < 0)
+ if (disk->driverType) {
+ if ((format = virStorageFileFormatTypeFromString(disk->driverType)) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown disk format %s for %s"),
+ disk->driverType, disk->src);
+ goto cleanup;
+ }
+ } else {
+ if ((format = virStorageFileProbeFormat(disk->src)) < 0)
+ goto cleanup;
+ }
+
+ if (virStorageFileGetMetadataFromFD(path, fd,
+ format,
+ &meta) < 0)
goto cleanup;
/* Get info for normal formats */
@@ -9706,7 +9725,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
highest allocated extent from QEMU */
if (virDomainObjIsActive(vm) &&
disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
- meta.format != VIR_STORAGE_FILE_RAW &&
+ format != VIR_STORAGE_FILE_RAW &&
S_ISBLK(sb.st_mode)) {
qemuDomainObjPrivatePtr priv = vm->privateData;
if (qemuDomainObjBeginJob(vm) < 0)
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
index 95015b0..acfe48e 100644
--- a/src/qemu/qemu_security_dac.c
+++ b/src/qemu/qemu_security_dac.c
@@ -115,7 +115,9 @@ qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED,
virStorageFileMetadata meta;
int ret;
- ret = virStorageFileGetMetadata(path, &meta);
+ ret = virStorageFileGetMetadata(path,
+ VIR_STORAGE_FILE_AUTO,
+ &meta);
if (path != disk->src)
VIR_FREE(path);
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index e5eef19..5c0f002 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -457,7 +457,9 @@ SELinuxSetSecurityImageLabel(virDomainObjPtr vm,
virStorageFileMetadata meta;
int ret;
- ret = virStorageFileGetMetadata(path, &meta);
+ ret = virStorageFileGetMetadata(path,
+ VIR_STORAGE_FILE_AUTO,
+ &meta);
if (path != disk->src)
VIR_FREE(path);
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index c66f107..2c045e6 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -830,7 +830,9 @@ get_files(vahControl * ctl)
do {
virStorageFileMetadata meta;
- ret = virStorageFileGetMetadata(path, &meta);
+ ret = virStorageFileGetMetadata(path,
+ VIR_STORAGE_FILE_AUTO,
+ &meta);
if (path != ctl->def->disks[i]->src)
VIR_FREE(path);
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index f0cd770..d3ac0fe 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -75,14 +75,19 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
memset(&meta, 0, sizeof(meta));
- if (virStorageFileGetMetadataFromFD(target->path, fd, &meta) < 0) {
+ if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
close(fd);
return -1;
}
- close(fd);
+ if (virStorageFileGetMetadataFromFD(target->path, fd,
+ target->format,
+ &meta) < 0) {
+ close(fd);
+ return -1;
+ }
- target->format = meta.format;
+ close(fd);
if (backingStore) {
*backingStore = meta.backingStore;
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
index 221268b..9712d92 100644
--- a/src/util/storage_file.c
+++ b/src/util/storage_file.c
@@ -696,18 +696,23 @@ virStorageFileProbeFormat(const char *path)
/**
* virStorageFileGetMetadataFromFD:
*
- * Probe for the format of 'fd' (which is an open file descriptor
- * for the file 'path'), filling 'meta' with the detected
- * format and other associated metadata.
+ * Extract metadata about the storage volume with the specified
+ * image format. If image format is VIR_STORAGE_FILE_AUTO, it
+ * will probe to automatically identify the format.
*
- * Callers are advised never to trust the returned 'meta->format'
- * unless it is listed as VIR_STORAGE_FILE_RAW, since a
- * malicious guest can turn a raw file into any other non-raw
- * format at will.
+ * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
+ * format, since a malicious guest can turn a raw file into any
+ * other non-raw format at will.
+ *
+ * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
+ * it indicates the image didn't specify an explicit format for its
+ * backing store. Callers are advised against probing for the
+ * backing store format in this case.
*/
int
virStorageFileGetMetadataFromFD(const char *path,
int fd,
+ int format,
virStorageFileMetadata *meta)
{
unsigned char *head;
@@ -731,9 +736,16 @@ virStorageFileGetMetadataFromFD(const char *path,
goto cleanup;
}
- meta->format = virStorageFileProbeFormatFromBuf(path, head, len);
+ if (format == VIR_STORAGE_FILE_AUTO)
+ format = virStorageFileProbeFormatFromBuf(path, head, len);
+
+ if (format < 0 ||
+ format >= VIR_STORAGE_FILE_LAST) {
+ virReportSystemError(EINVAL, _("unknown storage file format %d"), format);
+ return -1;
+ }
- ret = virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta);
+ ret = virStorageFileGetMetadataFromBuf(format, path, head, len, meta);
cleanup:
VIR_FREE(head);
@@ -743,16 +755,22 @@ cleanup:
/**
* virStorageFileGetMetadata:
*
- * Probe for the format of 'path', filling 'meta' with the detected
- * format and other associated metadata.
+ * Extract metadata about the storage volume with the specified
+ * image format. If image format is VIR_STORAGE_FILE_AUTO, it
+ * will probe to automatically identify the format.
*
- * Callers are advised never to trust the returned 'meta->format'
- * unless it is listed as VIR_STORAGE_FILE_RAW, since a
- * malicious guest can turn a raw file into any other non-raw
- * format at will.
+ * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
+ * format, since a malicious guest can turn a raw file into any
+ * other non-raw format at will.
+ *
+ * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
+ * it indicates the image didn't specify an explicit format for its
+ * backing store. Callers are advised against probing for the
+ * backing store format in this case.
*/
int
virStorageFileGetMetadata(const char *path,
+ int format,
virStorageFileMetadata *meta)
{
int fd, ret;
@@ -762,7 +780,7 @@ virStorageFileGetMetadata(const char *path,
return -1;
}
- ret = virStorageFileGetMetadataFromFD(path, fd, meta);
+ ret = virStorageFileGetMetadataFromFD(path, fd, format, meta);
close(fd);
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
index 3420d44..6853182 100644
--- a/src/util/storage_file.h
+++ b/src/util/storage_file.h
@@ -46,7 +46,6 @@ enum virStorageFileFormat {
VIR_ENUM_DECL(virStorageFileFormat);
typedef struct _virStorageFileMetadata {
- int format;
char *backingStore;
int backingStoreFormat;
unsigned long long capacity;
@@ -62,9 +61,11 @@ int virStorageFileProbeFormatFromFD(const char *path,
int fd);
int virStorageFileGetMetadata(const char *path,
+ int format,
virStorageFileMetadata *meta);
int virStorageFileGetMetadataFromFD(const char *path,
int fd,
+ int format,
virStorageFileMetadata *meta);
int virStorageFileIsSharedFS(const char *path);
--
1.7.1.1

View File

@@ -1,170 +0,0 @@
From ac5067f1e2e98181ee0e9230f756697f50d853eb Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 14 Jun 2010 18:09:15 +0100
Subject: [PATCH 05/11] Add an API for iterating over disk paths
There is duplicated code which iterates over disk backing stores
performing some action. Provide a convenient helper for doing
this to eliminate duplication & risk of mistakes with disk format
probing
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/libvirt_private.syms: Add virDomainDiskDefForeachPath()
---
src/conf/domain_conf.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 11 +++++
src/libvirt_private.syms | 1 +
3 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 378c06e..b20ca97 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -45,6 +45,7 @@
#include "macvtap.h"
#include "nwfilter_conf.h"
#include "ignore-value.h"
+#include "storage_file.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -7273,4 +7274,102 @@ done:
}
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
+ bool allowProbing,
+ bool ignoreOpenFailure,
+ virDomainDiskDefPathIterator iter,
+ void *opaque)
+{
+ virHashTablePtr paths;
+ int format;
+ int ret = -1;
+ size_t depth = 0;
+ char *nextpath = NULL;
+
+ if (!disk->src)
+ return 0;
+
+ if (disk->driverType) {
+ const char *formatStr = disk->driverType;
+ if (STREQ(formatStr, "aio"))
+ formatStr = "raw"; /* Xen compat */
+
+ if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown disk format '%s' for %s"),
+ disk->driverType, disk->src);
+ return -1;
+ }
+ } else {
+ if (allowProbing) {
+ format = VIR_STORAGE_FILE_AUTO;
+ } else {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("no disk format for %s and probing is disabled"),
+ disk->src);
+ return -1;
+ }
+ }
+
+ paths = virHashCreate(5);
+
+ do {
+ virStorageFileMetadata meta;
+ const char *path = nextpath ? nextpath : disk->src;
+ int fd;
+
+ if (iter(disk, path, depth, opaque) < 0)
+ goto cleanup;
+
+ if (virHashLookup(paths, path)) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("backing store for %s is self-referential"),
+ disk->src);
+ goto cleanup;
+ }
+
+ if ((fd = open(path, O_RDONLY)) < 0) {
+ if (ignoreOpenFailure) {
+ char ebuf[1024];
+ VIR_WARN("Ignoring open failure on %s: %s", path,
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ break;
+ } else {
+ virReportSystemError(errno,
+ _("unable to open disk path %s"),
+ path);
+ goto cleanup;
+ }
+ }
+
+ if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
+ close(fd);
+ goto cleanup;
+ }
+ close(fd);
+
+ if (virHashAddEntry(paths, path, (void*)0x1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ depth++;
+ nextpath = meta.backingStore;
+
+ format = meta.backingStoreFormat;
+
+ if (format == VIR_STORAGE_FILE_AUTO &&
+ !allowProbing)
+ format = VIR_STORAGE_FILE_RAW; /* Stops further recursion */
+ } while (nextpath);
+
+ ret = 0;
+
+cleanup:
+ virHashFree(paths, NULL);
+ VIR_FREE(nextpath);
+
+ return ret;
+}
+
#endif /* ! PROXY */
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 01da17e..d46869e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1079,6 +1079,17 @@ int virDomainChrDefForeach(virDomainDefPtr def,
void *opaque);
+typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr disk,
+ const char *path,
+ size_t depth,
+ void *opaque);
+
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
+ bool allowProbing,
+ bool ignoreOpenFailure,
+ virDomainDiskDefPathIterator iter,
+ void *opaque);
+
VIR_ENUM_DECL(virDomainVirt)
VIR_ENUM_DECL(virDomainBoot)
VIR_ENUM_DECL(virDomainFeature)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4607f49..b5f3695 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -225,6 +225,7 @@ virDomainSnapshotDefFormat;
virDomainSnapshotAssignDef;
virDomainObjAssignDef;
virDomainChrDefForeach;
+virDomainDiskDefForeachPath;
# domain_event.h
--
1.7.1.1

View File

@@ -1,506 +0,0 @@
From 54c1bb731d2b19a46a594cf9682c022f1e1114d2 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 15 Jun 2010 16:40:47 +0100
Subject: [PATCH 06/11] Convert all disk backing store loops to shared helper API
Update the QEMU cgroups code, QEMU DAC security driver, SELinux
and AppArmour security drivers over to use the shared helper API
virDomainDiskDefForeachPath().
* src/qemu/qemu_driver.c, src/qemu/qemu_security_dac.c,
src/security/security_selinux.c, src/security/virt-aa-helper.c:
Convert over to use virDomainDiskDefForeachPath()
---
src/qemu/qemu_driver.c | 161 ++++++++++++++++----------------------
src/qemu/qemu_security_dac.c | 47 ++++--------
src/security/security_selinux.c | 67 +++++++----------
src/security/virt-aa-helper.c | 71 ++++++++----------
4 files changed, 142 insertions(+), 204 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 97f2990..99aeffa 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3040,107 +3040,82 @@ static const char *const defaultDeviceACL[] = {
#define DEVICE_PTY_MAJOR 136
#define DEVICE_SND_MAJOR 116
-static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
- virDomainObjPtr vm,
- virDomainDiskDefPtr disk)
-{
- char *path = disk->src;
- int ret = -1;
- while (path != NULL) {
- virStorageFileMetadata meta;
- int rc;
+static int qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
+ const char *path,
+ size_t depth ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virCgroupPtr cgroup = opaque;
+ int rc;
- VIR_DEBUG("Process path '%s' for disk", path);
- rc = virCgroupAllowDevicePath(cgroup, path);
- if (rc != 0) {
- /* Get this for non-block devices */
- if (rc == -EINVAL) {
- VIR_DEBUG("Ignoring EINVAL for %s", path);
- } else if (rc == -EACCES) { /* Get this for root squash NFS */
- VIR_DEBUG("Ignoring EACCES for %s", path);
- } else {
- virReportSystemError(-rc,
- _("Unable to allow device %s for %s"),
- path, vm->def->name);
- if (path != disk->src)
- VIR_FREE(path);
- goto cleanup;
- }
+ VIR_DEBUG("Process path %s for disk", path);
+ /* XXX RO vs RW */
+ rc = virCgroupAllowDevicePath(cgroup, path);
+ if (rc != 0) {
+ /* Get this for non-block devices */
+ if (rc == -EINVAL) {
+ VIR_DEBUG("Ignoring EINVAL for %s", path);
+ } else if (rc == -EACCES) { /* Get this for root squash NFS */
+ VIR_DEBUG("Ignoring EACCES for %s", path);
+ } else {
+ virReportSystemError(-rc,
+ _("Unable to allow access for disk path %s"),
+ path);
+ return -1;
}
-
- rc = virStorageFileGetMetadata(path,
- VIR_STORAGE_FILE_AUTO,
- &meta);
- if (rc < 0)
- VIR_WARN("Unable to lookup parent image for %s", path);
-
- if (path != disk->src)
- VIR_FREE(path);
- path = NULL;
-
- if (rc < 0)
- break; /* Treating as non fatal */
-
- path = meta.backingStore;
}
+ return 0;
+}
- ret = 0;
-cleanup:
- return ret;
+static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
+ virDomainDiskDefPtr disk)
+{
+ return virDomainDiskDefForeachPath(disk,
+ true,
+ true,
+ qemuSetupDiskPathAllow,
+ cgroup);
}
-static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
- virDomainObjPtr vm,
- virDomainDiskDefPtr disk)
+static int qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
+ const char *path,
+ size_t depth ATTRIBUTE_UNUSED,
+ void *opaque)
{
- char *path = disk->src;
- int ret = -1;
-
- while (path != NULL) {
- virStorageFileMetadata meta;
- int rc;
+ virCgroupPtr cgroup = opaque;
+ int rc;
- VIR_DEBUG("Process path '%s' for disk", path);
- rc = virCgroupDenyDevicePath(cgroup, path);
- if (rc != 0) {
- /* Get this for non-block devices */
- if (rc == -EINVAL) {
- VIR_DEBUG("Ignoring EINVAL for %s", path);
- } else if (rc == -EACCES) { /* Get this for root squash NFS */
- VIR_DEBUG("Ignoring EACCES for %s", path);
- } else {
- virReportSystemError(-rc,
- _("Unable to deny device %s for %s"),
- path, vm->def->name);
- if (path != disk->src)
- VIR_FREE(path);
- goto cleanup;
- }
+ VIR_DEBUG("Process path %s for disk", path);
+ /* XXX RO vs RW */
+ rc = virCgroupDenyDevicePath(cgroup, path);
+ if (rc != 0) {
+ /* Get this for non-block devices */
+ if (rc == -EINVAL) {
+ VIR_DEBUG("Ignoring EINVAL for %s", path);
+ } else if (rc == -EACCES) { /* Get this for root squash NFS */
+ VIR_DEBUG("Ignoring EACCES for %s", path);
+ } else {
+ virReportSystemError(-rc,
+ _("Unable to allow access for disk path %s"),
+ path);
+ return -1;
}
-
- rc = virStorageFileGetMetadata(path,
- VIR_STORAGE_FILE_AUTO,
- &meta);
- if (rc < 0)
- VIR_WARN("Unable to lookup parent image for %s", path);
-
- if (path != disk->src)
- VIR_FREE(path);
- path = NULL;
-
- if (rc < 0)
- break; /* Treating as non fatal */
-
- path = meta.backingStore;
}
+ return 0;
+}
- ret = 0;
-cleanup:
- return ret;
+static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
+ virDomainDiskDefPtr disk)
+{
+ return virDomainDiskDefForeachPath(disk,
+ true,
+ true,
+ qemuTeardownDiskPathDeny,
+ cgroup);
}
@@ -3204,7 +3179,7 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
}
for (i = 0; i < vm->def->ndisks ; i++) {
- if (qemuSetupDiskCgroup(cgroup, vm, vm->def->disks[i]) < 0)
+ if (qemuSetupDiskCgroup(cgroup, vm->def->disks[i]) < 0)
goto cleanup;
}
@@ -8035,7 +8010,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
vm->def->name);
goto endjob;
}
- if (qemuSetupDiskCgroup(cgroup, vm, dev->data.disk) < 0)
+ if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
goto endjob;
}
@@ -8080,7 +8055,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
/* Fallthrough */
}
if (ret != 0 && cgroup) {
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -8280,7 +8255,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
vm->def->name);
goto endjob;
}
- if (qemuSetupDiskCgroup(cgroup, vm, dev->data.disk) < 0)
+ if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
goto endjob;
}
@@ -8303,7 +8278,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
}
if (ret != 0 && cgroup) {
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -8430,7 +8405,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
if (cgroup != NULL) {
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -8493,7 +8468,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
if (cgroup != NULL) {
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
index acfe48e..770010d 100644
--- a/src/qemu/qemu_security_dac.c
+++ b/src/qemu/qemu_security_dac.c
@@ -98,45 +98,28 @@ err:
static int
+qemuSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
+ const char *path,
+ size_t depth ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ return qemuSecurityDACSetOwnership(path, driver->user, driver->group);
+}
+
+
+static int
qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED,
virDomainDiskDefPtr disk)
{
- const char *path;
-
if (!driver->privileged || !driver->dynamicOwnership)
return 0;
- if (!disk->src)
- return 0;
-
- path = disk->src;
- do {
- virStorageFileMetadata meta;
- int ret;
-
- ret = virStorageFileGetMetadata(path,
- VIR_STORAGE_FILE_AUTO,
- &meta);
-
- if (path != disk->src)
- VIR_FREE(path);
- path = NULL;
-
- if (ret < 0)
- return -1;
-
- if (meta.backingStore != NULL &&
- qemuSecurityDACSetOwnership(meta.backingStore,
- driver->user, driver->group) < 0) {
- VIR_FREE(meta.backingStore);
- return -1;
- }
-
- path = meta.backingStore;
- } while (path != NULL);
-
- return qemuSecurityDACSetOwnership(disk->src, driver->user, driver->group);
+ return virDomainDiskDefForeachPath(disk,
+ true,
+ false,
+ qemuSecurityDACSetSecurityFileLabel,
+ NULL);
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 5c0f002..d191118 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -439,54 +439,43 @@ SELinuxRestoreSecurityImageLabel(virDomainObjPtr vm,
static int
+SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
+ const char *path,
+ size_t depth,
+ void *opaque)
+{
+ const virSecurityLabelDefPtr secdef = opaque;
+
+ if (depth == 0) {
+ if (disk->shared) {
+ return SELinuxSetFilecon(path, default_image_context);
+ } else if (disk->readonly) {
+ return SELinuxSetFilecon(path, default_content_context);
+ } else if (secdef->imagelabel) {
+ return SELinuxSetFilecon(path, secdef->imagelabel);
+ } else {
+ return 0;
+ }
+ } else {
+ return SELinuxSetFilecon(path, default_content_context);
+ }
+}
+
+static int
SELinuxSetSecurityImageLabel(virDomainObjPtr vm,
virDomainDiskDefPtr disk)
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
- const char *path;
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
return 0;
- if (!disk->src)
- return 0;
-
- path = disk->src;
- do {
- virStorageFileMetadata meta;
- int ret;
-
- ret = virStorageFileGetMetadata(path,
- VIR_STORAGE_FILE_AUTO,
- &meta);
-
- if (path != disk->src)
- VIR_FREE(path);
- path = NULL;
-
- if (ret < 0)
- break;
-
- if (meta.backingStore != NULL &&
- SELinuxSetFilecon(meta.backingStore,
- default_content_context) < 0) {
- VIR_FREE(meta.backingStore);
- return -1;
- }
-
- path = meta.backingStore;
- } while (path != NULL);
-
- if (disk->shared) {
- return SELinuxSetFilecon(disk->src, default_image_context);
- } else if (disk->readonly) {
- return SELinuxSetFilecon(disk->src, default_content_context);
- } else if (secdef->imagelabel) {
- return SELinuxSetFilecon(disk->src, secdef->imagelabel);
- }
-
- return 0;
+ return virDomainDiskDefForeachPath(disk,
+ true,
+ false,
+ SELinuxSetSecurityFileLabel,
+ secdef);
}
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 2c045e6..9ed0cd3 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -36,7 +36,6 @@
#include "uuid.h"
#include "hostusb.h"
#include "pci.h"
-#include "storage_file.h"
static char *progname;
@@ -801,6 +800,28 @@ file_iterate_pci_cb(pciDevice *dev ATTRIBUTE_UNUSED,
}
static int
+add_file_path(virDomainDiskDefPtr disk,
+ const char *path,
+ size_t depth,
+ void *opaque)
+{
+ virBufferPtr buf = opaque;
+ int ret;
+
+ if (depth == 0) {
+ if (disk->readonly)
+ ret = vah_add_file(buf, path, "r");
+ else
+ ret = vah_add_file(buf, path, "rw");
+ } else {
+ ret = vah_add_file(buf, path, "r");
+ }
+
+ return ret;
+}
+
+
+static int
get_files(vahControl * ctl)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -821,45 +842,15 @@ get_files(vahControl * ctl)
goto clean;
}
- for (i = 0; i < ctl->def->ndisks; i++)
- if (ctl->def->disks[i] && ctl->def->disks[i]->src) {
- int ret;
- const char *path;
-
- path = ctl->def->disks[i]->src;
- do {
- virStorageFileMetadata meta;
-
- ret = virStorageFileGetMetadata(path,
- VIR_STORAGE_FILE_AUTO,
- &meta);
-
- if (path != ctl->def->disks[i]->src)
- VIR_FREE(path);
- path = NULL;
-
- if (ret < 0) {
- vah_warning("could not open path, skipping");
- continue;
- }
-
- if (meta.backingStore != NULL &&
- (ret = vah_add_file(&buf, meta.backingStore, "rw")) != 0) {
- VIR_FREE(meta.backingStore);
- goto clean;
- }
-
- path = meta.backingStore;
- } while (path != NULL);
-
- if (ctl->def->disks[i]->readonly)
- ret = vah_add_file(&buf, ctl->def->disks[i]->src, "r");
- else
- ret = vah_add_file(&buf, ctl->def->disks[i]->src, "rw");
-
- if (ret != 0)
- goto clean;
- }
+ for (i = 0; i < ctl->def->ndisks; i++) {
+ int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
+ true,
+ false,
+ add_file_path,
+ &buf);
+ if (ret != 0)
+ goto clean;
+ }
for (i = 0; i < ctl->def->nserials; i++)
if (ctl->def->serials[i] && ctl->def->serials[i]->data.file.path)
--
1.7.1.1

File diff suppressed because it is too large Load Diff

View File

@@ -1,468 +0,0 @@
From dac2b936e77f6c76c11f162e4b175492e4803acb Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 15 Jun 2010 17:58:58 +0100
Subject: [PATCH 08/11] Disable all disk probing in QEMU driver & add config option to re-enable
Disk format probing is now disabled by default. A new config
option in /etc/qemu/qemu.conf will re-enable it for existing
deployments where this causes trouble
---
src/qemu/libvirtd_qemu.aug | 1 +
src/qemu/qemu.conf | 12 ++++++++++++
src/qemu/qemu_conf.c | 4 ++++
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_driver.c | 36 +++++++++++++++++++++++-------------
src/qemu/qemu_security_dac.c | 2 +-
src/qemu/test_libvirtd_qemu.aug | 4 ++++
src/security/security_apparmor.c | 12 ++++++++----
src/security/security_driver.c | 16 ++++++++++++++--
src/security/security_driver.h | 10 ++++++++--
src/security/security_selinux.c | 9 ++++++---
src/security/virt-aa-helper.c | 10 +++++++++-
tests/seclabeltest.c | 2 +-
13 files changed, 92 insertions(+), 27 deletions(-)
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 7c9f271..47d0525 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -40,6 +40,7 @@ module Libvirtd_qemu =
| bool_entry "relaxed_acs_check"
| bool_entry "vnc_allow_host_audio"
| bool_entry "clear_emulator_capabilities"
+ | bool_entry "allow_disk_format_probing"
(* Each enty in the config is one of the following three ... *)
let entry = vnc_entry
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 93934f3..dc8eb83 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -187,3 +187,15 @@
# exploit the privileges and possibly do damage to the host.
#
# clear_emulator_capabilities = 1
+
+
+
+# If allow_disk_format_probing is enabled, libvirt will probe disk
+# images to attempt to identify their format, when not otherwise
+# specified in the XML. This is disabled by default.
+#
+# WARNING: Enabling probing is a security hole in almost all
+# deployments. It is strongly recommended that users update their
+# guest XML <disk> elements to include <driver type='XXXX'/>
+# elements instead of enabling this option.
+# allow_disk_format_probing = 1
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 988220b..3ba48bf 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -365,6 +365,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG);
if (p) driver->clearEmulatorCapabilities = p->l;
+ p = virConfGetValue (conf, "allow_disk_format_probing");
+ CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG);
+ if (p) driver->allowDiskFormatProbing = p->l;
+
virConfFree (conf);
return 0;
}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index ab5f158..30e9f20 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -141,6 +141,7 @@ struct qemud_driver {
unsigned int relaxedACS : 1;
unsigned int vncAllowHostAudio : 1;
unsigned int clearEmulatorCapabilities : 1;
+ unsigned int allowDiskFormatProbing : 1;
virCapsPtr caps;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 616547c..3c479c5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1322,7 +1322,8 @@ qemudSecurityInit(struct qemud_driver *qemud_drv)
qemuSecurityDACSetDriver(qemud_drv);
ret = virSecurityDriverStartup(&security_drv,
- qemud_drv->securityDriverName);
+ qemud_drv->securityDriverName,
+ qemud_drv->allowDiskFormatProbing);
if (ret == -1) {
VIR_ERROR0(_("Failed to start security driver"));
return -1;
@@ -3070,11 +3071,12 @@ static int qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
}
-static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
+static int qemuSetupDiskCgroup(struct qemud_driver *driver,
+ virCgroupPtr cgroup,
virDomainDiskDefPtr disk)
{
return virDomainDiskDefForeachPath(disk,
- true,
+ driver->allowDiskFormatProbing,
true,
qemuSetupDiskPathAllow,
cgroup);
@@ -3109,11 +3111,12 @@ static int qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
}
-static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
+static int qemuTeardownDiskCgroup(struct qemud_driver *driver,
+ virCgroupPtr cgroup,
virDomainDiskDefPtr disk)
{
return virDomainDiskDefForeachPath(disk,
- true,
+ driver->allowDiskFormatProbing,
true,
qemuTeardownDiskPathDeny,
cgroup);
@@ -3180,7 +3183,7 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
}
for (i = 0; i < vm->def->ndisks ; i++) {
- if (qemuSetupDiskCgroup(cgroup, vm->def->disks[i]) < 0)
+ if (qemuSetupDiskCgroup(driver, cgroup, vm->def->disks[i]) < 0)
goto cleanup;
}
@@ -8033,7 +8036,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
vm->def->name);
goto endjob;
}
- if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
+ if (qemuSetupDiskCgroup(driver, cgroup, dev->data.disk) < 0)
goto endjob;
}
@@ -8078,7 +8081,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
/* Fallthrough */
}
if (ret != 0 && cgroup) {
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -8278,7 +8281,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
vm->def->name);
goto endjob;
}
- if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
+ if (qemuSetupDiskCgroup(driver, cgroup, dev->data.disk) < 0)
goto endjob;
}
@@ -8301,7 +8304,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
}
if (ret != 0 && cgroup) {
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -8429,7 +8432,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
if (cgroup != NULL) {
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -8493,7 +8496,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
if (cgroup != NULL) {
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
@@ -9672,8 +9675,15 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
goto cleanup;
}
} else {
- if ((format = virStorageFileProbeFormat(disk->src)) < 0)
+ if (driver->allowDiskFormatProbing) {
+ if ((format = virStorageFileProbeFormat(disk->src)) < 0)
+ goto cleanup;
+ } else {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("no disk format for %s and probing is disabled"),
+ disk->src);
goto cleanup;
+ }
}
if (virStorageFileGetMetadataFromFD(path, fd,
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
index 0bbcf69..55dc0c6 100644
--- a/src/qemu/qemu_security_dac.c
+++ b/src/qemu/qemu_security_dac.c
@@ -117,7 +117,7 @@ qemuSecurityDACSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
return 0;
return virDomainDiskDefForeachPath(disk,
- true,
+ driver->allowDiskFormatProbing,
false,
qemuSecurityDACSetSecurityFileLabel,
NULL);
diff --git a/src/qemu/test_libvirtd_qemu.aug b/src/qemu/test_libvirtd_qemu.aug
index 3326cc5..f0c4a0d 100644
--- a/src/qemu/test_libvirtd_qemu.aug
+++ b/src/qemu/test_libvirtd_qemu.aug
@@ -101,6 +101,8 @@ relaxed_acs_check = 1
vnc_allow_host_audio = 1
clear_emulator_capabilities = 0
+
+allow_disk_format_probing = 1
"
test Libvirtd_qemu.lns get conf =
@@ -212,3 +214,5 @@ clear_emulator_capabilities = 0
{ "vnc_allow_host_audio" = "1" }
{ "#empty" }
{ "clear_emulator_capabilities" = "0" }
+{ "#empty" }
+{ "allow_disk_format_probing" = "1" }
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index cb5c739..c5f9829 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -157,6 +157,8 @@ load_profile(virSecurityDriverPtr drv,
char *xml = NULL;
int pipefd[2];
pid_t child;
+ const char *probe = virSecurityDriverGetAllowDiskFormatProbing(drv)
+ ? "1" : "0";
if (pipe(pipefd) < -1) {
virReportSystemError(errno, "%s", _("unable to create pipe"));
@@ -172,19 +174,19 @@ load_profile(virSecurityDriverPtr drv,
if (create) {
const char *const argv[] = {
- VIRT_AA_HELPER, "-c", "-u", profile, NULL
+ VIRT_AA_HELPER, "-p", probe, "-c", "-u", profile, NULL
};
ret = virExec(argv, NULL, NULL, &child,
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
} else if (fn) {
const char *const argv[] = {
- VIRT_AA_HELPER, "-r", "-u", profile, "-f", fn, NULL
+ VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, "-f", fn, NULL
};
ret = virExec(argv, NULL, NULL, &child,
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
} else {
const char *const argv[] = {
- VIRT_AA_HELPER, "-r", "-u", profile, NULL
+ VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, NULL
};
ret = virExec(argv, NULL, NULL, &child,
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
@@ -347,9 +349,11 @@ AppArmorSecurityDriverProbe(void)
* currently not used.
*/
static int
-AppArmorSecurityDriverOpen(virSecurityDriverPtr drv)
+AppArmorSecurityDriverOpen(virSecurityDriverPtr drv,
+ bool allowDiskFormatProbing)
{
virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI);
+ virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
return 0;
}
diff --git a/src/security/security_driver.c b/src/security/security_driver.c
index aac9f78..9e32fa4 100644
--- a/src/security/security_driver.c
+++ b/src/security/security_driver.c
@@ -56,7 +56,8 @@ virSecurityDriverVerify(virDomainDefPtr def)
int
virSecurityDriverStartup(virSecurityDriverPtr *drv,
- const char *name)
+ const char *name,
+ bool allowDiskFormatProbing)
{
unsigned int i;
@@ -72,7 +73,7 @@ virSecurityDriverStartup(virSecurityDriverPtr *drv,
switch (tmp->probe()) {
case SECURITY_DRIVER_ENABLE:
virSecurityDriverInit(tmp);
- if (tmp->open(tmp) == -1) {
+ if (tmp->open(tmp, allowDiskFormatProbing) == -1) {
return -1;
} else {
*drv = tmp;
@@ -125,3 +126,14 @@ virSecurityDriverGetModel(virSecurityDriverPtr drv)
{
return drv->name;
}
+
+void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
+ bool allowDiskFormatProbing)
+{
+ drv->_private.allowDiskFormatProbing = allowDiskFormatProbing;
+}
+
+bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv)
+{
+ return drv->_private.allowDiskFormatProbing;
+}
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index 61c9eb0..d768f32 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -33,7 +33,8 @@ typedef struct _virSecurityDriverState virSecurityDriverState;
typedef virSecurityDriverState *virSecurityDriverStatePtr;
typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void);
-typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv);
+typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv,
+ bool allowDiskFormatProbing);
typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityDriverPtr drv,
virDomainObjPtr vm,
virDomainDiskDefPtr disk);
@@ -102,12 +103,14 @@ struct _virSecurityDriver {
*/
struct {
char doi[VIR_SECURITY_DOI_BUFLEN];
+ bool allowDiskFormatProbing;
} _private;
};
/* Global methods */
int virSecurityDriverStartup(virSecurityDriverPtr *drv,
- const char *name);
+ const char *name,
+ bool allowDiskFormatProbing);
int
virSecurityDriverVerify(virDomainDefPtr def);
@@ -120,7 +123,10 @@ virSecurityDriverVerify(virDomainDefPtr def);
void virSecurityDriverInit(virSecurityDriverPtr drv);
int virSecurityDriverSetDOI(virSecurityDriverPtr drv,
const char *doi);
+void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
+ bool allowDiskFormatProbing);
const char *virSecurityDriverGetDOI(virSecurityDriverPtr drv);
const char *virSecurityDriverGetModel(virSecurityDriverPtr drv);
+bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv);
#endif /* __VIR_SECURITY_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index cc3812b..a9dd836 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -266,13 +266,15 @@ SELinuxSecurityDriverProbe(void)
}
static int
-SELinuxSecurityDriverOpen(virSecurityDriverPtr drv)
+SELinuxSecurityDriverOpen(virSecurityDriverPtr drv,
+ bool allowDiskFormatProbing)
{
/*
* Where will the DOI come from? SELinux configuration, or qemu
* configuration? For the moment, we'll just set it to "0".
*/
virSecurityDriverSetDOI(drv, SECURITY_SELINUX_VOID_DOI);
+ virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
return SELinuxInitialize();
}
@@ -467,18 +469,19 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
}
static int
-SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv,
virDomainObjPtr vm,
virDomainDiskDefPtr disk)
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+ bool allowDiskFormatProbing = virSecurityDriverGetAllowDiskFormatProbing(drv);
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
return 0;
return virDomainDiskDefForeachPath(disk,
- true,
+ allowDiskFormatProbing,
false,
SELinuxSetSecurityFileLabel,
secdef);
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 9ed0cd3..521545d 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -40,6 +40,7 @@
static char *progname;
typedef struct {
+ bool allowDiskFormatProbing;
char uuid[PROFILE_NAME_SIZE]; /* UUID of vm */
bool dryrun; /* dry run */
char cmd; /* 'c' create
@@ -844,7 +845,7 @@ get_files(vahControl * ctl)
for (i = 0; i < ctl->def->ndisks; i++) {
int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
- true,
+ ctl->allowDiskFormatProbing,
false,
add_file_path,
&buf);
@@ -943,6 +944,7 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
{
int arg, idx = 0;
struct option opt[] = {
+ {"probing", 1, 0, 'p' },
{"add", 0, 0, 'a'},
{"create", 0, 0, 'c'},
{"dryrun", 0, 0, 'd'},
@@ -991,6 +993,12 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
PROFILE_NAME_SIZE) == NULL)
vah_error(ctl, 1, "error copying UUID");
break;
+ case 'p':
+ if (STREQ(optarg, "1"))
+ ctl->allowDiskFormatProbing = true;
+ else
+ ctl->allowDiskFormatProbing = false;
+ break;
default:
vah_error(ctl, 1, "unsupported option");
break;
diff --git a/tests/seclabeltest.c b/tests/seclabeltest.c
index 26d1f86..ef3f026 100644
--- a/tests/seclabeltest.c
+++ b/tests/seclabeltest.c
@@ -15,7 +15,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
const char *doi, *model;
virSecurityDriverPtr security_drv;
- ret = virSecurityDriverStartup (&security_drv, "selinux");
+ ret = virSecurityDriverStartup (&security_drv, "selinux", false);
if (ret == -1)
{
fprintf (stderr, "Failed to start security driver");
--
1.7.1.1

View File

@@ -1,94 +0,0 @@
From 3534cd47a57ee9cf7041472511444784f14d6939 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 14 Jun 2010 16:08:55 +0100
Subject: [PATCH 09/11] Add ability to set a default driver name/type when parsing disks
Record a default driver name/type in capabilities struct. Use this
when parsing disks if value is not set in XML config.
* src/conf/capabilities.h: Record default driver name/type for disks
* src/conf/domain_conf.c: Fallback to default driver name/type
when parsing disks
* src/qemu/qemu_driver.c: Set default driver name/type to raw
---
src/conf/capabilities.h | 2 ++
src/conf/domain_conf.c | 16 +++++++++++++++-
src/qemu/qemu_driver.c | 8 ++++++++
3 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index 9290c82..f676eb8 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -123,6 +123,8 @@ struct _virCaps {
virCapsGuestPtr *guests;
unsigned char macPrefix[VIR_MAC_PREFIX_BUFLEN];
unsigned int emulatorRequired : 1;
+ const char *defaultDiskDriverName;
+ const char *defaultDiskDriverType;
void *(*privateDataAllocFunc)(void);
void (*privateDataFreeFunc)(void *);
int (*privateDataXMLFormat)(virBufferPtr, void *);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b20ca97..f3b8cfa 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1639,6 +1639,16 @@ virDomainDiskDefParseXML(virCapsPtr caps,
def->serial = serial;
serial = NULL;
+ if (!def->driverType &&
+ caps->defaultDiskDriverType &&
+ !(def->driverType = strdup(caps->defaultDiskDriverType)))
+ goto no_memory;
+
+ if (!def->driverName &&
+ caps->defaultDiskDriverName &&
+ !(def->driverName = strdup(caps->defaultDiskDriverName)))
+ goto no_memory;
+
if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
&& virDomainDiskDefAssignAddress(caps, def) < 0)
goto error;
@@ -1659,6 +1669,9 @@ cleanup:
return def;
+no_memory:
+ virReportOOMError();
+
error:
virDomainDiskDefFree(def);
def = NULL;
@@ -4275,7 +4288,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
if (n && VIR_ALLOC_N(def->disks, n) < 0)
goto no_memory;
for (i = 0 ; i < n ; i++) {
- virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps, nodes[i],
+ virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
+ nodes[i],
flags);
if (!disk)
goto error;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3c479c5..14b790e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1357,6 +1357,14 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
return NULL;
}
+ if (driver->allowDiskFormatProbing) {
+ caps->defaultDiskDriverName = NULL;
+ caps->defaultDiskDriverType = NULL;
+ } else {
+ caps->defaultDiskDriverName = "qemu";
+ caps->defaultDiskDriverType = "raw";
+ }
+
/* Domain XML parser hooks */
caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
--
1.7.1.1

View File

@@ -1,291 +0,0 @@
From 2ba8625d6d148fa489586efabdfaf2ef20903762 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Wed, 16 Jun 2010 14:14:05 +0100
Subject: [PATCH 10/11] Rewrite qemu-img backing store format handling
When creating qcow2 files with a backing store, it is important
to set an explicit format to prevent QEMU probing. The storage
backend was only doing this if it found a 'kvm-img' binary. This
is wrong because plenty of kvm-img binaries don't support an
explicit format, and plenty of 'qemu-img' binaries do support
a format. The result was that most qcow2 files were not getting
a backing store format.
This patch runs 'qemu-img -h' to check for the two support
argument formats
'-o backing_format=raw'
'-F raw'
and use whichever option it finds
* src/storage/storage_backend.c: Query binary to determine
how to set the backing store format
---
src/storage/storage_backend.c | 214 +++++++++++++++++++++++++++++------------
1 files changed, 152 insertions(+), 62 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index aba8937..c185693 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -561,6 +561,69 @@ static int virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
return 0;
}
+enum {
+ QEMU_IMG_BACKING_FORMAT_NONE = 0,
+ QEMU_IMG_BACKING_FORMAT_FLAG,
+ QEMU_IMG_BACKING_FORMAT_OPTIONS,
+};
+
+static int virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
+{
+ const char *const qemuarg[] = { qemuimg, "-h", NULL };
+ const char *const qemuenv[] = { "LC_ALL=C", NULL };
+ pid_t child = 0;
+ int status;
+ int newstdout = -1;
+ char *help = NULL;
+ enum { MAX_HELP_OUTPUT_SIZE = 1024*8 };
+ int len;
+ char *start;
+ char *end;
+ char *tmp;
+ int ret = -1;
+
+ if (virExec(qemuarg, qemuenv, NULL,
+ &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
+ goto cleanup;
+
+ if ((len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help)) < 0) {
+ virReportSystemError(errno,
+ _("Unable to read '%s -h' output"),
+ qemuimg);
+ goto cleanup;
+ }
+
+ start = strstr(help, " create ");
+ end = strstr(start, "\n");
+ if ((tmp = strstr(start, "-F fmt")) && tmp < end)
+ ret = QEMU_IMG_BACKING_FORMAT_FLAG;
+ else if ((tmp = strstr(start, "[-o options]")) && tmp < end)
+ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
+ else
+ ret = QEMU_IMG_BACKING_FORMAT_NONE;
+
+cleanup:
+ VIR_FREE(help);
+ close(newstdout);
+rewait:
+ if (child) {
+ if (waitpid(child, &status, 0) != child) {
+ if (errno == EINTR)
+ goto rewait;
+
+ VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
+ WEXITSTATUS(status), (unsigned long)child);
+ }
+ if (WEXITSTATUS(status) != 0) {
+ VIR_WARN("Unexpected exit status '%d', qemu probably failed",
+ WEXITSTATUS(status));
+ }
+ }
+
+ return ret;
+}
+
+
static int
virStorageBackendCreateQemuImg(virConnectPtr conn,
virStoragePoolObjPtr pool,
@@ -568,10 +631,9 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
virStorageVolDefPtr inputvol,
unsigned int flags ATTRIBUTE_UNUSED)
{
- int ret;
+ int ret = -1;
char size[100];
char *create_tool;
- short use_kvmimg;
const char *type = virStorageFileFormatTypeToString(vol->target.format);
const char *backingType = vol->backingStore.path ?
@@ -582,41 +644,10 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
const char *inputPath = inputvol ? inputvol->target.path : NULL;
/* Treat input block devices as 'raw' format */
const char *inputType = inputPath ?
- virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ? VIR_STORAGE_FILE_RAW : inputvol->target.format) :
- NULL;
-
- const char **imgargv;
- /* The extra NULL field is for indicating encryption (-e). */
- const char *imgargvnormal[] = {
- NULL, "create",
- "-f", type,
- vol->target.path,
- size,
- NULL,
- NULL
- };
- /* Extra NULL fields are for including "backingType" when using
- * kvm-img (-F backingType), and for indicating encryption (-e).
- */
- const char *imgargvbacking[] = {
- NULL, "create",
- "-f", type,
- "-b", vol->backingStore.path,
- vol->target.path,
- size,
- NULL,
- NULL,
- NULL,
- NULL
- };
- const char *convargv[] = {
- NULL, "convert",
- "-f", inputType,
- "-O", type,
- inputPath,
- vol->target.path,
- NULL,
- };
+ virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ?
+ VIR_STORAGE_FILE_RAW :
+ inputvol->target.format) :
+ NULL;
if (type == NULL) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
@@ -690,44 +721,103 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
}
}
- if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
- use_kvmimg = 1;
- else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
- use_kvmimg = 0;
- else {
+ /* Size in KB */
+ snprintf(size, sizeof(size), "%lluK", vol->capacity/1024);
+
+ /* KVM is usually ahead of qemu on features, so try that first */
+ create_tool = virFindFileInPath("kvm-img");
+ if (!create_tool)
+ create_tool = virFindFileInPath("qemu-img");
+
+ if (!create_tool) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("unable to find kvm-img or qemu-img"));
return -1;
}
if (inputvol) {
- convargv[0] = create_tool;
- imgargv = convargv;
+ const char *imgargv[] = {
+ create_tool,
+ "convert",
+ "-f", inputType,
+ "-O", type,
+ inputPath,
+ vol->target.path,
+ NULL,
+ };
+
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
} else if (vol->backingStore.path) {
- imgargvbacking[0] = create_tool;
- if (use_kvmimg) {
- imgargvbacking[6] = "-F";
- imgargvbacking[7] = backingType;
- imgargvbacking[8] = vol->target.path;
- imgargvbacking[9] = size;
+ const char *imgargv[] = {
+ create_tool,
+ "create",
+ "-f", type,
+ "-b", vol->backingStore.path,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+ int imgformat = virStorageBackendQEMUImgBackingFormat(create_tool);
+ char *optflag = NULL;
+ if (imgformat < 0)
+ goto cleanup;
+
+ switch (imgformat) {
+ case QEMU_IMG_BACKING_FORMAT_FLAG:
+ imgargv[6] = "-F";
+ imgargv[7] = backingType;
+ imgargv[8] = vol->target.path;
+ imgargv[9] = size;
+ if (vol->target.encryption != NULL)
+ imgargv[10] = "-e";
+ break;
+
+ case QEMU_IMG_BACKING_FORMAT_OPTIONS:
+ if (virAsprintf(&optflag, "backing_fmt=%s", backingType) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ imgargv[6] = "-o";
+ imgargv[7] = optflag;
+ imgargv[8] = vol->target.path;
+ imgargv[9] = size;
if (vol->target.encryption != NULL)
- imgargvbacking[10] = "-e";
- } else if (vol->target.encryption != NULL)
- imgargvbacking[8] = "-e";
- imgargv = imgargvbacking;
+ imgargv[10] = "-e";
+ break;
+
+ default:
+ VIR_INFO("Unable to set backing store format for %s with %s",
+ vol->target.path, create_tool);
+ imgargv[6] = vol->target.path;
+ imgargv[7] = size;
+ if (vol->target.encryption != NULL)
+ imgargv[8] = "-e";
+ }
+
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
+ VIR_FREE(optflag);
} else {
- imgargvnormal[0] = create_tool;
- imgargv = imgargvnormal;
+ /* The extra NULL field is for indicating encryption (-e). */
+ const char *imgargv[] = {
+ create_tool,
+ "create",
+ "-f", type,
+ vol->target.path,
+ size,
+ NULL,
+ NULL
+ };
if (vol->target.encryption != NULL)
imgargv[6] = "-e";
- }
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
+ }
- /* Size in KB */
- snprintf(size, sizeof(size), "%lluK", vol->capacity/1024);
-
- ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
- VIR_FREE(imgargv[0]);
+ cleanup:
+ VIR_FREE(create_tool);
return ret;
}
--
1.7.1.1

View File

@@ -1,165 +0,0 @@
From d33f44c2e74de28c89b64cdc2c0a6564662e075c Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Fri, 9 Jul 2010 11:28:40 +0100
Subject: [PATCH 11/11] Use the extract backing store format in storage volume lookup
The storage volume lookup code was probing for the backing store
format, instead of using the format extracted from the file
itself. This meant it could report in accurate information. If
a format is included in the file, then use that in preference,
with probing as a fallback.
* src/storage/storage_backend_fs.c: Use extracted backing store
format
---
src/storage/storage_backend_fs.c | 80 +++++++++++++++++---------------------
1 files changed, 36 insertions(+), 44 deletions(-)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index d3ac0fe..ffb0071 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -51,6 +51,7 @@
static int
virStorageBackendProbeTarget(virStorageVolTargetPtr target,
char **backingStore,
+ int *backingStoreFormat,
unsigned long long *allocation,
unsigned long long *capacity,
virStorageEncryptionPtr *encryption)
@@ -58,6 +59,10 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
int fd, ret;
virStorageFileMetadata meta;
+ if (backingStore)
+ *backingStore = NULL;
+ if (backingStoreFormat)
+ *backingStoreFormat = VIR_STORAGE_FILE_AUTO;
if (encryption)
*encryption = NULL;
@@ -89,22 +94,30 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
close(fd);
- if (backingStore) {
- *backingStore = meta.backingStore;
- meta.backingStore = NULL;
+ if (meta.backingStore) {
+ if (backingStore) {
+ *backingStore = meta.backingStore;
+ meta.backingStore = NULL;
+ if (meta.backingStoreFormat == VIR_STORAGE_FILE_AUTO) {
+ if ((*backingStoreFormat = virStorageFileProbeFormat(*backingStore)) < 0) {
+ close(fd);
+ goto cleanup;
+ }
+ } else {
+ *backingStoreFormat = meta.backingStoreFormat;
+ }
+ } else {
+ VIR_FREE(meta.backingStore);
+ }
}
- VIR_FREE(meta.backingStore);
-
if (capacity && meta.capacity)
*capacity = meta.capacity;
if (encryption != NULL && meta.encrypted) {
if (VIR_ALLOC(*encryption) < 0) {
virReportOOMError();
- if (backingStore)
- VIR_FREE(*backingStore);
- return -1;
+ goto cleanup;
}
switch (target->format) {
@@ -124,6 +137,11 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
}
return 0;
+
+cleanup:
+ if (backingStore)
+ VIR_FREE(*backingStore);
+ return -1;
}
#if WITH_STORAGE_FS
@@ -585,6 +603,7 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
while ((ent = readdir(dir)) != NULL) {
int ret;
char *backingStore;
+ int backingStoreFormat;
if (VIR_ALLOC(vol) < 0)
goto no_memory;
@@ -604,6 +623,7 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
if ((ret = virStorageBackendProbeTarget(&vol->target,
&backingStore,
+ &backingStoreFormat,
&vol->allocation,
&vol->capacity,
&vol->target.encryption)) < 0) {
@@ -619,46 +639,18 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
}
if (backingStore != NULL) {
- if (vol->target.format == VIR_STORAGE_FILE_QCOW2 &&
- STRPREFIX("fmt:", backingStore)) {
- char *fmtstr = backingStore + 4;
- char *path = strchr(fmtstr, ':');
- if (!path) {
- VIR_FREE(backingStore);
- } else {
- *path = '\0';
- if ((vol->backingStore.format =
- virStorageFileFormatTypeFromString(fmtstr)) < 0) {
- VIR_FREE(backingStore);
- } else {
- memmove(backingStore, path, strlen(path) + 1);
- vol->backingStore.path = backingStore;
-
- if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
- NULL,
- NULL) < 0)
- VIR_FREE(vol->backingStore);
- }
- }
- } else {
- vol->backingStore.path = backingStore;
-
- if ((ret = virStorageBackendProbeTarget(&vol->backingStore,
- NULL, NULL, NULL,
- NULL)) < 0) {
- if (ret == -1)
- goto cleanup;
- else {
- /* Silently ignore non-regular files,
- * eg '.' '..', 'lost+found' */
- VIR_FREE(vol->backingStore);
- }
- }
+ vol->backingStore.path = backingStore;
+ vol->backingStore.format = backingStoreFormat;
+
+ if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
+ NULL,
+ NULL) < 0) {
+ VIR_FREE(vol->backingStore.path);
+ goto cleanup;
}
}
-
if (VIR_REALLOC_N(pool->volumes.objs,
pool->volumes.count+1) < 0)
goto no_memory;
--
1.7.1.1

View File

@@ -1,265 +0,0 @@
From 112a309bc7839e95c558b535143f855ce89cca8c Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Thu, 10 Jun 2010 12:50:38 -0400
Subject: [PATCH] CVE-2010-2242 Apply a source port mapping to virtual network masquerading
IPtables will seek to preserve the source port unchanged when
doing masquerading, if possible. NFS has a pseudo-security
option where it checks for the source port <= 1023 before
allowing a mount request. If an admin has used this to make the
host OS trusted for mounts, the default iptables behaviour will
potentially allow NAT'd guests access too. This needs to be
stopped.
With this change, the iptables -t nat -L -n -v rules for the
default network will be
Chain POSTROUTING (policy ACCEPT 95 packets, 9163 bytes)
pkts bytes target prot opt in out source destination
14 840 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
75 5752 MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
0 0 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
* src/network/bridge_driver.c: Add masquerade rules for TCP
and UDP protocols
* src/util/iptables.c, src/util/iptables.c: Add source port
mappings for TCP & UDP protocols when masquerading.
---
src/network/bridge_driver.c | 73 ++++++++++++++++++++++++++++++++++++++++--
src/util/iptables.c | 70 +++++++++++++++++++++++++++++------------
src/util/iptables.h | 6 ++-
3 files changed, 122 insertions(+), 27 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 72255c1..80ed57a 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -638,18 +638,74 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
goto masqerr2;
}
- /* enable masquerading */
+ /*
+ * Enable masquerading.
+ *
+ * We need to end up with 3 rules in the table in this order
+ *
+ * 1. protocol=tcp with sport mapping restricton
+ * 2. protocol=udp with sport mapping restricton
+ * 3. generic any protocol
+ *
+ * The sport mappings are required, because default IPtables
+ * MASQUERADE is maintain port number unchanged where possible.
+ *
+ * NFS can be configured to only "trust" port numbers < 1023.
+ *
+ * Guests using NAT thus need to be prevented from having port
+ * numbers < 1023, otherwise they can bypass the NFS "security"
+ * check on the source port number.
+ *
+ * Since we use '--insert' to add rules to the header of the
+ * chain, we actually need to add them in the reverse of the
+ * order just mentioned !
+ */
+
+ /* First the generic masquerade rule for other protocols */
if ((err = iptablesAddForwardMasquerade(driver->iptables,
network->def->network,
- network->def->forwardDev))) {
+ network->def->forwardDev,
+ NULL))) {
virReportSystemError(err,
_("failed to add iptables rule to enable masquerading to '%s'"),
network->def->forwardDev ? network->def->forwardDev : NULL);
goto masqerr3;
}
+ /* UDP with a source port restriction */
+ if ((err = iptablesAddForwardMasquerade(driver->iptables,
+ network->def->network,
+ network->def->forwardDev,
+ "udp"))) {
+ virReportSystemError(err,
+ _("failed to add iptables rule to enable UDP masquerading to '%s'"),
+ network->def->forwardDev ? network->def->forwardDev : NULL);
+ goto masqerr4;
+ }
+
+ /* TCP with a source port restriction */
+ if ((err = iptablesAddForwardMasquerade(driver->iptables,
+ network->def->network,
+ network->def->forwardDev,
+ "tcp"))) {
+ virReportSystemError(err,
+ _("failed to add iptables rule to enable TCP masquerading to '%s'"),
+ network->def->forwardDev ? network->def->forwardDev : NULL);
+ goto masqerr5;
+ }
+
return 1;
+ masqerr5:
+ iptablesRemoveForwardMasquerade(driver->iptables,
+ network->def->network,
+ network->def->forwardDev,
+ "udp");
+ masqerr4:
+ iptablesRemoveForwardMasquerade(driver->iptables,
+ network->def->network,
+ network->def->forwardDev,
+ NULL);
masqerr3:
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
network->def->network,
@@ -814,8 +870,17 @@ networkRemoveIptablesRules(struct network_driver *driver,
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
iptablesRemoveForwardMasquerade(driver->iptables,
- network->def->network,
- network->def->forwardDev);
+ network->def->network,
+ network->def->forwardDev,
+ "tcp");
+ iptablesRemoveForwardMasquerade(driver->iptables,
+ network->def->network,
+ network->def->forwardDev,
+ "udp");
+ iptablesRemoveForwardMasquerade(driver->iptables,
+ network->def->network,
+ network->def->forwardDev,
+ NULL);
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
network->def->network,
network->def->bridge,
diff --git a/src/util/iptables.c b/src/util/iptables.c
index d06b857..f63e8c6 100644
--- a/src/util/iptables.c
+++ b/src/util/iptables.c
@@ -692,25 +692,49 @@ iptablesRemoveForwardRejectIn(iptablesContext *ctx,
*/
static int
iptablesForwardMasquerade(iptablesContext *ctx,
- const char *network,
- const char *physdev,
- int action)
+ const char *network,
+ const char *physdev,
+ const char *protocol,
+ int action)
{
- if (physdev && physdev[0]) {
- return iptablesAddRemoveRule(ctx->nat_postrouting,
- action,
- "--source", network,
- "!", "--destination", network,
- "--out-interface", physdev,
- "--jump", "MASQUERADE",
- NULL);
+ if (protocol && protocol[0]) {
+ if (physdev && physdev[0]) {
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
+ action,
+ "--source", network,
+ "-p", protocol,
+ "!", "--destination", network,
+ "--out-interface", physdev,
+ "--jump", "MASQUERADE",
+ "--to-ports", "1024-65535",
+ NULL);
+ } else {
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
+ action,
+ "--source", network,
+ "-p", protocol,
+ "!", "--destination", network,
+ "--jump", "MASQUERADE",
+ "--to-ports", "1024-65535",
+ NULL);
+ }
} else {
- return iptablesAddRemoveRule(ctx->nat_postrouting,
- action,
- "--source", network,
- "!", "--destination", network,
- "--jump", "MASQUERADE",
- NULL);
+ if (physdev && physdev[0]) {
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
+ action,
+ "--source", network,
+ "!", "--destination", network,
+ "--out-interface", physdev,
+ "--jump", "MASQUERADE",
+ NULL);
+ } else {
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
+ action,
+ "--source", network,
+ "!", "--destination", network,
+ "--jump", "MASQUERADE",
+ NULL);
+ }
}
}
@@ -719,6 +743,7 @@ iptablesForwardMasquerade(iptablesContext *ctx,
* @ctx: pointer to the IP table context
* @network: the source network name
* @physdev: the physical input device or NULL
+ * @protocol: the network protocol or NULL
*
* Add rules to the IP table context to allow masquerading
* network @network on @physdev. This allow the bridge to
@@ -729,9 +754,10 @@ iptablesForwardMasquerade(iptablesContext *ctx,
int
iptablesAddForwardMasquerade(iptablesContext *ctx,
const char *network,
- const char *physdev)
+ const char *physdev,
+ const char *protocol)
{
- return iptablesForwardMasquerade(ctx, network, physdev, ADD);
+ return iptablesForwardMasquerade(ctx, network, physdev, protocol, ADD);
}
/**
@@ -739,6 +765,7 @@ iptablesAddForwardMasquerade(iptablesContext *ctx,
* @ctx: pointer to the IP table context
* @network: the source network name
* @physdev: the physical input device or NULL
+ * @protocol: the network protocol or NULL
*
* Remove rules from the IP table context to stop masquerading
* network @network on @physdev. This stops the bridge from
@@ -749,7 +776,8 @@ iptablesAddForwardMasquerade(iptablesContext *ctx,
int
iptablesRemoveForwardMasquerade(iptablesContext *ctx,
const char *network,
- const char *physdev)
+ const char *physdev,
+ const char *protocol)
{
- return iptablesForwardMasquerade(ctx, network, physdev, REMOVE);
+ return iptablesForwardMasquerade(ctx, network, physdev, protocol, REMOVE);
}
diff --git a/src/util/iptables.h b/src/util/iptables.h
index 7d55a6d..b47d854 100644
--- a/src/util/iptables.h
+++ b/src/util/iptables.h
@@ -85,9 +85,11 @@ int iptablesRemoveForwardRejectIn (iptablesContext *ctx,
int iptablesAddForwardMasquerade (iptablesContext *ctx,
const char *network,
- const char *physdev);
+ const char *physdev,
+ const char *protocol);
int iptablesRemoveForwardMasquerade (iptablesContext *ctx,
const char *network,
- const char *physdev);
+ const char *physdev,
+ const char *protocol);
#endif /* __QEMUD_IPTABLES_H__ */
--
1.6.6.1

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
14164638fe0e7f65e425acc85dabc517 libvirt-0.8.2.tar.gz
3035b484861516a1cd425acef1e760e3 libvirt-0.6.2.tar.gz