Update to 0.8.2 release. Fix CVE-2010-2237, CVE-2010-2238, CVE-2010-2239, CVE-2010-2242

This commit is contained in:
Daniel P. Berrange 2010-07-12 15:47:10 +00:00
parent 3d90c2f845
commit f75a9b8ec9
31 changed files with 4617 additions and 1589 deletions

View File

@ -3,16 +3,3 @@
i686
x86_64
libvirt-*.tar.gz
libvirt-0.6.0.tar.gz
libvirt-0.6.1.tar.gz
libvirt-0.6.2.tar.gz
libvirt-0.6.3.tar.gz
libvirt-0.6.4.tar.gz
libvirt-0.6.5.tar.gz
libvirt-0.7.0.tar.gz
libvirt-0.7.1.tar.gz
libvirt-0.7.2.tar.gz
libvirt-0.7.3.tar.gz
libvirt-0.7.4.tar.gz
libvirt-0.7.5.tar.gz
libvirt-0.7.6.tar.gz

View File

@ -1,163 +0,0 @@
commit 377bc412ce10845930346744e30fe9c4790e5e63
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 19 16:03:52 2010 -0400
daemon: Export SDL audio environment variables
/etc/sysconfig/libvirtd has a few environment variables for configuring
libvirt SDL audio. The libvirtd process doesn't see these, however, because
they are never exported. Let's export the variables after sourcing the
sysconfig script.
There is another problem here that the commented out values in the
sysconfig script are not neccessarily the actual defaults, we are qemus
mercy here. Not sure how to solve that.
diff --git a/daemon/libvirtd.init.in b/daemon/libvirtd.init.in
index 809433e..aa7870c 100644
--- a/daemon/libvirtd.init.in
+++ b/daemon/libvirtd.init.in
@@ -45,6 +45,9 @@ KRB5_KTNAME=/etc/libvirt/krb5.tab
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
+export QEMU_AUDIO_DRV
+export SDL_AUDIODRIVER
+
LIBVIRTD_CONFIG_ARGS=
if [ -n "$LIBVIRTD_CONFIG" ]
then
commit 7f44743c524faa493d05eaf026f1e90a807e502b
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 26 10:51:36 2010 -0400
daemon: sysconf: Update comment about VNC audio
diff --git a/daemon/libvirtd.sysconf b/daemon/libvirtd.sysconf
index 28080a0..b730c5e 100644
--- a/daemon/libvirtd.sysconf
+++ b/daemon/libvirtd.sysconf
@@ -11,7 +11,8 @@
# Override the QEMU/SDL default audio driver probing when
# starting virtual machines using SDL graphics
#
-# NB these have no effect for VMs using VNC
+# NB these have no effect for VMs using VNC, unless vnc_allow_host_audio
+# is enabled in /etc/libvirt/qemu.conf
#QEMU_AUDIO_DRV=sdl
#
#SDL_AUDIODRIVER=pulse
commit fb3ebd0397980ae035e66f0008b09e13377ef80f
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 19 16:41:01 2010 -0400
qemu: Allow using regular audio backends with VNC
Currently all host audio backends are disabled if a VM is using VNC, in
favor of the QEMU VNC audio extension. Unfortunately no released VNC
client supports this extension, so users have no way of getting audio
to work if using VNC.
Add a new config option in qemu.conf which allows changing libvirt's
behavior, but keep the default intact.
v2: Fix doc typos, change name to vnc_allow_host_audio
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 5bd60b3..551cc20 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -38,6 +38,7 @@ module Libvirtd_qemu =
| str_entry "save_image_format"
| str_entry "hugetlbfs_mount"
| bool_entry "relaxed_acs_check"
+ | bool_entry "vnc_allow_host_audio"
(* 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 3da332f..98a1176 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -168,3 +168,13 @@
# be assigned to guests.
#
# relaxed_acs_check = 1
+
+
+# QEMU implements an extension for providing audio over a VNC connection,
+# though if your VNC client does not support it, your only chance for getting
+# sound output is through regular audio backends. By default, libvirt will
+# disable all QEMU sound backends if using VNC, since they can cause
+# permissions issues. Enabling this option will make libvirtd honor the
+# QEMU_AUDIO_DRV environment variable when using VNC.
+#
+# vnc_allow_host_audio = 0
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 2755545..b4d8e74 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -351,6 +351,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG);
if (p) driver->relaxedACS = p->l;
+ p = virConfGetValue (conf, "vnc_allow_host_audio");
+ CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG);
+ if (p) driver->vncAllowHostAudio = p->l;
+
virConfFree (conf);
return 0;
}
@@ -4399,12 +4403,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT(def->graphics[0]->data.vnc.keymap);
}
- /* QEMU implements a VNC extension for providing audio, so we
- * set the audio backend to none, to prevent it opening the
- * host OS audio devices since that causes security issues
- * and is non-sensical when using VNC.
+ /* Unless user requested it, set the audio backend to none, to
+ * prevent it opening the host OS audio devices, since that causes
+ * security issues and might not work when using VNC.
*/
- ADD_ENV_LIT("QEMU_AUDIO_DRV=none");
+ if (driver->vncAllowHostAudio) {
+ ADD_ENV_COPY("QEMU_AUDIO_DRV");
+ } else {
+ ADD_ENV_LIT("QEMU_AUDIO_DRV=none");
+ }
} else if ((def->ngraphics == 1) &&
def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
char *xauth = NULL;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 8fd8d79..7fb4de5 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -138,6 +138,8 @@ struct qemud_driver {
unsigned int relaxedACS : 1;
+ unsigned int vncAllowHostAudio : 1;
+
virCapsPtr caps;
/* An array of callbacks */
diff --git a/src/qemu/test_libvirtd_qemu.aug b/src/qemu/test_libvirtd_qemu.aug
index 2feedc0..a048ae5 100644
--- a/src/qemu/test_libvirtd_qemu.aug
+++ b/src/qemu/test_libvirtd_qemu.aug
@@ -97,6 +97,8 @@ save_image_format = \"gzip\"
hugetlbfs_mount = \"/dev/hugepages\"
relaxed_acs_check = 1
+
+vnc_allow_host_audio = 1
"
test Libvirtd_qemu.lns get conf =
@@ -204,3 +206,5 @@ relaxed_acs_check = 1
{ "hugetlbfs_mount" = "/dev/hugepages" }
{ "#empty" }
{ "relaxed_acs_check" = "1" }
+{ "#empty" }
+{ "vnc_allow_host_audio" = "1" }

View File

@ -1,110 +0,0 @@
diff -rup libvirt-0.7.7/src/qemu/libvirtd_qemu.aug new/src/qemu/libvirtd_qemu.aug
--- libvirt-0.7.7/src/qemu/libvirtd_qemu.aug 2010-06-17 12:38:52.998946000 -0400
+++ new/src/qemu/libvirtd_qemu.aug 2010-06-17 12:39:28.504148000 -0400
@@ -39,6 +39,7 @@ module Libvirtd_qemu =
| str_entry "hugetlbfs_mount"
| bool_entry "relaxed_acs_check"
| bool_entry "vnc_allow_host_audio"
+ | bool_entry "clear_emulator_capabilities"
(* Each enty in the config is one of the following three ... *)
let entry = vnc_entry
diff -rup libvirt-0.7.7/src/qemu/qemu.conf new/src/qemu/qemu.conf
--- libvirt-0.7.7/src/qemu/qemu.conf 2010-06-17 12:38:53.001953000 -0400
+++ new/src/qemu/qemu.conf 2010-06-17 12:39:28.508149000 -0400
@@ -178,3 +178,12 @@
# QEMU_AUDIO_DRV environment variable when using VNC.
#
# vnc_allow_host_audio = 0
+
+# If clear_emulator_capabilities is enabled, libvirt will drop all
+# privileged capabilities of the QEmu/KVM emulator. This is enabled by
+# default.
+#
+# Warning: Disabling this option means that a compromised guest can
+# exploit the privileges and possibly do damage to the host.
+#
+# clear_emulator_capabilities = 1
diff -rup libvirt-0.7.7/src/qemu/qemu_conf.c new/src/qemu/qemu_conf.c
--- libvirt-0.7.7/src/qemu/qemu_conf.c 2010-06-17 12:38:53.010946000 -0400
+++ new/src/qemu/qemu_conf.c 2010-06-17 12:39:28.526151000 -0400
@@ -103,6 +103,7 @@ int qemudLoadDriverConfig(struct qemud_d
/* Setup critical defaults */
driver->dynamicOwnership = 1;
+ driver->clearEmulatorCapabilities = 1;
if (!(driver->vncListen = strdup("127.0.0.1"))) {
virReportOOMError();
@@ -354,6 +355,10 @@ int qemudLoadDriverConfig(struct qemud_d
CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG);
if (p) driver->vncAllowHostAudio = p->l;
+ p = virConfGetValue (conf, "clear_emulator_capabilities");
+ CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG);
+ if (p) driver->clearEmulatorCapabilities = p->l;
+
virConfFree (conf);
return 0;
}
diff -rup libvirt-0.7.7/src/qemu/qemu_conf.h new/src/qemu/qemu_conf.h
--- libvirt-0.7.7/src/qemu/qemu_conf.h 2010-06-17 12:38:53.015945000 -0400
+++ new/src/qemu/qemu_conf.h 2010-06-17 12:39:28.531146000 -0400
@@ -129,8 +129,8 @@ struct qemud_driver {
ebtablesContext *ebtables;
unsigned int relaxedACS : 1;
-
unsigned int vncAllowHostAudio : 1;
+ unsigned int clearEmulatorCapabilities : 1;
virCapsPtr caps;
diff -rup libvirt-0.7.7/src/qemu/qemu_driver.c new/src/qemu/qemu_driver.c
--- libvirt-0.7.7/src/qemu/qemu_driver.c 2010-06-17 12:38:52.988953000 -0400
+++ new/src/qemu/qemu_driver.c 2010-06-17 12:39:28.542147000 -0400
@@ -2699,7 +2699,7 @@ static int qemudStartVMDaemon(virConnect
int stdin_fd) {
const char **argv = NULL, **tmp;
const char **progenv = NULL;
- int i, ret;
+ int i, ret, runflags;
struct stat sb;
int *tapfds = NULL;
int ntapfds = 0;
@@ -2893,9 +2893,16 @@ static int qemudStartVMDaemon(virConnect
for (i = 0 ; i < ntapfds ; i++)
FD_SET(tapfds[i], &keepfd);
+ VIR_DEBUG("Clear emulator capabilities: %d",
+ driver->clearEmulatorCapabilities);
+ runflags = VIR_EXEC_NONBLOCK;
+ if (driver->clearEmulatorCapabilities) {
+ runflags |= VIR_EXEC_CLEAR_CAPS;
+ }
+
ret = virExecDaemonize(argv, progenv, &keepfd, &child,
stdin_fd, &logfile, &logfile,
- VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS,
+ runflags,
qemudSecurityHook, &hookData,
pidfile);
VIR_FREE(pidfile);
diff -rup libvirt-0.7.7/src/qemu/test_libvirtd_qemu.aug new/src/qemu/test_libvirtd_qemu.aug
--- libvirt-0.7.7/src/qemu/test_libvirtd_qemu.aug 2010-06-17 12:38:53.018948000 -0400
+++ new/src/qemu/test_libvirtd_qemu.aug 2010-06-17 12:39:28.546145000 -0400
@@ -99,6 +99,8 @@ hugetlbfs_mount = \"/dev/hugepages\"
relaxed_acs_check = 1
vnc_allow_host_audio = 1
+
+clear_emulator_capabilities = 0
"
test Libvirtd_qemu.lns get conf =
@@ -208,3 +210,5 @@ vnc_allow_host_audio = 1
{ "relaxed_acs_check" = "1" }
{ "#empty" }
{ "vnc_allow_host_audio" = "1" }
+{ "#empty" }
+{ "clear_emulator_capabilities" = "0" }

View File

@ -1,132 +0,0 @@
commit c4896d378b921ba6471562d7b17641be121c19d6
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Thu Apr 15 11:35:07 2010 +0100
Fix CDROM media change for QEMU when using -device syntax
Disk devices in QEMU have two parts, the guest device and the host
backend driver. Historically these two parts have had the same
"unique" name. With the switch to using -device though, they now
have separate names. Thus when changing CDROM media, for guests
using -device syntax, we need to prepend the QEMU_DRIVE_HOST_PREFIX
constant
* src/qemu/qemu_conf.c, src/qemu/qemu_conf.h: Add helper function
qemuDeviceDriveHostAlias() for building a host backend alias
* src/qemu/qemu_driver.c: Use qemuDeviceDriveHostAlias() to determine
the host backend alias for performing eject/change commands in the
monitor
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 1a8b4aa..0cbedf2 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1699,6 +1699,26 @@ static int qemuAssignDeviceDiskAliasLegacy(virDomainDiskDefPtr disk)
}
+char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
+ unsigned long long qemudCmdFlags)
+{
+ char *ret;
+
+ if (qemudCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ if (virAsprintf(&ret, "%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+ } else {
+ if (!(ret = strdup(disk->info.alias))) {
+ virReportOOMError();
+ return NULL;
+ }
+ }
+ return ret;
+}
+
+
/* Names used before -drive supported the id= option */
static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk)
{
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 574709e..b2820f0 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -220,6 +220,9 @@ char * qemuBuildNicStr(virDomainNetDefPtr net,
char * qemuBuildNicDevStr(virDomainNetDefPtr net,
int vlan);
+char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
+ unsigned long long qemudCmdFlags);
+
/* Both legacy & current support */
char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
int bootable,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0189dcf..7d2f3ef 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6552,11 +6552,13 @@ cleanup:
static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
virDomainObjPtr vm,
- virDomainDiskDefPtr disk)
+ virDomainDiskDefPtr disk,
+ unsigned long long qemuCmdFlags)
{
virDomainDiskDefPtr origdisk = NULL;
int i;
int ret;
+ char *driveAlias = NULL;
origdisk = NULL;
for (i = 0 ; i < vm->def->ndisks ; i++) {
@@ -6594,6 +6596,9 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
return -1;
+ if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCmdFlags)))
+ goto error;
+
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (disk->src) {
@@ -6605,10 +6610,10 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
format = origdisk->driverType;
}
ret = qemuMonitorChangeMedia(priv->mon,
- origdisk->info.alias,
+ driveAlias,
disk->src, format);
} else {
- ret = qemuMonitorEjectMedia(priv->mon, origdisk->info.alias);
+ ret = qemuMonitorEjectMedia(priv->mon, driveAlias);
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -6625,11 +6630,14 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
disk->src = NULL;
origdisk->type = disk->type;
+ VIR_FREE(driveAlias);
+
virDomainDiskDefFree(disk);
return ret;
error:
+ VIR_FREE(driveAlias);
if (driver->securityDriver &&
driver->securityDriver->domainRestoreSecurityImageLabel &&
driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
@@ -7434,7 +7442,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- ret = qemudDomainChangeEjectableMedia(driver, vm, dev->data.disk);
+ ret = qemudDomainChangeEjectableMedia(driver, vm,
+ dev->data.disk,
+ qemuCmdFlags);
if (ret == 0)
dev->data.disk = NULL;
break;

View File

@ -1,41 +0,0 @@
From e3c36a2575bc88a16d776693dc39ea01c780b406 Mon Sep 17 00:00:00 2001
From: Jiri Denemark <jdenemar@redhat.com>
Date: Tue, 16 Mar 2010 16:03:59 +0100
Subject: [PATCH] Use fsync() at the end of file allocation instead of O_DSYNC
Instead of opening storage file with O_DSYNC, make sure data are written
to a disk only before we claim allocation has finished.
---
src/storage/storage_backend.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index ec9fc43..7294a00 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -331,6 +331,13 @@ static int createRawFileOpHook(int fd, void *data) {
goto cleanup;
}
}
+
+ if (fsync(fd) < 0) {
+ ret = errno;
+ virReportSystemError(errno, _("cannot sync data to file '%s'"),
+ hdata->vol->target.path);
+ goto cleanup;
+ }
}
cleanup:
@@ -359,7 +366,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
gid_t gid = (vol->target.perms.gid == -1) ? getgid() : vol->target.perms.gid;
if ((createstat = virFileOperation(vol->target.path,
- O_RDWR | O_CREAT | O_EXCL | O_DSYNC,
+ O_RDWR | O_CREAT | O_EXCL,
vol->target.perms.mode, uid, gid,
createRawFileOpHook, &hdata,
VIR_FILE_OP_FORCE_PERMS |
--
1.6.6.1

View File

@ -1,12 +0,0 @@
diff -rup libvirt-0.7.1/src/util/hostusb.c new/src/hostusb.c
--- libvirt-0.7.1/src/util/hostusb.c 2010-06-03 13:51:14.392459000 -0400
+++ new/src/util/hostusb.c 2010-06-03 14:49:11.763379000 -0400
@@ -123,7 +123,7 @@ static int usbFindBusByVendor(virConnect
char *tmpstr = de->d_name;
unsigned found_bus, found_addr;
- if (STREQ(de->d_name, "usb"))
+ if (STRPREFIX(de->d_name, "usb"))
tmpstr += 3;
if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {

View File

@ -1,233 +0,0 @@
From 3a441522017aa9c1b8b54d2ce4569d0f0d96fa72 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 12 Mar 2010 12:36:56 -0500
Subject: [PATCH] qemu: Add some debugging at domain startup
---
src/qemu/qemu_driver.c | 24 +++++++++++++++++++++++-
1 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f8ab545..040d645 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2695,6 +2695,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
FD_ZERO(&keepfd);
+ DEBUG0("Beginning VM startup process");
+
if (virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("VM is already active"));
@@ -2703,22 +2705,27 @@ static int qemudStartVMDaemon(virConnectPtr conn,
/* If you are using a SecurityDriver with dynamic labelling,
then generate a security label for isolation */
+ DEBUG0("Generating domain security label (if required)");
if (driver->securityDriver &&
driver->securityDriver->domainGenSecurityLabel &&
driver->securityDriver->domainGenSecurityLabel(vm) < 0)
return -1;
+ DEBUG0("Generating setting domain security labels (if required)");
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityAllLabel &&
driver->securityDriver->domainSetSecurityAllLabel(vm) < 0)
goto cleanup;
- /* Ensure no historical cgroup for this VM is lieing around bogus settings */
+ /* Ensure no historical cgroup for this VM is lying around bogus
+ * settings */
+ DEBUG0("Ensuring no historical cgroup is lying around");
qemuRemoveCgroup(driver, vm, 1);
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport) {
+ DEBUG0("Determining VNC port");
int port = qemudNextFreeVNCPort(driver);
if (port < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -2735,6 +2742,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ DEBUG0("Creating domain log file");
if ((logfile = qemudLogFD(driver, vm->def->name)) < 0)
goto cleanup;
@@ -2751,14 +2759,17 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ DEBUG0("Determing emulator version");
if (qemudExtractVersionInfo(emulator,
NULL,
&qemuCmdFlags) < 0)
goto cleanup;
+ DEBUG0("Setting up domain cgroup (if required)");
if (qemuSetupCgroup(driver, vm) < 0)
goto cleanup;
+ DEBUG0("Preparing host devices");
if (qemuPrepareHostDevices(driver, vm->def) < 0)
goto cleanup;
@@ -2767,6 +2778,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ DEBUG0("Preparing monitor state");
if (qemuPrepareMonitorChr(driver, priv->monConfig, vm->def->name) < 0)
goto cleanup;
@@ -2798,6 +2810,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
* use in hotplug
*/
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ DEBUG0("Assigning domain PCI addresses");
/* Populate cache with current addresses */
if (priv->pciaddrs) {
qemuDomainPCIAddressSetFree(priv->pciaddrs);
@@ -2816,6 +2829,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
priv->persistentAddrs = 0;
}
+ DEBUG0("Building emulator command line");
vm->def->id = driver->nextvmid++;
if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
priv->monJSON, qemuCmdFlags, &argv, &progenv,
@@ -2899,25 +2913,31 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (ret == -1) /* The VM failed to start */
goto cleanup;
+ DEBUG0("Waiting for monitor to show up");
if (qemudWaitForMonitor(driver, vm, pos) < 0)
goto abort;
+ DEBUG0("Detecting VCPU PIDs");
if (qemuDetectVcpuPIDs(driver, vm) < 0)
goto abort;
+ DEBUG0("Setting CPU affinity");
if (qemudInitCpuAffinity(vm) < 0)
goto abort;
+ DEBUG0("Setting any required VM passwords");
if (qemuInitPasswords(conn, driver, vm, qemuCmdFlags) < 0)
goto abort;
/* If we have -device, then addresses are assigned explicitly.
* If not, then we have to detect dynamic ones here */
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ DEBUG0("Determining domain device PCI addresses");
if (qemuInitPCIAddresses(driver, vm) < 0)
goto abort;
}
+ DEBUG0("Setting initial memory amount");
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuMonitorSetBalloon(priv->mon, vm->def->memory) < 0) {
qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -2925,6 +2945,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
}
if (migrateFrom == NULL) {
+ DEBUG0("Starting domain CPUs");
/* Allow the CPUS to start executing */
if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
if (virGetLastError() == NULL)
@@ -2937,6 +2958,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
qemuDomainObjExitMonitorWithDriver(driver, vm);
+ DEBUG0("Writing domain status to disk");
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
goto abort;
--
1.6.6.1
From 6d5c8a8f51db8ce97ab35ab6022dd5c94ab016b4 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 12 Mar 2010 12:37:52 -0500
Subject: [PATCH] qemu: Fix USB by product with security enabled
We need to call PrepareHostdevs to determine the USB device path before
any security calls. PrepareHostUSBDevices was also incorrectly skipping
all USB devices.
---
src/qemu/qemu_driver.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 040d645..b17d26d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2360,7 +2360,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver ATTRIBUTE_UNUSED,
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
continue;
/* Resolve a vendor/product to bus/device */
@@ -2703,6 +2703,11 @@ static int qemudStartVMDaemon(virConnectPtr conn,
return -1;
}
+ /* Must be run before security labelling */
+ DEBUG0("Preparing host devices");
+ if (qemuPrepareHostDevices(driver, vm->def) < 0)
+ goto cleanup;
+
/* If you are using a SecurityDriver with dynamic labelling,
then generate a security label for isolation */
DEBUG0("Generating domain security label (if required)");
@@ -2769,10 +2774,6 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (qemuSetupCgroup(driver, vm) < 0)
goto cleanup;
- DEBUG0("Preparing host devices");
- if (qemuPrepareHostDevices(driver, vm->def) < 0)
- goto cleanup;
-
if (VIR_ALLOC(priv->monConfig) < 0) {
virReportOOMError();
goto cleanup;
--
1.6.6.1
From 65e97240e6e4606820dd1c42ac172319e0af4d8d Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Mon, 22 Mar 2010 10:45:36 -0400
Subject: [PATCH] security: selinux: Fix crash when releasing non-existent label
This can be triggered by the qemuStartVMDaemon cleanup path if a
VM references a non-existent USB device (by product) in the XML.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
src/security/security_selinux.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 975b315..6680e2d 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -632,7 +632,8 @@ SELinuxReleaseSecurityLabel(virDomainObjPtr vm)
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
- if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
+ if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC ||
+ secdef->label == NULL)
return 0;
context_t con = context_new(secdef->label);
--
1.6.6.1

View File

@ -1,35 +0,0 @@
commit 9d0adf249827dde9e1c0d1c19513cf6018ceb34e
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 19 15:57:56 2010 -0400
daemon: A few initscript corrections
Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=565238
- Avahi service is called 'avahi-daemon'
- chkconfig descriptions must use \ for line continuations
diff --git a/daemon/libvirtd.init.in b/daemon/libvirtd.init.in
index d4dc98b..809433e 100644
--- a/daemon/libvirtd.init.in
+++ b/daemon/libvirtd.init.in
@@ -9,7 +9,7 @@
# Should-Start: $named
# Should-Start: xend
# Should-Start: hal
-# Should-Start: avahi
+# Should-Start: avahi-daemon
# Required-Stop: $network messagebus
# Should-Stop: $named
# Default-Start: 3 4 5
@@ -24,8 +24,8 @@
# libvirtd: guest and virtual network management daemon
#
# chkconfig: 345 97 03
-# description: This is a daemon for managing guest instances
-# and libvirt virtual networks
+# description: This is a daemon for managing guest instances \
+# and libvirt virtual networks \
# See http://libvirt.org
#
# processname: libvirtd

View File

@ -1,65 +0,0 @@
commit e5f31f461f63bbad211e84b810d6ba43a705f9dd
Author: Justin Clift <justin@salasaga.org>
Date: Sun May 30 13:28:42 2010 +1000
Trivial virsh.pod additions --all for "list" command and similar
This is just a trivial patch to virsh.pod (from git master). It adds the
following pieces to the virsh man page:
+ Shows the --inactive and --all optional parameters for the list
command.
Closes Bugzilla #575512, reported by Renich Bon Ciric
https://bugzilla.redhat.com/show_bug.cgi?id=575512
+ Corrects the existing description of the list command, to now say
that only running domains are listed if no domains are specified.
The man page up until this point has said all domains are listed if
no domains are specified, which is incorrect.
+ Adds the "shut off" state to the list of states for the list
command.
+ Adds a missing =back around line 755, that pod2man was complaining
was missing.
diff --git a/tools/virsh.pod b/tools/virsh.pod
index cf7585d..495bb46 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -156,10 +156,10 @@ description see:
L<http://libvirt.org/formatcaps.html>
The XML also show the NUMA topology information if available.
-=item B<list>
+=item B<list> optional I<--inactive> I<--all>
Prints information about one or more domains. If no domains are
-specified it prints out information about all domains.
+specified it prints out information about running domains.
An example format for the list is as follows:
@@ -177,7 +177,7 @@ State is the run state (see below).
B<STATES>
-The State field lists 6 states for a domain, and which ones the
+The State field lists 7 states for a domain, and which ones the
current domain is in.
=over 4
@@ -205,6 +205,11 @@ The domain is in the process of shutting down, i.e. the guest operating system
has been notified and should be in the process of stopping its operations
gracefully.
+=item B<shut off>
+
+The domain is not running. Usually this indicates the domain has been
+shut down completely, or has not been started.
+
=item B<crashed>
The domain has crashed, which is always a violent ending. Usually

View File

@ -1,169 +0,0 @@
commit a83fe2c23efad190a1e00e448f607fe032650fd6
Author: Cole Robinson <crobinso@redhat.com>
Date: Thu May 20 19:31:16 2010 -0400
network: bridge: Don't start network if it collides with host routing
Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=235961
If using the default virtual network, an easy way to lose guest network
connectivity is to install libvirt inside the VM. The autostarted
default network inside the guest collides with host virtual network
routing. This is a long standing issue that has caused users quite a
bit of pain and confusion.
On network startup, parse /proc/net/route and compare the requested
IP+netmask against host routing destinations: if any matches are found,
refuse to start the network.
v2: Drop sscanf, fix a comment typo, comment that function could use
libnl instead of /proc
v3: Consider route netmask. Compare binary data rather than convert to
string.
v4: Return to using sscanf, drop inet functions in favor of virSocket,
parsing safety checks. Don't make parse failures fatal, in case
expected format changes.
v5: Try and continue if we receive unexpected. Delimit parsed lines to
prevent scanning past newline
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 5d7ef19..7ab3f3e 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -57,6 +57,7 @@
#include "iptables.h"
#include "bridge.h"
#include "logging.h"
+#include "util/network.h"
#define NETWORK_PID_DIR LOCAL_STATE_DIR "/run/libvirt/network"
#define NETWORK_STATE_DIR LOCAL_STATE_DIR "/lib/libvirt/network"
@@ -908,6 +909,114 @@ cleanup:
return ret;
}
+#define PROC_NET_ROUTE "/proc/net/route"
+
+/* XXX: This function can be a lot more exhaustive, there are certainly
+ * other scenarios where we can ruin host network connectivity.
+ * XXX: Using a proper library is preferred over parsing /proc
+ */
+static int networkCheckRouteCollision(virNetworkObjPtr network)
+{
+ int ret = -1, len;
+ unsigned int net_dest;
+ char *cur, *buf = NULL;
+ enum {MAX_ROUTE_SIZE = 1024*64};
+ virSocketAddr inaddress, innetmask;
+
+ if (!network->def->ipAddress || !network->def->netmask)
+ return 0;
+
+ if (virSocketParseAddr(network->def->ipAddress, &inaddress, 0) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse IP address '%s'"),
+ network->def->ipAddress);
+ goto error;
+ }
+
+ if (virSocketParseAddr(network->def->netmask, &innetmask, 0) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse netmask '%s'"),
+ network->def->netmask);
+ goto error;
+ }
+
+ if (inaddress.stor.ss_family != AF_INET ||
+ innetmask.stor.ss_family != AF_INET) {
+ /* Only support collision check for IPv4 */
+ goto out;
+ }
+
+ net_dest = (inaddress.inet4.sin_addr.s_addr &
+ innetmask.inet4.sin_addr.s_addr);
+
+ /* Read whole routing table into memory */
+ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
+ goto error;
+
+ /* Dropping the last character shouldn't hurt */
+ if (len > 0)
+ buf[len-1] = '\0';
+
+ VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
+
+ if (!STRPREFIX (buf, "Iface"))
+ goto out;
+
+ /* First line is just headings, skip it */
+ cur = strchr(buf, '\n');
+ if (cur)
+ cur++;
+
+ while (cur) {
+ char iface[17], dest[128], mask[128];
+ unsigned int addr_val, mask_val;
+ int num;
+
+ /* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
+ char *nl = strchr(cur, '\n');
+ if (nl) {
+ *nl++ = '\0';
+ }
+
+ num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
+ iface, dest, mask);
+ cur = nl;
+
+ if (num != 3) {
+ VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
+ continue;
+ }
+
+ if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
+ VIR_DEBUG("Failed to convert network address %s to uint", dest);
+ continue;
+ }
+
+ if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
+ VIR_DEBUG("Failed to convert network mask %s to uint", mask);
+ continue;
+ }
+
+ addr_val &= mask_val;
+
+ if ((net_dest == addr_val) &&
+ (innetmask.inet4.sin_addr.s_addr == mask_val)) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network %s/%s is already in use by "
+ "interface %s"),
+ network->def->ipAddress,
+ network->def->netmask, iface);
+ goto error;
+ }
+ }
+
+out:
+ ret = 0;
+error:
+ VIR_FREE(buf);
+ return ret;
+}
+
static int networkStartNetworkDaemon(struct network_driver *driver,
virNetworkObjPtr network)
{
@@ -919,6 +1028,10 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
return -1;
}
+ /* Check to see if network collides with an existing route */
+ if (networkCheckRouteCollision(network) < 0)
+ return -1;
+
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
virReportSystemError(err,
_("cannot create bridge '%s'"),

View File

@ -1,26 +0,0 @@
commit b7a7b3365145f6e9e434a3265a58666cd2e6d8dd
Author: Guido Günther <agx@sigxcpu.org>
Date: Wed Mar 17 21:04:11 2010 +0100
Don't crash without a security driver
"virsh dominfo <vm>" crashes if there's no primary security driver set
since we only intialize the secmodel.model and secmodel.doi if we have
one. Attached patch checks for securityPrimaryDriver instead of
securityDriver since the later is always set in qemudSecurityInit().
Closes: http://bugs.debian.org/574359
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1f2b11d..257f914 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4979,7 +4979,7 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn,
int ret = 0;
qemuDriverLock(driver);
- if (!driver->securityDriver) {
+ if (!driver->securityPrimaryDriver) {
memset(secmodel, 0, sizeof (*secmodel));
goto cleanup;
}

View File

@ -1,77 +0,0 @@
commit 74c7a3463d18a530d6d749d0199061b5d3f17faa
Author: Cole Robinson <crobinso@redhat.com>
Date: Tue May 11 14:44:34 2010 -0400
node_device: udev: Fix PCI product/vendor swappage
Product and vendor values were swapped in the XML, which made virt-manager
PCI device listing kinda useless.
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index bcfe991..4a9d65f 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -382,8 +382,8 @@ static int udevTranslatePCIIds(unsigned int vendor,
/* pci_get_strings returns void */
pci_get_strings(&m,
- &vendor_name,
&device_name,
+ &vendor_name,
NULL,
NULL);
commit 75d88455f54088f88bc7a503da0a4cd413ef7b95
Author: Klaus Ethgen <Klaus@Ethgen.de>
Date: Tue Apr 27 09:20:47 2010 +0200
The base used for conversion of USB values should be 16 not 10.
Signed-off-by: Guido Günther <agx@sigxcpu.org>
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index b12a49e..3a5a7e2 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -548,8 +548,6 @@ out:
}
-/* XXX Is 10 the correct base for the Number/Class/SubClass/Protocol
- * conversions? */
static int udevProcessUSBInterface(struct udev_device *device,
virNodeDeviceDefPtr def)
{
@@ -559,28 +557,28 @@ static int udevProcessUSBInterface(struct udev_device *device,
if (udevGetUintSysfsAttr(device,
"bInterfaceNumber",
&data->usb_if.number,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
if (udevGetUintSysfsAttr(device,
"bInterfaceClass",
&data->usb_if._class,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
if (udevGetUintSysfsAttr(device,
"bInterfaceSubClass",
&data->usb_if.subclass,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
if (udevGetUintSysfsAttr(device,
"bInterfaceProtocol",
&data->usb_if.protocol,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}

View File

@ -1,50 +0,0 @@
commit e984019688509605966c03cd77f4591d2cc222d3
Author: Cole Robinson <crobinso@redhat.com>
Date: Fri Apr 30 18:14:35 2010 +0200
domain: Fix PCI address decimal parsing regression
<hostdev> address parsing previously attempted to detect the number
base: currently it is hardcoded to base 16, which can break PCI
assignment via virt-manager. Revert to the previous behavior.
* src/conf/domain_conf.c: virDomainDevicePCIAddressParseXML, switch to
virStrToLong_ui(bus, NULL, 0, ...) to autodetect base
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 1607e8b..546ddf2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1079,28 +1079,28 @@ virDomainDevicePCIAddressParseXML(xmlNodePtr node,
function = virXMLPropString(node, "function");
if (domain &&
- virStrToLong_ui(domain, NULL, 16, &addr->domain) < 0) {
+ virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'domain' attribute"));
goto cleanup;
}
if (bus &&
- virStrToLong_ui(bus, NULL, 16, &addr->bus) < 0) {
+ virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'bus' attribute"));
goto cleanup;
}
if (slot &&
- virStrToLong_ui(slot, NULL, 16, &addr->slot) < 0) {
+ virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'slot' attribute"));
goto cleanup;
}
if (function &&
- virStrToLong_ui(function, NULL, 16, &addr->function) < 0) {
+ virStrToLong_ui(function, NULL, 0, &addr->function) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'function' attribute"));
goto cleanup;

View File

@ -1,108 +0,0 @@
commit 83be64034a0b530c904ceb4fd1ed1c10b5cdf4bf
Author: Cole Robinson <crobinso@redhat.com>
Date: Mon May 17 10:15:53 2010 -0400
qemu: Report cmdline output if VM dies early
qemuReadLogOutput early VM death detection is racy and won't always work.
Startup then errors when connecting to the VM monitor. This won't report
the emulator cmdline output which is typically the most useful diagnostic.
Check if the VM has died at the very end of the monitor connection step,
and if so, report the cmdline output.
See also: https://bugzilla.redhat.com/show_bug.cgi?id=581381
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ab6bec8..582fdee 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2034,39 +2034,47 @@ static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED)
VIR_FREE(payload);
}
+static void
+qemuReadLogFD(int logfd, char *buf, int maxlen, int off)
+{
+ int ret;
+ char *tmpbuf = buf + off;
+
+ ret = saferead(logfd, tmpbuf, maxlen - off - 1);
+ if (ret < 0) {
+ ret = 0;
+ }
+
+ tmpbuf[ret] = '\0';
+}
+
static int
qemudWaitForMonitor(struct qemud_driver* driver,
virDomainObjPtr vm, off_t pos)
{
- char buf[4096]; /* Plenty of space to get startup greeting */
+ char buf[4096] = ""; /* Plenty of space to get startup greeting */
int logfd;
int ret = -1;
+ virHashTablePtr paths = NULL;
- if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos))
- < 0)
+ if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos)) < 0)
return -1;
- ret = qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
- qemudFindCharDevicePTYs,
- "console", 30);
- if (close(logfd) < 0) {
- char ebuf[4096];
- VIR_WARN(_("Unable to close logfile: %s"),
- virStrerror(errno, ebuf, sizeof ebuf));
- }
-
- if (ret < 0)
- return -1;
+ if (qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
+ qemudFindCharDevicePTYs,
+ "console", 30) < 0)
+ goto closelog;
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
- if (qemuConnectMonitor(driver, vm) < 0)
- return -1;
+ if (qemuConnectMonitor(driver, vm) < 0) {
+ goto cleanup;
+ }
/* Try to get the pty path mappings again via the monitor. This is much more
* reliable if it's available.
* Note that the monitor itself can be on a pty, so we still need to try the
* log output method. */
- virHashTablePtr paths = virHashCreate(0);
+ paths = virHashCreate(0);
if (paths == NULL) {
virReportOOMError();
goto cleanup;
@@ -2087,6 +2095,23 @@ cleanup:
virHashFree(paths, qemudFreePtyPath);
}
+ if (kill(vm->pid, 0) == -1 && errno == ESRCH) {
+ /* VM is dead, any other error raised in the interim is probably
+ * not as important as the qemu cmdline output */
+ qemuReadLogFD(logfd, buf, sizeof(buf), strlen(buf));
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("process exited while connecting to monitor: %s"),
+ buf);
+ ret = -1;
+ }
+
+closelog:
+ if (close(logfd) < 0) {
+ char ebuf[4096];
+ VIR_WARN(_("Unable to close logfile: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ }
+
return ret;
}

View File

@ -1,155 +0,0 @@
diff -rup libvirt-0.7.7/src/conf/storage_conf.c new/src/conf/storage_conf.c
--- libvirt-0.7.7/src/conf/storage_conf.c 2010-03-05 09:46:29.000000000 -0500
+++ new/src/conf/storage_conf.c 2010-06-17 12:28:44.319588000 -0400
@@ -601,6 +601,7 @@ virStoragePoolDefParseXML(xmlXPathContex
xmlNodePtr source_node;
char *type = NULL;
char *uuid = NULL;
+ char *tmppath;
if (VIR_ALLOC(ret) < 0) {
virReportOOMError();
@@ -698,11 +699,16 @@ virStoragePoolDefParseXML(xmlXPathContex
}
}
- if ((ret->target.path = virXPathString("string(./target/path)", ctxt)) == NULL) {
+ if ((tmppath = virXPathString("string(./target/path)", ctxt)) == NULL) {
virStorageReportError(VIR_ERR_XML_ERROR,
"%s", _("missing storage pool target path"));
goto cleanup;
}
+ ret->target.path = virFileSanitizePath(tmppath);
+ VIR_FREE(tmppath);
+ if (!ret->target.path)
+ goto cleanup;
+
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
"./target/permissions", 0700) < 0)
diff -rup libvirt-0.7.7/src/libvirt_private.syms new/src/libvirt_private.syms
--- libvirt-0.7.7/src/libvirt_private.syms 2010-03-05 10:45:23.000000000 -0500
+++ new/src/libvirt_private.syms 2010-06-17 12:28:44.334585000 -0400
@@ -582,6 +582,7 @@ virFileReadLimFD;
virFilePid;
virFileReadPid;
virFileLinkPointsTo;
+virFileSanitizePath;
virParseNumber;
virAsprintf;
virRun;
diff -rup libvirt-0.7.7/src/storage/storage_driver.c new/src/storage/storage_driver.c
--- libvirt-0.7.7/src/storage/storage_driver.c 2010-03-05 09:46:29.000000000 -0500
+++ new/src/storage/storage_driver.c 2010-06-17 12:28:44.346586000 -0400
@@ -1200,6 +1200,11 @@ storageVolumeLookupByPath(virConnectPtr
virStorageDriverStatePtr driver = conn->storagePrivateData;
unsigned int i;
virStorageVolPtr ret = NULL;
+ char *cleanpath;
+
+ cleanpath = virFileSanitizePath(path);
+ if (!cleanpath)
+ return NULL;
storageDriverLock(driver);
for (i = 0 ; i < driver->pools.count && !ret ; i++) {
@@ -1209,7 +1214,7 @@ storageVolumeLookupByPath(virConnectPtr
const char *stable_path;
stable_path = virStorageBackendStablePath(driver->pools.objs[i],
- path);
+ cleanpath);
/*
* virStorageBackendStablePath already does
* virStorageReportError if it fails; we just need to keep
@@ -1238,6 +1243,7 @@ storageVolumeLookupByPath(virConnectPtr
"%s", _("no storage vol with matching path"));
cleanup:
+ VIR_FREE(cleanpath);
storageDriverUnlock(driver);
return ret;
}
diff -rup libvirt-0.7.7/src/util/util.c new/src/util/util.c
--- libvirt-0.7.7/src/util/util.c 2010-03-03 05:48:25.000000000 -0500
+++ new/src/util/util.c 2010-06-17 12:28:44.357588000 -0400
@@ -1867,6 +1867,55 @@ int virFileAbsPath(const char *path, cha
return 0;
}
+/* Remove spurious / characters from a path. The result must be freed */
+char *
+virFileSanitizePath(const char *path)
+{
+ const char *cur = path;
+ char *cleanpath;
+ int idx = 0;
+
+ cleanpath = strdup(path);
+ if (!cleanpath) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ /* Need to sanitize:
+ * // -> //
+ * /// -> /
+ * /../foo -> /../foo
+ * /foo///bar/ -> /foo/bar
+ */
+
+ /* Starting with // is valid posix, but ///foo == /foo */
+ if (cur[0] == '/' && cur[1] == '/' && cur[2] != '/') {
+ idx = 2;
+ cur += 2;
+ }
+
+ /* Sanitize path in place */
+ while (*cur != '\0') {
+ if (*cur != '/') {
+ cleanpath[idx++] = *cur++;
+ continue;
+ }
+
+ /* Skip all extra / */
+ while (*++cur == '/')
+ continue;
+
+ /* Don't add a trailing / */
+ if (idx != 0 && *cur == '\0')
+ break;
+
+ cleanpath[idx++] = '/';
+ }
+ cleanpath[idx] = '\0';
+
+ return cleanpath;
+}
+
/* Like strtol, but produce an "int" result, and check more carefully.
Return 0 upon success; return -1 to indicate failure.
When END_PTR is NULL, the byte after the final valid digit must be NUL.
diff -rup libvirt-0.7.7/src/util/util.h new/src/util/util.h
--- libvirt-0.7.7/src/util/util.h 2010-02-19 12:14:07.000000000 -0500
+++ new/src/util/util.h 2010-06-17 12:28:44.364585000 -0400
@@ -109,6 +109,8 @@ char *virFindFileInPath(const char *file
int virFileExists(const char *path);
+char *virFileSanitizePath(const char *path);
+
enum {
VIR_FILE_OP_NONE = 0,
VIR_FILE_OP_AS_UID = (1 << 0),
diff -rup libvirt-0.7.7/tests/storagepoolxml2xmlin/pool-dir.xml new/tests/storagepoolxml2xmlin/pool-dir.xml
--- libvirt-0.7.7/tests/storagepoolxml2xmlin/pool-dir.xml 2009-12-22 04:37:57.000000000 -0500
+++ new/tests/storagepoolxml2xmlin/pool-dir.xml 2010-06-17 12:28:44.367585000 -0400
@@ -7,7 +7,7 @@
<source>
</source>
<target>
- <path>/var/lib/libvirt/images</path>
+ <path>///var/////lib/libvirt/images//</path>
<permissions>
<mode>0700</mode>
<owner>0</owner>

View File

@ -1,87 +0,0 @@
From 3f1aa08af6580c215d973bc6bf57f505dbf8b926 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 12 Mar 2010 13:38:39 -0500
Subject: [PATCH] security: Set permissions for kernel/initrd
Fixes URL installs when running virt-install as root on Fedora.
---
src/qemu/qemu_security_dac.c | 21 +++++++++++++++++++++
src/security/security_selinux.c | 16 ++++++++++++++++
2 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
index 6911f48..1883fbe 100644
--- a/src/qemu/qemu_security_dac.c
+++ b/src/qemu/qemu_security_dac.c
@@ -332,6 +332,15 @@ qemuSecurityDACRestoreSecurityAllLabel(virDomainObjPtr vm)
vm->def->disks[i]) < 0)
rc = -1;
}
+
+ if (vm->def->os.kernel &&
+ qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
+ rc = -1;
+
+ if (vm->def->os.initrd &&
+ qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
+ rc = -1;
+
return rc;
}
@@ -356,6 +365,18 @@ qemuSecurityDACSetSecurityAllLabel(virDomainObjPtr vm)
return -1;
}
+ if (vm->def->os.kernel &&
+ qemuSecurityDACSetOwnership(vm->def->os.kernel,
+ driver->user,
+ driver->group) < 0)
+ return -1;
+
+ if (vm->def->os.initrd &&
+ qemuSecurityDACSetOwnership(vm->def->os.initrd,
+ driver->user,
+ driver->group) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index b2c8581..975b315 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -616,6 +616,14 @@ SELinuxRestoreSecurityAllLabel(virDomainObjPtr vm)
rc = -1;
}
+ if (vm->def->os.kernel &&
+ SELinuxRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
+ rc = -1;
+
+ if (vm->def->os.initrd &&
+ SELinuxRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
+ rc = -1;
+
return rc;
}
@@ -736,6 +744,14 @@ SELinuxSetSecurityAllLabel(virDomainObjPtr vm)
return -1;
}
+ if (vm->def->os.kernel &&
+ SELinuxSetFilecon(vm->def->os.kernel, default_content_context) < 0)
+ return -1;
+
+ if (vm->def->os.initrd &&
+ SELinuxSetFilecon(vm->def->os.initrd, default_content_context) < 0)
+ return -1;
+
return 0;
}
--
1.6.6.1

View File

@ -1,66 +0,0 @@
commit 07f6c3a95f1caca368c8723b5b0a25ae2faa1ffe
Author: David Allan <dallan@redhat.com>
Date: Thu May 27 10:44:02 2010 -0400
v2 of Cole's wlan support
* Incorporated Jim's feedback (v1 & v2)
* Moved case of DEVTYPE == "wlan" up as it's definitive that we have a network interface.
* Made comment more detailed about the wired case to explain better
how it differentiates between wired network interfaces and USB
devices.
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index f0485f1..c437861 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -597,8 +597,15 @@ static int udevProcessNetworkInterface(struct udev_device *device,
virNodeDeviceDefPtr def)
{
int ret = -1;
+ const char *devtype = udev_device_get_devtype(device);
union _virNodeDevCapData *data = &def->caps->data;
+ if (devtype && STREQ(devtype, "wlan")) {
+ data->net.subtype = VIR_NODE_DEV_CAP_NET_80211;
+ } else {
+ data->net.subtype = VIR_NODE_DEV_CAP_NET_80203;
+ }
+
if (udevGetStringProperty(device,
"INTERFACE",
&data->net.ifname) == PROPERTY_ERROR) {
@@ -1074,6 +1081,8 @@ static int udevGetDeviceType(struct udev_device *device,
int ret = 0;
devtype = udev_device_get_devtype(device);
+ VIR_DEBUG("Found device type '%s' for device '%s'",
+ NULLSTR(devtype), udev_device_get_sysname(device));
if (devtype != NULL && STREQ(devtype, "usb_device")) {
*type = VIR_NODE_DEV_CAP_USB_DEV;
@@ -1105,13 +1114,20 @@ static int udevGetDeviceType(struct udev_device *device,
goto out;
}
+ if (devtype != NULL && STREQ(devtype, "wlan")) {
+ *type = VIR_NODE_DEV_CAP_NET;
+ goto out;
+ }
+
if (udevGetUintProperty(device, "PCI_CLASS", &tmp, 16) == PROPERTY_FOUND) {
*type = VIR_NODE_DEV_CAP_PCI_DEV;
goto out;
}
- /* It does not appear that network interfaces set the device type
- * property. */
+ /* It does not appear that wired network interfaces set the
+ * DEVTYPE property. USB devices also have an INTERFACE property,
+ * but they do set DEVTYPE, so if devtype is NULL and the
+ * INTERFACE property exists, we have a network device. */
if (devtype == NULL &&
udevGetStringProperty(device,
"INTERFACE",

View File

@ -0,0 +1,356 @@
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

@ -0,0 +1,159 @@
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

@ -0,0 +1,585 @@
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

@ -0,0 +1,285 @@
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

@ -0,0 +1,170 @@
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

@ -0,0 +1,506 @@
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

@ -0,0 +1,468 @@
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

@ -0,0 +1,94 @@
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

@ -0,0 +1,291 @@
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

@ -0,0 +1,165 @@
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

@ -0,0 +1,265 @@
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

View File

@ -61,6 +61,9 @@
%define with_udev 0%{!?_without_udev:0}
%define with_hal 0%{!?_without_hal:0}
%define with_yajl 0%{!?_without_yajl:0}
%define with_nwfilter 0%{!?_without_nwfilter:0}
%define with_libpcap 0%{!?_without_libpcap:0}
%define with_macvtap 0%{!?_without_macvtap:0}
# Non-server/HV driver defaults which are always enabled
%define with_python 0%{!?_without_python:1}
@ -147,6 +150,19 @@
%define with_yajl 0%{!?_without_yajl:%{server_drivers}}
%endif
# Enable libpcap library
%if %{with_qemu}
%define with_nwfilter 0%{!?_without_nwfilter:%{server_drivers}}
%define with_libpcap 0%{!?_without_libpcap:%{server_drivers}}
%define with_macvtap 0%{!?_without_macvtap:%{server_drivers}}
%endif
%if %{with_macvtap}
%define with_libnl 1
%else
%define with_libnl 0
%endif
# Force QEMU to run as non-root
%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
%define qemu_user qemu
@ -168,49 +184,31 @@
Summary: Library providing a simple API virtualization
Name: libvirt
Version: 0.7.7
Release: 5%{?dist}%{?extra_release}
Version: 0.8.2
Release: 1%{?dist}%{?extra_release}
License: LGPLv2+
Group: Development/Libraries
Source: http://libvirt.org/sources/libvirt-%{version}.tar.gz
# Fix USB devices by product with security enabled (bz 574136)
Patch1: %{name}-%{version}-fix-usb-product.patch
# Set kernel/initrd in security driver, fixes some URL installs (bz 566425)
Patch2: %{name}-%{version}-set-kernel-perms.patch
# Fix slow storage volume allocation (bz 582356)
Patch3: %{name}-%{version}-fix-slow-dsync.patch
# Fix nodedev XML conversion errors (bz 591262)
Patch4: %{name}-%{version}-nodedev-conversions.patch
# Fix PCI xml decimal parsing (bz 582752)
Patch5: %{name}-%{version}-pci-decimal-parsing.patch
# Fix CDROM media connect/eject (bz 582005)
Patch6: %{name}-%{version}-fix-cdrom-change.patch
# Always report qemu startup output on error (bz 581381)
Patch7: %{name}-%{version}-qemu-startup-output.patch
# Fix crash from 'virsh dominfo' if secdriver disabled (bz 581166)
Patch8: %{name}-%{version}-no-secdriver-crash.patch
# Add qemu.conf options for audio workaround
Patch9: %{name}-%{version}-audio-config.patch
# Fix parsing certain USB sysfs files (bz 598272)
Patch10: %{name}-%{version}-fix-usb-parsing.patch
# Sanitize pool target paths (bz 494005)
Patch11: %{name}-%{version}-sanitize-pool.patch
# Add qemu.conf for clear emulator capabilities
Patch12: %{name}-%{version}-caps-option.patch
# Prevent libvirtd inside a VM from breaking network access (bz 235961)
Patch13: %{name}-%{version}-network-collision.patch
# Mention --all in 'virsh list' docs (bz 575512)
Patch14: %{name}-%{version}-man-page-list.patch
# Initscript fixes (bz 565238)
Patch15: %{name}-%{version}-init-fixes.patch
# List wireless interfaces via nodedev-list (bz 596928)
Patch16: %{name}-%{version}-udev-wireless.patch
# Patches 1-> 11 CVE-2010-2237, 2238, 2239
Patch1: libvirt-0.8.2-01-extract-backing-store-format.patch
Patch2: libvirt-0.8.2-02-remove-type-field.patch
Patch3: libvirt-0.8.2-03-refactor-metadata-extract.patch
Patch4: libvirt-0.8.2-04-require-storage-format.patch
Patch5: libvirt-0.8.2-05-disk-path-iterator.patch
Patch6: libvirt-0.8.2-06-use-disk-iterator.patch
Patch7: libvirt-0.8.2-07-secdriver-params.patch
Patch8: libvirt-0.8.2-08-disable-disk-probing.patch
Patch9: libvirt-0.8.2-09-set-default-driver.patch
Patch10: libvirt-0.8.2-10-qemu-img-format-handling.patch
Patch11: libvirt-0.8.2-11-storage-vol-backing.patch
# CVE-2010-2242
Patch12: libvirt-0.8.2-apply-iptables-sport-mapping.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
URL: http://libvirt.org/
BuildRequires: python-devel
# The client side, i.e. shared libs and virsh are in a subpackage
Requires: libvirt-client = %{version}-%{release}
Requires: %{name}-client = %{version}-%{release}
# Used by many of the drivers, so turn it on whenever the
# daemon is present
@ -221,6 +219,11 @@ Requires: bridge-utils
Requires: dnsmasq
Requires: iptables
%endif
%if %{with_nwfilter}
Requires: ebtables
Requires: iptables
Requires: iptables-ipv6
%endif
# needed for device enumeration
%if %{with_hal}
Requires: hal
@ -280,7 +283,7 @@ Requires: device-mapper
BuildRequires: xen-devel
%endif
%if %{with_one}
BuildRequires: xmlrpc-c-devel >= 1.14.0 xmlrpc-c-client
BuildRequires: xmlrpc-c-devel >= 1.14.0
%endif
BuildRequires: libxml2-devel
BuildRequires: xhtml1-dtds
@ -298,6 +301,12 @@ BuildRequires: libpciaccess-devel >= 0.10.9
%if %{with_yajl}
BuildRequires: yajl-devel
%endif
%if %{with_libpcap}
BuildRequires: libpcap-devel
%endif
%if %{with_libnl}
BuildRequires: libnl-devel
%endif
%if %{with_avahi}
BuildRequires: avahi-devel
%endif
@ -370,6 +379,9 @@ BuildRequires: libssh2-devel
%if %{with_netcf}
BuildRequires: netcf-devel >= 0.1.4
%endif
%if %{with_esx}
BuildRequires: libcurl-devel
%endif
# Fedora build root suckage
BuildRequires: gawk
@ -401,7 +413,7 @@ virtualization capabilities of recent versions of Linux (and other OSes).
%package devel
Summary: Libraries, includes, etc. to compile with the libvirt library
Group: Development/Libraries
Requires: libvirt-client = %{version}-%{release}
Requires: %{name}-client = %{version}-%{release}
Requires: pkgconfig
%if %{with_xen}
Requires: xen-devel
@ -415,7 +427,7 @@ the virtualization capabilities of recent versions of Linux (and other OSes).
%package python
Summary: Python bindings for the libvirt library
Group: Development/Libraries
Requires: libvirt-client = %{version}-%{release}
Requires: %{name}-client = %{version}-%{release}
%description python
The libvirt-python package contains a module that permits applications
@ -438,10 +450,6 @@ of recent versions of Linux (and other OSes).
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%build
%if ! %{with_xen}
@ -556,6 +564,14 @@ of recent versions of Linux (and other OSes).
%define _without_yajl --without-yajl
%endif
%if ! %{with_libpcap}
%define _without_libpcap --without-libpcap
%endif
%if ! %{with_macvtap}
%define _without_macvtap --without-macvtap
%endif
%configure %{?_without_xen} \
%{?_without_qemu} \
%{?_without_openvz} \
@ -584,6 +600,8 @@ of recent versions of Linux (and other OSes).
%{?_without_hal} \
%{?_without_udev} \
%{?_without_yajl} \
%{?_without_libpcap} \
%{?_without_macvtap} \
--with-qemu-user=%{qemu_user} \
--with-qemu-group=%{qemu_group} \
--with-init-script=redhat \
@ -595,7 +613,7 @@ gzip -9 ChangeLog
rm -fr %{buildroot}
%makeinstall
for i in domain-events/events-c dominfo domsuspend hellolibvirt python
for i in domain-events/events-c dominfo domsuspend hellolibvirt python xml/nwfilter
do
(cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in)
done
@ -605,6 +623,7 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.la
rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.a
%if %{with_network}
install -d -m 0755 $RPM_BUILD_ROOT%{_datadir}/lib/libvirt/dnsmasq/
# We don't want to install /etc/libvirt/qemu/networks in the main %files list
# because if the admin wants to delete the default network completely, we don't
# want to end up re-incarnating it on every RPM upgrade.
@ -638,11 +657,20 @@ rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/libvirt-python-%{version}
rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/libvirt-%{version}
%endif
%if ! %{with_libvirtd}
rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/nwfilter
%endif
%if ! %{with_qemu}
rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu.conf
rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.qemu
%endif
%if ! %{with_lxc}
rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/lxc.conf
rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.lxc
%endif
%if ! %{with_uml}
rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.uml
%endif
%if %{with_libvirtd}
@ -652,6 +680,23 @@ chmod 0644 $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/libvirtd
%clean
rm -fr %{buildroot}
%check
cd tests
# These 3 tests don't current work in a mock build root
for i in nodeinfotest daemon-conf seclabeltest
do
rm -f $i
printf "#!/bin/sh\nexit 0\n" > $i
chmod +x $i
done
# Temp hack till we figure out why its broken on ppc
%ifarch ppc
rm -f nwfilterxml2xmltest
printf "#!/bin/sh\nexit 0\n" > nwfilterxml2xmltest
chmod +x nwfilterxml2xmltest
%endif
make check
%pre
%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
# Normally 'setup' adds this in /etc/passwd, but this is
@ -672,7 +717,7 @@ getent passwd qemu >/dev/null || \
# or on the first upgrade from a non-network aware libvirt only.
# We check this by looking to see if the daemon is already installed
/sbin/chkconfig --list libvirtd 1>/dev/null 2>&1
if [ $? != 0 -a ! -f %{_sysconfdir}/libvirt/qemu/networks/default.xml ]
if test $? != 0 && test ! -f %{_sysconfdir}/libvirt/qemu/networks/default.xml
then
UUID=`/usr/bin/uuidgen`
sed -e "s,</name>,</name>\n <uuid>$UUID</uuid>," \
@ -696,7 +741,22 @@ if [ $1 = 0 ]; then
fi
%endif
%post client -p /sbin/ldconfig
%preun client
if [ $1 = 0 ]; then
/sbin/chkconfig --del libvirt-guests
rm -f /var/lib/libvirt/libvirt-guests
fi
%post client
/sbin/ldconfig
/sbin/chkconfig --add libvirt-guests
if [ $1 -ge 1 ]; then
# this doesn't do anything but allowing for libvirt-guests to be
# stopped on the first shutdown
/sbin/service libvirt-guests start > /dev/null 2>&1 || true
fi
%postun client -p /sbin/ldconfig
@ -713,19 +773,26 @@ fi
%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/autostart
%endif
%dir %attr(0700, root, root) %{_sysconfdir}/libvirt/nwfilter/
%{_sysconfdir}/libvirt/nwfilter/*.xml
%{_sysconfdir}/rc.d/init.d/libvirtd
%config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
%config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/lxc/
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/uml/
%if %{with_qemu}
%config(noreplace) %{_sysconfdir}/libvirt/qemu.conf
%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.qemu
%endif
%if %{with_lxc}
%config(noreplace) %{_sysconfdir}/libvirt/lxc.conf
%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.lxc
%endif
%if %{with_uml}
%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.uml
%endif
%dir %{_datadir}/libvirt/
@ -758,6 +825,7 @@ fi
%if %{with_network}
%dir %{_localstatedir}/run/libvirt/network/
%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt/network/
%dir %attr(0755, root, root) %{_localstatedir}/lib/libvirt/dnsmasq/
%endif
%if %{with_qemu}
@ -813,6 +881,7 @@ fi
%dir %{_datadir}/libvirt/schemas/
%{_datadir}/libvirt/schemas/domain.rng
%{_datadir}/libvirt/schemas/domainsnapshot.rng
%{_datadir}/libvirt/schemas/network.rng
%{_datadir}/libvirt/schemas/storagepool.rng
%{_datadir}/libvirt/schemas/storagevol.rng
@ -821,9 +890,14 @@ fi
%{_datadir}/libvirt/schemas/interface.rng
%{_datadir}/libvirt/schemas/secret.rng
%{_datadir}/libvirt/schemas/storageencryption.rng
%{_datadir}/libvirt/schemas/nwfilter.rng
%{_datadir}/libvirt/cpu_map.xml
%{_sysconfdir}/rc.d/init.d/libvirt-guests
%config(noreplace) %{_sysconfdir}/sysconfig/libvirt-guests
%dir %attr(0700, root, root) %{_localstatedir}/lib/libvirt
%if %{with_sasl}
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
%endif

View File

@ -1 +1 @@
5f315b0bf20e3964f7657ba1e630cd67 libvirt-0.7.7.tar.gz
14164638fe0e7f65e425acc85dabc517 libvirt-0.8.2.tar.gz