From f75a9b8ec93448970a388fdde3091236be7fae8c Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 12 Jul 2010 15:47:10 +0000 Subject: [PATCH] Update to 0.8.2 release. Fix CVE-2010-2237, CVE-2010-2238, CVE-2010-2239, CVE-2010-2242 --- .cvsignore | 13 - libvirt-0.7.7-audio-config.patch | 163 --- libvirt-0.7.7-caps-option.patch | 110 -- libvirt-0.7.7-fix-cdrom-change.patch | 132 -- libvirt-0.7.7-fix-slow-dsync.patch | 41 - libvirt-0.7.7-fix-usb-parsing.patch | 12 - libvirt-0.7.7-fix-usb-product.patch | 233 ---- libvirt-0.7.7-init-fixes.patch | 35 - libvirt-0.7.7-man-page-list.patch | 65 - libvirt-0.7.7-network-collision.patch | 169 --- libvirt-0.7.7-no-secdriver-crash.patch | 26 - libvirt-0.7.7-nodedev-conversions.patch | 77 -- libvirt-0.7.7-pci-decimal-parsing.patch | 50 - libvirt-0.7.7-qemu-startup-output.patch | 108 -- libvirt-0.7.7-sanitize-pool.patch | 155 --- libvirt-0.7.7-set-kernel-perms.patch | 87 -- libvirt-0.7.7-udev-wireless.patch | 66 - ....8.2-01-extract-backing-store-format.patch | 356 +++++ libvirt-0.8.2-02-remove-type-field.patch | 159 +++ ...t-0.8.2-03-refactor-metadata-extract.patch | 585 +++++++++ libvirt-0.8.2-04-require-storage-format.patch | 285 ++++ libvirt-0.8.2-05-disk-path-iterator.patch | 170 +++ libvirt-0.8.2-06-use-disk-iterator.patch | 506 ++++++++ libvirt-0.8.2-07-secdriver-params.patch | 1152 +++++++++++++++++ libvirt-0.8.2-08-disable-disk-probing.patch | 468 +++++++ libvirt-0.8.2-09-set-default-driver.patch | 94 ++ ...rt-0.8.2-10-qemu-img-format-handling.patch | 291 +++++ libvirt-0.8.2-11-storage-vol-backing.patch | 165 +++ ...t-0.8.2-apply-iptables-sport-mapping.patch | 265 ++++ libvirt.spec | 166 ++- sources | 2 +- 31 files changed, 4617 insertions(+), 1589 deletions(-) delete mode 100644 libvirt-0.7.7-audio-config.patch delete mode 100644 libvirt-0.7.7-caps-option.patch delete mode 100644 libvirt-0.7.7-fix-cdrom-change.patch delete mode 100644 libvirt-0.7.7-fix-slow-dsync.patch delete mode 100644 libvirt-0.7.7-fix-usb-parsing.patch delete mode 100644 libvirt-0.7.7-fix-usb-product.patch delete mode 100644 libvirt-0.7.7-init-fixes.patch delete mode 100644 libvirt-0.7.7-man-page-list.patch delete mode 100644 libvirt-0.7.7-network-collision.patch delete mode 100644 libvirt-0.7.7-no-secdriver-crash.patch delete mode 100644 libvirt-0.7.7-nodedev-conversions.patch delete mode 100644 libvirt-0.7.7-pci-decimal-parsing.patch delete mode 100644 libvirt-0.7.7-qemu-startup-output.patch delete mode 100644 libvirt-0.7.7-sanitize-pool.patch delete mode 100644 libvirt-0.7.7-set-kernel-perms.patch delete mode 100644 libvirt-0.7.7-udev-wireless.patch create mode 100644 libvirt-0.8.2-01-extract-backing-store-format.patch create mode 100644 libvirt-0.8.2-02-remove-type-field.patch create mode 100644 libvirt-0.8.2-03-refactor-metadata-extract.patch create mode 100644 libvirt-0.8.2-04-require-storage-format.patch create mode 100644 libvirt-0.8.2-05-disk-path-iterator.patch create mode 100644 libvirt-0.8.2-06-use-disk-iterator.patch create mode 100644 libvirt-0.8.2-07-secdriver-params.patch create mode 100644 libvirt-0.8.2-08-disable-disk-probing.patch create mode 100644 libvirt-0.8.2-09-set-default-driver.patch create mode 100644 libvirt-0.8.2-10-qemu-img-format-handling.patch create mode 100644 libvirt-0.8.2-11-storage-vol-backing.patch create mode 100644 libvirt-0.8.2-apply-iptables-sport-mapping.patch diff --git a/.cvsignore b/.cvsignore index 4904e96..55e6af8 100644 --- a/.cvsignore +++ b/.cvsignore @@ -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 diff --git a/libvirt-0.7.7-audio-config.patch b/libvirt-0.7.7-audio-config.patch deleted file mode 100644 index 7e63dfb..0000000 --- a/libvirt-0.7.7-audio-config.patch +++ /dev/null @@ -1,163 +0,0 @@ -commit 377bc412ce10845930346744e30fe9c4790e5e63 -Author: Cole Robinson -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 -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 -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" } diff --git a/libvirt-0.7.7-caps-option.patch b/libvirt-0.7.7-caps-option.patch deleted file mode 100644 index afb660b..0000000 --- a/libvirt-0.7.7-caps-option.patch +++ /dev/null @@ -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" } diff --git a/libvirt-0.7.7-fix-cdrom-change.patch b/libvirt-0.7.7-fix-cdrom-change.patch deleted file mode 100644 index 0a61574..0000000 --- a/libvirt-0.7.7-fix-cdrom-change.patch +++ /dev/null @@ -1,132 +0,0 @@ -commit c4896d378b921ba6471562d7b17641be121c19d6 -Author: Daniel P. Berrange -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; diff --git a/libvirt-0.7.7-fix-slow-dsync.patch b/libvirt-0.7.7-fix-slow-dsync.patch deleted file mode 100644 index f9bedc7..0000000 --- a/libvirt-0.7.7-fix-slow-dsync.patch +++ /dev/null @@ -1,41 +0,0 @@ -From e3c36a2575bc88a16d776693dc39ea01c780b406 Mon Sep 17 00:00:00 2001 -From: Jiri Denemark -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 - diff --git a/libvirt-0.7.7-fix-usb-parsing.patch b/libvirt-0.7.7-fix-usb-parsing.patch deleted file mode 100644 index fb26220..0000000 --- a/libvirt-0.7.7-fix-usb-parsing.patch +++ /dev/null @@ -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) { diff --git a/libvirt-0.7.7-fix-usb-product.patch b/libvirt-0.7.7-fix-usb-product.patch deleted file mode 100644 index 8ce24a9..0000000 --- a/libvirt-0.7.7-fix-usb-product.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 3a441522017aa9c1b8b54d2ce4569d0f0d96fa72 Mon Sep 17 00:00:00 2001 -From: Cole Robinson -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 -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 -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 ---- - 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 - diff --git a/libvirt-0.7.7-init-fixes.patch b/libvirt-0.7.7-init-fixes.patch deleted file mode 100644 index 4926f46..0000000 --- a/libvirt-0.7.7-init-fixes.patch +++ /dev/null @@ -1,35 +0,0 @@ -commit 9d0adf249827dde9e1c0d1c19513cf6018ceb34e -Author: Cole Robinson -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 diff --git a/libvirt-0.7.7-man-page-list.patch b/libvirt-0.7.7-man-page-list.patch deleted file mode 100644 index b6a543c..0000000 --- a/libvirt-0.7.7-man-page-list.patch +++ /dev/null @@ -1,65 +0,0 @@ -commit e5f31f461f63bbad211e84b810d6ba43a705f9dd -Author: Justin Clift -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 - The XML also show the NUMA topology information if available. - --=item B -+=item B 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 - --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 -+ -+The domain is not running. Usually this indicates the domain has been -+shut down completely, or has not been started. -+ - =item B - - The domain has crashed, which is always a violent ending. Usually diff --git a/libvirt-0.7.7-network-collision.patch b/libvirt-0.7.7-network-collision.patch deleted file mode 100644 index 6ae89be..0000000 --- a/libvirt-0.7.7-network-collision.patch +++ /dev/null @@ -1,169 +0,0 @@ -commit a83fe2c23efad190a1e00e448f607fe032650fd6 -Author: Cole Robinson -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'"), diff --git a/libvirt-0.7.7-no-secdriver-crash.patch b/libvirt-0.7.7-no-secdriver-crash.patch deleted file mode 100644 index add93cb..0000000 --- a/libvirt-0.7.7-no-secdriver-crash.patch +++ /dev/null @@ -1,26 +0,0 @@ -commit b7a7b3365145f6e9e434a3265a58666cd2e6d8dd -Author: Guido Günther -Date: Wed Mar 17 21:04:11 2010 +0100 - - Don't crash without a security driver - - "virsh dominfo " 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; - } diff --git a/libvirt-0.7.7-nodedev-conversions.patch b/libvirt-0.7.7-nodedev-conversions.patch deleted file mode 100644 index 2f641bc..0000000 --- a/libvirt-0.7.7-nodedev-conversions.patch +++ /dev/null @@ -1,77 +0,0 @@ -commit 74c7a3463d18a530d6d749d0199061b5d3f17faa -Author: Cole Robinson -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 -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 - -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; - } - diff --git a/libvirt-0.7.7-pci-decimal-parsing.patch b/libvirt-0.7.7-pci-decimal-parsing.patch deleted file mode 100644 index ed51361..0000000 --- a/libvirt-0.7.7-pci-decimal-parsing.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit e984019688509605966c03cd77f4591d2cc222d3 -Author: Cole Robinson -Date: Fri Apr 30 18:14:35 2010 +0200 - - domain: Fix PCI address decimal parsing regression - - 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
'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
'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
'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
'function' attribute")); - goto cleanup; diff --git a/libvirt-0.7.7-qemu-startup-output.patch b/libvirt-0.7.7-qemu-startup-output.patch deleted file mode 100644 index 57b739e..0000000 --- a/libvirt-0.7.7-qemu-startup-output.patch +++ /dev/null @@ -1,108 +0,0 @@ -commit 83be64034a0b530c904ceb4fd1ed1c10b5cdf4bf -Author: Cole Robinson -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; - } - diff --git a/libvirt-0.7.7-sanitize-pool.patch b/libvirt-0.7.7-sanitize-pool.patch deleted file mode 100644 index ad37b2c..0000000 --- a/libvirt-0.7.7-sanitize-pool.patch +++ /dev/null @@ -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 @@ - - - -- /var/lib/libvirt/images -+ ///var/////lib/libvirt/images// - - 0700 - 0 diff --git a/libvirt-0.7.7-set-kernel-perms.patch b/libvirt-0.7.7-set-kernel-perms.patch deleted file mode 100644 index aa623ff..0000000 --- a/libvirt-0.7.7-set-kernel-perms.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 3f1aa08af6580c215d973bc6bf57f505dbf8b926 Mon Sep 17 00:00:00 2001 -From: Cole Robinson -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 - diff --git a/libvirt-0.7.7-udev-wireless.patch b/libvirt-0.7.7-udev-wireless.patch deleted file mode 100644 index 41913d1..0000000 --- a/libvirt-0.7.7-udev-wireless.patch +++ /dev/null @@ -1,66 +0,0 @@ -commit 07f6c3a95f1caca368c8723b5b0a25ae2faa1ffe -Author: David Allan -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", diff --git a/libvirt-0.8.2-01-extract-backing-store-format.patch b/libvirt-0.8.2-01-extract-backing-store-format.patch new file mode 100644 index 0000000..569cf0a --- /dev/null +++ b/libvirt-0.8.2-01-extract-backing-store-format.patch @@ -0,0 +1,356 @@ +From 953440bd12608a20007ee5da5ab69fbbe910bd28 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + + 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 + diff --git a/libvirt-0.8.2-02-remove-type-field.patch b/libvirt-0.8.2-02-remove-type-field.patch new file mode 100644 index 0000000..74672f5 --- /dev/null +++ b/libvirt-0.8.2-02-remove-type-field.patch @@ -0,0 +1,159 @@ +From cab428b1d4d432965cee6f5afb67265557706715 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-03-refactor-metadata-extract.patch b/libvirt-0.8.2-03-refactor-metadata-extract.patch new file mode 100644 index 0000000..d868825 --- /dev/null +++ b/libvirt-0.8.2-03-refactor-metadata-extract.patch @@ -0,0 +1,585 @@ +From 57482ca0be29e9e92e242c9acb577e0b770c01d1 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-04-require-storage-format.patch b/libvirt-0.8.2-04-require-storage-format.patch new file mode 100644 index 0000000..deb4c37 --- /dev/null +++ b/libvirt-0.8.2-04-require-storage-format.patch @@ -0,0 +1,285 @@ +From 726a63a437efd96510ce316bf30d16f213d4db27 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-05-disk-path-iterator.patch b/libvirt-0.8.2-05-disk-path-iterator.patch new file mode 100644 index 0000000..4f74940 --- /dev/null +++ b/libvirt-0.8.2-05-disk-path-iterator.patch @@ -0,0 +1,170 @@ +From ac5067f1e2e98181ee0e9230f756697f50d853eb Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-06-use-disk-iterator.patch b/libvirt-0.8.2-06-use-disk-iterator.patch new file mode 100644 index 0000000..028710e --- /dev/null +++ b/libvirt-0.8.2-06-use-disk-iterator.patch @@ -0,0 +1,506 @@ +From 54c1bb731d2b19a46a594cf9682c022f1e1114d2 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-07-secdriver-params.patch b/libvirt-0.8.2-07-secdriver-params.patch new file mode 100644 index 0000000..08adca0 --- /dev/null +++ b/libvirt-0.8.2-07-secdriver-params.patch @@ -0,0 +1,1152 @@ +From bbf8c57b06ec1b63ae814114867eaceebb7dc166 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +Date: Tue, 15 Jun 2010 17:44:19 +0100 +Subject: [PATCH 07/11] Pass security driver object into all security driver callbacks + +The implementation of security driver callbacks often needs +to access the security driver object. Currently only a handful +of callbacks include the driver object as a parameter. Later +patches require this is many more places. + +* src/qemu/qemu_driver.c: Pass in the security driver object + to all callbacks +* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c, + src/security/security_apparmor.c, src/security/security_driver.h, + src/security/security_selinux.c: Add a virSecurityDriverPtr + param to all security callbacks +--- + src/qemu/qemu_driver.c | 88 ++++++++++++++++++++----------- + src/qemu/qemu_security_dac.c | 44 +++++++++++----- + src/qemu/qemu_security_stacked.c | 107 +++++++++++++++++++++++++------------- + src/security/security_apparmor.c | 57 +++++++++++++------- + src/security/security_driver.h | 40 ++++++++++---- + src/security/security_selinux.c | 56 +++++++++++++------ + 6 files changed, 260 insertions(+), 132 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 99aeffa..616547c 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -1278,7 +1278,8 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq + + if (driver->securityDriver && + driver->securityDriver->domainReserveSecurityLabel && +- driver->securityDriver->domainReserveSecurityLabel(obj) < 0) ++ driver->securityDriver->domainReserveSecurityLabel(driver->securityDriver, ++ obj) < 0) + goto error; + + if (obj->def->id >= driver->nextvmid) +@@ -3401,13 +3402,15 @@ static int qemudStartVMDaemon(virConnectPtr conn, + DEBUG0("Generating domain security label (if required)"); + if (driver->securityDriver && + driver->securityDriver->domainGenSecurityLabel && +- driver->securityDriver->domainGenSecurityLabel(vm) < 0) ++ driver->securityDriver->domainGenSecurityLabel(driver->securityDriver, ++ vm) < 0) + goto cleanup; + + DEBUG0("Generating setting domain security labels (if required)"); + if (driver->securityDriver && + driver->securityDriver->domainSetSecurityAllLabel && +- driver->securityDriver->domainSetSecurityAllLabel(vm, stdin_path) < 0) { ++ driver->securityDriver->domainSetSecurityAllLabel(driver->securityDriver, ++ vm, stdin_path) < 0) { + if (stdin_path && virStorageFileIsSharedFS(stdin_path) != 1) + goto cleanup; + } +@@ -3766,10 +3769,12 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver, + /* Reset Security Labels */ + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityAllLabel) +- driver->securityDriver->domainRestoreSecurityAllLabel(vm, migrated); ++ driver->securityDriver->domainRestoreSecurityAllLabel(driver->securityDriver, ++ vm, migrated); + if (driver->securityDriver && + driver->securityDriver->domainReleaseSecurityLabel) +- driver->securityDriver->domainReleaseSecurityLabel(vm); ++ driver->securityDriver->domainReleaseSecurityLabel(driver->securityDriver, ++ vm); + + /* Clear out dynamically assigned labels */ + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { +@@ -5171,7 +5176,8 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path, + if ((!bypassSecurityDriver) && + driver->securityDriver && + driver->securityDriver->domainSetSavedStateLabel && +- driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1) ++ driver->securityDriver->domainSetSavedStateLabel(driver->securityDriver, ++ vm, path) == -1) + goto endjob; + + if (header.compressed == QEMUD_SAVE_FORMAT_RAW) { +@@ -5206,7 +5212,8 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path, + if ((!bypassSecurityDriver) && + driver->securityDriver && + driver->securityDriver->domainRestoreSavedStateLabel && +- driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1) ++ driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, ++ vm, path) == -1) + VIR_WARN("failed to restore save state label on %s", path); + + if (cgroup != NULL) { +@@ -5253,7 +5260,8 @@ endjob: + if ((!bypassSecurityDriver) && + driver->securityDriver && + driver->securityDriver->domainRestoreSavedStateLabel && +- driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1) ++ driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, ++ vm, path) == -1) + VIR_WARN("failed to restore save state label on %s", path); + } + +@@ -5488,7 +5496,8 @@ static int qemudDomainCoreDump(virDomainPtr dom, + + if (driver->securityDriver && + driver->securityDriver->domainSetSavedStateLabel && +- driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1) ++ driver->securityDriver->domainSetSavedStateLabel(driver->securityDriver, ++ vm, path) == -1) + goto endjob; + + /* Migrate will always stop the VM, so the resume condition is +@@ -5531,7 +5540,8 @@ static int qemudDomainCoreDump(virDomainPtr dom, + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSavedStateLabel && +- driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1) ++ driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, ++ vm, path) == -1) + goto endjob; + + endjob: +@@ -5914,12 +5924,13 @@ static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr sec + * QEMU monitor hasn't seen SIGHUP/ERR on poll(). + */ + if (virDomainObjIsActive(vm)) { +- if (driver->securityDriver && driver->securityDriver->domainGetSecurityProcessLabel) { +- if (driver->securityDriver->domainGetSecurityProcessLabel(vm, seclabel) == -1) { +- qemuReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("Failed to get security label")); +- goto cleanup; +- } ++ if (driver->securityDriver && ++ driver->securityDriver->domainGetSecurityProcessLabel && ++ driver->securityDriver->domainGetSecurityProcessLabel(driver->securityDriver, ++ vm, seclabel) < 0) { ++ qemuReportError(VIR_ERR_INTERNAL_ERROR, ++ "%s", _("Failed to get security label")); ++ goto cleanup; + } + } + +@@ -6325,7 +6336,8 @@ qemudDomainSaveImageStartVM(virConnectPtr conn, + out: + if (driver->securityDriver && + driver->securityDriver->domainRestoreSavedStateLabel && +- driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1) ++ driver->securityDriver->domainRestoreSavedStateLabel(driver->securityDriver, ++ vm, path) == -1) + VIR_WARN("failed to restore save state label on %s", path); + + return ret; +@@ -7039,7 +7051,8 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainSetSecurityImageLabel && +- driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + return -1; + + if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCmdFlags))) +@@ -7068,7 +7081,8 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, origdisk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, origdisk) < 0) + VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src); + + VIR_FREE(origdisk->src); +@@ -7086,7 +7100,8 @@ error: + VIR_FREE(driveAlias); + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + VIR_WARN("Unable to restore security label on new media %s", disk->src); + return -1; + } +@@ -7113,7 +7128,8 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainSetSecurityImageLabel && +- driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + return -1; + + if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { +@@ -7180,7 +7196,8 @@ error: + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + VIR_WARN("Unable to restore security label on %s", disk->src); + + return -1; +@@ -7322,7 +7339,8 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainSetSecurityImageLabel && +- driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + return -1; + + /* We should have an address already, so make sure */ +@@ -7408,7 +7426,8 @@ error: + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + VIR_WARN("Unable to restore security label on %s", disk->src); + + return -1; +@@ -7435,7 +7454,8 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainSetSecurityImageLabel && +- driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainSetSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + return -1; + + if (!disk->src) { +@@ -7491,7 +7511,8 @@ error: + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, disk) < 0) + VIR_WARN("Unable to restore security label on %s", disk->src); + + return -1; +@@ -7928,7 +7949,8 @@ static int qemudDomainAttachHostDevice(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainSetSecurityHostdevLabel && +- driver->securityDriver->domainSetSecurityHostdevLabel(vm, hostdev) < 0) ++ driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver, ++ vm, hostdev) < 0) + return -1; + + switch (hostdev->source.subsys.type) { +@@ -7956,7 +7978,8 @@ static int qemudDomainAttachHostDevice(struct qemud_driver *driver, + error: + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityHostdevLabel && +- driver->securityDriver->domainRestoreSecurityHostdevLabel(vm, hostdev) < 0) ++ driver->securityDriver->domainRestoreSecurityHostdevLabel(driver->securityDriver, ++ vm, hostdev) < 0) + VIR_WARN0("Unable to restore host device labelling on hotplug fail"); + + return -1; +@@ -8401,7 +8424,8 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, dev->data.disk) < 0) + VIR_WARN("Unable to restore security label on %s", dev->data.disk->src); + + if (cgroup != NULL) { +@@ -8464,7 +8488,8 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityImageLabel && +- driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0) ++ driver->securityDriver->domainRestoreSecurityImageLabel(driver->securityDriver, ++ vm, dev->data.disk) < 0) + VIR_WARN("Unable to restore security label on %s", dev->data.disk->src); + + if (cgroup != NULL) { +@@ -8889,7 +8914,8 @@ static int qemudDomainDetachHostDevice(struct qemud_driver *driver, + + if (driver->securityDriver && + driver->securityDriver->domainRestoreSecurityHostdevLabel && +- driver->securityDriver->domainRestoreSecurityHostdevLabel(vm, dev->data.hostdev) < 0) ++ driver->securityDriver->domainRestoreSecurityHostdevLabel(driver->securityDriver, ++ vm, dev->data.hostdev) < 0) + VIR_WARN0("Failed to restore host device labelling"); + + return ret; +diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c +index 770010d..0bbcf69 100644 +--- a/src/qemu/qemu_security_dac.c ++++ b/src/qemu/qemu_security_dac.c +@@ -108,7 +108,8 @@ qemuSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, ++qemuSecurityDACSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk) + + { +@@ -124,7 +125,8 @@ qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACRestoreSecurityImageLabelInt(virDomainObjPtr vm ATTRIBUTE_UNUSED, ++qemuSecurityDACRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDiskDefPtr disk, + int migrated) + { +@@ -166,10 +168,11 @@ qemuSecurityDACRestoreSecurityImageLabelInt(virDomainObjPtr vm ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACRestoreSecurityImageLabel(virDomainObjPtr vm, ++qemuSecurityDACRestoreSecurityImageLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk) + { +- return qemuSecurityDACRestoreSecurityImageLabelInt(vm, disk, 0); ++ return qemuSecurityDACRestoreSecurityImageLabelInt(drv, vm, disk, 0); + } + + +@@ -192,7 +195,8 @@ qemuSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACSetSecurityHostdevLabel(virDomainObjPtr vm, ++qemuSecurityDACSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev) + + { +@@ -261,7 +265,8 @@ qemuSecurityDACRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACRestoreSecurityHostdevLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, ++qemuSecurityDACRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr dev) + + { +@@ -407,7 +412,8 @@ qemuSecurityDACRestoreChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACRestoreSecurityAllLabel(virDomainObjPtr vm, ++qemuSecurityDACRestoreSecurityAllLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + int migrated) + { + int i; +@@ -420,12 +426,14 @@ qemuSecurityDACRestoreSecurityAllLabel(virDomainObjPtr vm, + vm->def->name, migrated); + + for (i = 0 ; i < vm->def->nhostdevs ; i++) { +- if (qemuSecurityDACRestoreSecurityHostdevLabel(vm, ++ if (qemuSecurityDACRestoreSecurityHostdevLabel(drv, ++ vm, + vm->def->hostdevs[i]) < 0) + rc = -1; + } + for (i = 0 ; i < vm->def->ndisks ; i++) { +- if (qemuSecurityDACRestoreSecurityImageLabelInt(vm, ++ if (qemuSecurityDACRestoreSecurityImageLabelInt(drv, ++ vm, + vm->def->disks[i], + migrated) < 0) + rc = -1; +@@ -461,7 +469,9 @@ qemuSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path ATTRIBUTE_UNUSED) ++qemuSecurityDACSetSecurityAllLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, ++ const char *stdin_path ATTRIBUTE_UNUSED) + { + int i; + +@@ -472,11 +482,15 @@ qemuSecurityDACSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path AT + /* XXX fixme - we need to recursively label the entriy tree :-( */ + if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR) + continue; +- if (qemuSecurityDACSetSecurityImageLabel(vm, vm->def->disks[i]) < 0) ++ if (qemuSecurityDACSetSecurityImageLabel(drv, ++ vm, ++ vm->def->disks[i]) < 0) + return -1; + } + for (i = 0 ; i < vm->def->nhostdevs ; i++) { +- if (qemuSecurityDACSetSecurityHostdevLabel(vm, vm->def->hostdevs[i]) < 0) ++ if (qemuSecurityDACSetSecurityHostdevLabel(drv, ++ vm, ++ vm->def->hostdevs[i]) < 0) + return -1; + } + +@@ -503,7 +517,8 @@ qemuSecurityDACSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path AT + + + static int +-qemuSecurityDACSetSavedStateLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, ++qemuSecurityDACSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *savefile) + { + if (!driver->privileged) +@@ -514,7 +529,8 @@ qemuSecurityDACSetSavedStateLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, + + + static int +-qemuSecurityDACRestoreSavedStateLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED, ++qemuSecurityDACRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *savefile) + { + if (!driver->privileged) +diff --git a/src/qemu/qemu_security_stacked.c b/src/qemu/qemu_security_stacked.c +index df76135..432d095 100644 +--- a/src/qemu/qemu_security_stacked.c ++++ b/src/qemu/qemu_security_stacked.c +@@ -57,18 +57,21 @@ qemuSecurityStackedVerify(virDomainDefPtr def) + + + static int +-qemuSecurityStackedGenLabel(virDomainObjPtr vm) ++qemuSecurityStackedGenLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainGenSecurityLabel && +- driver->securitySecondaryDriver->domainGenSecurityLabel(vm) < 0) ++ driver->securitySecondaryDriver->domainGenSecurityLabel(driver->securitySecondaryDriver, ++ vm) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainGenSecurityLabel && +- driver->securityPrimaryDriver->domainGenSecurityLabel(vm) < 0) ++ driver->securityPrimaryDriver->domainGenSecurityLabel(driver->securityPrimaryDriver, ++ vm) < 0) + rc = -1; + + return rc; +@@ -76,18 +79,21 @@ qemuSecurityStackedGenLabel(virDomainObjPtr vm) + + + static int +-qemuSecurityStackedReleaseLabel(virDomainObjPtr vm) ++qemuSecurityStackedReleaseLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainReleaseSecurityLabel && +- driver->securitySecondaryDriver->domainReleaseSecurityLabel(vm) < 0) ++ driver->securitySecondaryDriver->domainReleaseSecurityLabel(driver->securitySecondaryDriver, ++ vm) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainReleaseSecurityLabel && +- driver->securityPrimaryDriver->domainReleaseSecurityLabel(vm) < 0) ++ driver->securityPrimaryDriver->domainReleaseSecurityLabel(driver->securityPrimaryDriver, ++ vm) < 0) + rc = -1; + + return rc; +@@ -95,18 +101,21 @@ qemuSecurityStackedReleaseLabel(virDomainObjPtr vm) + + + static int +-qemuSecurityStackedReserveLabel(virDomainObjPtr vm) ++qemuSecurityStackedReserveLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainReserveSecurityLabel && +- driver->securitySecondaryDriver->domainReserveSecurityLabel(vm) < 0) ++ driver->securitySecondaryDriver->domainReserveSecurityLabel(driver->securitySecondaryDriver, ++ vm) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainReserveSecurityLabel && +- driver->securityPrimaryDriver->domainReserveSecurityLabel(vm) < 0) ++ driver->securityPrimaryDriver->domainReserveSecurityLabel(driver->securityPrimaryDriver, ++ vm) < 0) + rc = -1; + + return rc; +@@ -114,19 +123,22 @@ qemuSecurityStackedReserveLabel(virDomainObjPtr vm) + + + static int +-qemuSecurityStackedSetSecurityImageLabel(virDomainObjPtr vm, ++qemuSecurityStackedSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainSetSecurityImageLabel && +- driver->securitySecondaryDriver->domainSetSecurityImageLabel(vm, disk) < 0) ++ driver->securitySecondaryDriver->domainSetSecurityImageLabel(driver->securitySecondaryDriver, ++ vm, disk) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainSetSecurityImageLabel && +- driver->securityPrimaryDriver->domainSetSecurityImageLabel(vm, disk) < 0) ++ driver->securityPrimaryDriver->domainSetSecurityImageLabel(driver->securityPrimaryDriver, ++ vm, disk) < 0) + rc = -1; + + return rc; +@@ -134,19 +146,22 @@ qemuSecurityStackedSetSecurityImageLabel(virDomainObjPtr vm, + + + static int +-qemuSecurityStackedRestoreSecurityImageLabel(virDomainObjPtr vm, ++qemuSecurityStackedRestoreSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainRestoreSecurityImageLabel && +- driver->securitySecondaryDriver->domainRestoreSecurityImageLabel(vm, disk) < 0) ++ driver->securitySecondaryDriver->domainRestoreSecurityImageLabel(driver->securitySecondaryDriver, ++ vm, disk) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainRestoreSecurityImageLabel && +- driver->securityPrimaryDriver->domainRestoreSecurityImageLabel(vm, disk) < 0) ++ driver->securityPrimaryDriver->domainRestoreSecurityImageLabel(driver->securityPrimaryDriver, ++ vm, disk) < 0) + rc = -1; + + return rc; +@@ -154,7 +169,8 @@ qemuSecurityStackedRestoreSecurityImageLabel(virDomainObjPtr vm, + + + static int +-qemuSecurityStackedSetSecurityHostdevLabel(virDomainObjPtr vm, ++qemuSecurityStackedSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev) + + { +@@ -162,12 +178,14 @@ qemuSecurityStackedSetSecurityHostdevLabel(virDomainObjPtr vm, + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainSetSecurityHostdevLabel && +- driver->securitySecondaryDriver->domainSetSecurityHostdevLabel(vm, dev) < 0) ++ driver->securitySecondaryDriver->domainSetSecurityHostdevLabel(driver->securitySecondaryDriver, ++ vm, dev) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainSetSecurityHostdevLabel && +- driver->securityPrimaryDriver->domainSetSecurityHostdevLabel(vm, dev) < 0) ++ driver->securityPrimaryDriver->domainSetSecurityHostdevLabel(driver->securityPrimaryDriver, ++ vm, dev) < 0) + rc = -1; + + return rc; +@@ -175,20 +193,22 @@ qemuSecurityStackedSetSecurityHostdevLabel(virDomainObjPtr vm, + + + static int +-qemuSecurityStackedRestoreSecurityHostdevLabel(virDomainObjPtr vm, ++qemuSecurityStackedRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev) +- + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel && +- driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel(vm, dev) < 0) ++ driver->securitySecondaryDriver->domainRestoreSecurityHostdevLabel(driver->securitySecondaryDriver, ++ vm, dev) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel && +- driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel(vm, dev) < 0) ++ driver->securityPrimaryDriver->domainRestoreSecurityHostdevLabel(driver->securityPrimaryDriver, ++ vm, dev) < 0) + rc = -1; + + return rc; +@@ -196,18 +216,22 @@ qemuSecurityStackedRestoreSecurityHostdevLabel(virDomainObjPtr vm, + + + static int +-qemuSecurityStackedSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path) ++qemuSecurityStackedSetSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, ++ const char *stdin_path) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainSetSecurityAllLabel && +- driver->securitySecondaryDriver->domainSetSecurityAllLabel(vm, stdin_path) < 0) ++ driver->securitySecondaryDriver->domainSetSecurityAllLabel(driver->securitySecondaryDriver, ++ vm, stdin_path) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainSetSecurityAllLabel && +- driver->securityPrimaryDriver->domainSetSecurityAllLabel(vm, stdin_path) < 0) ++ driver->securityPrimaryDriver->domainSetSecurityAllLabel(driver->securityPrimaryDriver, ++ vm, stdin_path) < 0) + rc = -1; + + return rc; +@@ -215,19 +239,22 @@ qemuSecurityStackedSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_pat + + + static int +-qemuSecurityStackedRestoreSecurityAllLabel(virDomainObjPtr vm, ++qemuSecurityStackedRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + int migrated) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainRestoreSecurityAllLabel && +- driver->securitySecondaryDriver->domainRestoreSecurityAllLabel(vm, migrated) < 0) ++ driver->securitySecondaryDriver->domainRestoreSecurityAllLabel(driver->securitySecondaryDriver, ++ vm, migrated) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainRestoreSecurityAllLabel && +- driver->securityPrimaryDriver->domainRestoreSecurityAllLabel(vm, migrated) < 0) ++ driver->securityPrimaryDriver->domainRestoreSecurityAllLabel(driver->securityPrimaryDriver, ++ vm, migrated) < 0) + rc = -1; + + return rc; +@@ -235,19 +262,22 @@ qemuSecurityStackedRestoreSecurityAllLabel(virDomainObjPtr vm, + + + static int +-qemuSecurityStackedSetSavedStateLabel(virDomainObjPtr vm, ++qemuSecurityStackedSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + const char *savefile) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainSetSavedStateLabel && +- driver->securitySecondaryDriver->domainSetSavedStateLabel(vm, savefile) < 0) ++ driver->securitySecondaryDriver->domainSetSavedStateLabel(driver->securitySecondaryDriver, ++ vm, savefile) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainSetSavedStateLabel && +- driver->securityPrimaryDriver->domainSetSavedStateLabel(vm, savefile) < 0) ++ driver->securityPrimaryDriver->domainSetSavedStateLabel(driver->securityPrimaryDriver, ++ vm, savefile) < 0) + rc = -1; + + return rc; +@@ -255,19 +285,22 @@ qemuSecurityStackedSetSavedStateLabel(virDomainObjPtr vm, + + + static int +-qemuSecurityStackedRestoreSavedStateLabel(virDomainObjPtr vm, ++qemuSecurityStackedRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + const char *savefile) + { + int rc = 0; + + if (driver->securitySecondaryDriver && + driver->securitySecondaryDriver->domainRestoreSavedStateLabel && +- driver->securitySecondaryDriver->domainRestoreSavedStateLabel(vm, savefile) < 0) ++ driver->securitySecondaryDriver->domainRestoreSavedStateLabel(driver->securitySecondaryDriver, ++ vm, savefile) < 0) + rc = -1; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainRestoreSavedStateLabel && +- driver->securityPrimaryDriver->domainRestoreSavedStateLabel(vm, savefile) < 0) ++ driver->securityPrimaryDriver->domainRestoreSavedStateLabel(driver->securityPrimaryDriver, ++ vm, savefile) < 0) + rc = -1; + + return rc; +@@ -296,14 +329,16 @@ qemuSecurityStackedSetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, + } + + static int +-qemuSecurityStackedGetProcessLabel(virDomainObjPtr vm, ++qemuSecurityStackedGetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virSecurityLabelPtr seclabel) + { + int rc = 0; + + if (driver->securityPrimaryDriver && + driver->securityPrimaryDriver->domainGetSecurityProcessLabel && +- driver->securityPrimaryDriver->domainGetSecurityProcessLabel(vm, ++ driver->securityPrimaryDriver->domainGetSecurityProcessLabel(driver->securityPrimaryDriver, ++ vm, + seclabel) < 0) + rc = -1; + +diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c +index e883f69..cb5c739 100644 +--- a/src/security/security_apparmor.c ++++ b/src/security/security_apparmor.c +@@ -148,7 +148,8 @@ profile_status_file(const char *str) + * load (add) a profile. Will create one if necessary + */ + static int +-load_profile(const char *profile, virDomainObjPtr vm, ++load_profile(virSecurityDriverPtr drv, ++ const char *profile, virDomainObjPtr vm, + const char *fn) + { + int rc = -1, status, ret; +@@ -281,7 +282,8 @@ cleanup: + * NULL. + */ + static int +-reload_profile(virDomainObjPtr vm, const char *fn) ++reload_profile(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, const char *fn) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; + int rc = -1; +@@ -295,7 +297,7 @@ reload_profile(virDomainObjPtr vm, const char *fn) + + /* Update the profile only if it is loaded */ + if (profile_loaded(secdef->imagelabel) >= 0) { +- if (load_profile(secdef->imagelabel, vm, fn) < 0) { ++ if (load_profile(drv, secdef->imagelabel, vm, fn) < 0) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot update AppArmor profile " + "\'%s\'"), +@@ -357,7 +359,8 @@ AppArmorSecurityDriverOpen(virSecurityDriverPtr drv) + * called on shutdown. + */ + static int +-AppArmorGenSecurityLabel(virDomainObjPtr vm) ++AppArmorGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + int rc = -1; + char *profile_name = NULL; +@@ -411,14 +414,15 @@ AppArmorGenSecurityLabel(virDomainObjPtr vm) + } + + static int +-AppArmorSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path) ++AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, const char *stdin_path) + { + if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC) + return 0; + + /* if the profile is not already loaded, then load one */ + if (profile_loaded(vm->def->seclabel.label) < 0) { +- if (load_profile(vm->def->seclabel.label, vm, stdin_path) < 0) { ++ if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path) < 0) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot generate AppArmor profile " + "\'%s\'"), vm->def->seclabel.label); +@@ -433,7 +437,9 @@ AppArmorSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path) + * running. + */ + static int +-AppArmorGetSecurityProcessLabel(virDomainObjPtr vm, virSecurityLabelPtr sec) ++AppArmorGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, ++ virSecurityLabelPtr sec) + { + int rc = -1; + char *profile_name = NULL; +@@ -465,7 +471,8 @@ AppArmorGetSecurityProcessLabel(virDomainObjPtr vm, virSecurityLabelPtr sec) + * more details. Currently called via qemudShutdownVMDaemon. + */ + static int +-AppArmorReleaseSecurityLabel(virDomainObjPtr vm) ++AppArmorReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; + +@@ -478,7 +485,8 @@ AppArmorReleaseSecurityLabel(virDomainObjPtr vm) + + + static int +-AppArmorRestoreSecurityAllLabel(virDomainObjPtr vm, ++AppArmorRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + int migrated ATTRIBUTE_UNUSED) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; +@@ -533,15 +541,17 @@ AppArmorSetSecurityProcessLabel(virSecurityDriverPtr drv, virDomainObjPtr vm) + + /* Called when hotplugging */ + static int +-AppArmorRestoreSecurityImageLabel(virDomainObjPtr vm, ++AppArmorRestoreSecurityImageLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk ATTRIBUTE_UNUSED) + { +- return reload_profile(vm, NULL); ++ return reload_profile(drv, vm, NULL); + } + + /* Called when hotplugging */ + static int +-AppArmorSetSecurityImageLabel(virDomainObjPtr vm, virDomainDiskDefPtr disk) ++AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, virDomainDiskDefPtr disk) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; + int rc = -1; +@@ -566,7 +576,7 @@ AppArmorSetSecurityImageLabel(virDomainObjPtr vm, virDomainDiskDefPtr disk) + + /* update the profile only if it is loaded */ + if (profile_loaded(secdef->imagelabel) >= 0) { +- if (load_profile(secdef->imagelabel, vm, disk->src) < 0) { ++ if (load_profile(drv, secdef->imagelabel, vm, disk->src) < 0) { + virSecurityReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot update AppArmor profile " + "\'%s\'"), +@@ -600,14 +610,16 @@ AppArmorSecurityVerify(virDomainDefPtr def) + } + + static int +-AppArmorReserveSecurityLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED) ++AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm ATTRIBUTE_UNUSED) + { + /* NOOP. Nothing to reserve with AppArmor */ + return 0; + } + + static int +-AppArmorSetSecurityHostdevLabel(virDomainObjPtr vm, ++AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED) + + { +@@ -621,7 +633,8 @@ AppArmorSetSecurityHostdevLabel(virDomainObjPtr vm, + } + + static int +-AppArmorRestoreSecurityHostdevLabel(virDomainObjPtr vm, ++AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED) + + { +@@ -634,18 +647,20 @@ AppArmorRestoreSecurityHostdevLabel(virDomainObjPtr vm, + } + + static int +-AppArmorSetSavedStateLabel(virDomainObjPtr vm, +- const char *savefile) ++AppArmorSetSavedStateLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, ++ const char *savefile) + { +- return reload_profile(vm, savefile); ++ return reload_profile(drv, vm, savefile); + } + + + static int +-AppArmorRestoreSavedStateLabel(virDomainObjPtr vm, ++AppArmorRestoreSavedStateLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + const char *savefile ATTRIBUTE_UNUSED) + { +- return reload_profile(vm, NULL); ++ return reload_profile(drv, vm, NULL); + } + + virSecurityDriver virAppArmorSecurityDriver = { +diff --git a/src/security/security_driver.h b/src/security/security_driver.h +index 99260a4..61c9eb0 100644 +--- a/src/security/security_driver.h ++++ b/src/security/security_driver.h +@@ -28,32 +28,48 @@ typedef enum { + + typedef struct _virSecurityDriver virSecurityDriver; + typedef virSecurityDriver *virSecurityDriverPtr; ++ ++typedef struct _virSecurityDriverState virSecurityDriverState; ++typedef virSecurityDriverState *virSecurityDriverStatePtr; ++ + typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void); + typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv); +-typedef int (*virSecurityDomainRestoreImageLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk); + typedef int (*virSecurityDomainSetSocketLabel) (virSecurityDriverPtr drv, + virDomainObjPtr vm); + typedef int (*virSecurityDomainClearSocketLabel)(virSecurityDriverPtr drv, + virDomainObjPtr vm); +-typedef int (*virSecurityDomainSetImageLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainSetImageLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk); +-typedef int (*virSecurityDomainRestoreHostdevLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainRestoreHostdevLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev); +-typedef int (*virSecurityDomainSetHostdevLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainSetHostdevLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev); +-typedef int (*virSecurityDomainSetSavedStateLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainSetSavedStateLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + const char *savefile); +-typedef int (*virSecurityDomainRestoreSavedStateLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainRestoreSavedStateLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + const char *savefile); +-typedef int (*virSecurityDomainGenLabel) (virDomainObjPtr sec); +-typedef int (*virSecurityDomainReserveLabel) (virDomainObjPtr sec); +-typedef int (*virSecurityDomainReleaseLabel) (virDomainObjPtr sec); +-typedef int (*virSecurityDomainSetAllLabel) (virDomainObjPtr sec, ++typedef int (*virSecurityDomainGenLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr sec); ++typedef int (*virSecurityDomainReserveLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr sec); ++typedef int (*virSecurityDomainReleaseLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr sec); ++typedef int (*virSecurityDomainSetAllLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr sec, + const char *stdin_path); +-typedef int (*virSecurityDomainRestoreAllLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainRestoreAllLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + int migrated); +-typedef int (*virSecurityDomainGetProcessLabel) (virDomainObjPtr vm, ++typedef int (*virSecurityDomainGetProcessLabel) (virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virSecurityLabelPtr sec); + typedef int (*virSecurityDomainSetProcessLabel) (virSecurityDriverPtr drv, + virDomainObjPtr vm); +diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c +index d191118..cc3812b 100644 +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -156,7 +156,8 @@ SELinuxInitialize(void) + } + + static int +-SELinuxGenSecurityLabel(virDomainObjPtr vm) ++SELinuxGenSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + int rc = -1; + char mcs[1024]; +@@ -220,7 +221,8 @@ done: + } + + static int +-SELinuxReserveSecurityLabel(virDomainObjPtr vm) ++SELinuxReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + security_context_t pctx; + context_t ctx = NULL; +@@ -275,7 +277,8 @@ SELinuxSecurityDriverOpen(virSecurityDriverPtr drv) + } + + static int +-SELinuxGetSecurityProcessLabel(virDomainObjPtr vm, ++SELinuxGetSecurityProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virSecurityLabelPtr sec) + { + security_context_t ctx; +@@ -387,7 +390,8 @@ err: + } + + static int +-SELinuxRestoreSecurityImageLabelInt(virDomainObjPtr vm, ++SELinuxRestoreSecurityImageLabelInt(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk, + int migrated) + { +@@ -431,10 +435,11 @@ SELinuxRestoreSecurityImageLabelInt(virDomainObjPtr vm, + + + static int +-SELinuxRestoreSecurityImageLabel(virDomainObjPtr vm, ++SELinuxRestoreSecurityImageLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk) + { +- return SELinuxRestoreSecurityImageLabelInt(vm, disk, 0); ++ return SELinuxRestoreSecurityImageLabelInt(drv, vm, disk, 0); + } + + +@@ -462,7 +467,8 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk, + } + + static int +-SELinuxSetSecurityImageLabel(virDomainObjPtr vm, ++SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainDiskDefPtr disk) + + { +@@ -500,7 +506,8 @@ SELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + } + + static int +-SELinuxSetSecurityHostdevLabel(virDomainObjPtr vm, ++SELinuxSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev) + + { +@@ -568,7 +575,8 @@ SELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, + } + + static int +-SELinuxRestoreSecurityHostdevLabel(virDomainObjPtr vm, ++SELinuxRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + virDomainHostdevDefPtr dev) + + { +@@ -715,7 +723,8 @@ SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + + + static int +-SELinuxRestoreSecurityAllLabel(virDomainObjPtr vm, ++SELinuxRestoreSecurityAllLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + int migrated ATTRIBUTE_UNUSED) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; +@@ -728,11 +737,14 @@ SELinuxRestoreSecurityAllLabel(virDomainObjPtr vm, + return 0; + + for (i = 0 ; i < vm->def->nhostdevs ; i++) { +- if (SELinuxRestoreSecurityHostdevLabel(vm, vm->def->hostdevs[i]) < 0) ++ if (SELinuxRestoreSecurityHostdevLabel(drv, ++ vm, ++ vm->def->hostdevs[i]) < 0) + rc = -1; + } + for (i = 0 ; i < vm->def->ndisks ; i++) { +- if (SELinuxRestoreSecurityImageLabelInt(vm, ++ if (SELinuxRestoreSecurityImageLabelInt(drv, ++ vm, + vm->def->disks[i], + migrated) < 0) + rc = -1; +@@ -756,7 +768,8 @@ SELinuxRestoreSecurityAllLabel(virDomainObjPtr vm, + } + + static int +-SELinuxReleaseSecurityLabel(virDomainObjPtr vm) ++SELinuxReleaseSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; + +@@ -779,7 +792,8 @@ SELinuxReleaseSecurityLabel(virDomainObjPtr vm) + + + static int +-SELinuxSetSavedStateLabel(virDomainObjPtr vm, ++SELinuxSetSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + const char *savefile) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; +@@ -792,7 +806,8 @@ SELinuxSetSavedStateLabel(virDomainObjPtr vm, + + + static int +-SELinuxRestoreSavedStateLabel(virDomainObjPtr vm, ++SELinuxRestoreSavedStateLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED, ++ virDomainObjPtr vm, + const char *savefile) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; +@@ -963,7 +978,9 @@ SELinuxSetSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, + + + static int +-SELinuxSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path) ++SELinuxSetSecurityAllLabel(virSecurityDriverPtr drv, ++ virDomainObjPtr vm, ++ const char *stdin_path) + { + const virSecurityLabelDefPtr secdef = &vm->def->seclabel; + int i; +@@ -978,11 +995,14 @@ SELinuxSetSecurityAllLabel(virDomainObjPtr vm, const char *stdin_path) + vm->def->disks[i]->src, vm->def->disks[i]->dst); + continue; + } +- if (SELinuxSetSecurityImageLabel(vm, vm->def->disks[i]) < 0) ++ if (SELinuxSetSecurityImageLabel(drv, ++ vm, vm->def->disks[i]) < 0) + return -1; + } + for (i = 0 ; i < vm->def->nhostdevs ; i++) { +- if (SELinuxSetSecurityHostdevLabel(vm, vm->def->hostdevs[i]) < 0) ++ if (SELinuxSetSecurityHostdevLabel(drv, ++ vm, ++ vm->def->hostdevs[i]) < 0) + return -1; + } + +-- +1.7.1.1 + diff --git a/libvirt-0.8.2-08-disable-disk-probing.patch b/libvirt-0.8.2-08-disable-disk-probing.patch new file mode 100644 index 0000000..5952ad5 --- /dev/null +++ b/libvirt-0.8.2-08-disable-disk-probing.patch @@ -0,0 +1,468 @@ +From dac2b936e77f6c76c11f162e4b175492e4803acb Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 elements to include ++# 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 + diff --git a/libvirt-0.8.2-09-set-default-driver.patch b/libvirt-0.8.2-09-set-default-driver.patch new file mode 100644 index 0000000..93c4ca5 --- /dev/null +++ b/libvirt-0.8.2-09-set-default-driver.patch @@ -0,0 +1,94 @@ +From 3534cd47a57ee9cf7041472511444784f14d6939 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-10-qemu-img-format-handling.patch b/libvirt-0.8.2-10-qemu-img-format-handling.patch new file mode 100644 index 0000000..813bf16 --- /dev/null +++ b/libvirt-0.8.2-10-qemu-img-format-handling.patch @@ -0,0 +1,291 @@ +From 2ba8625d6d148fa489586efabdfaf2ef20903762 Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-11-storage-vol-backing.patch b/libvirt-0.8.2-11-storage-vol-backing.patch new file mode 100644 index 0000000..7ffcc57 --- /dev/null +++ b/libvirt-0.8.2-11-storage-vol-backing.patch @@ -0,0 +1,165 @@ +From d33f44c2e74de28c89b64cdc2c0a6564662e075c Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt-0.8.2-apply-iptables-sport-mapping.patch b/libvirt-0.8.2-apply-iptables-sport-mapping.patch new file mode 100644 index 0000000..d929a34 --- /dev/null +++ b/libvirt-0.8.2-apply-iptables-sport-mapping.patch @@ -0,0 +1,265 @@ +From 112a309bc7839e95c558b535143f855ce89cca8c Mon Sep 17 00:00:00 2001 +From: Daniel P. Berrange +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 + diff --git a/libvirt.spec b/libvirt.spec index af5220f..0463c3f 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -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,,\n $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 diff --git a/sources b/sources index f68b14e..e8d4bbd 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -5f315b0bf20e3964f7657ba1e630cd67 libvirt-0.7.7.tar.gz +14164638fe0e7f65e425acc85dabc517 libvirt-0.8.2.tar.gz