diff --git a/libvirt-0.7.1-audio-config.patch b/libvirt-0.7.1-audio-config.patch new file mode 100644 index 0000000..b921845 --- /dev/null +++ b/libvirt-0.7.1-audio-config.patch @@ -0,0 +1,122 @@ +diff -rup libvirt-0.7.1/qemud/libvirtd.init.in audio/qemud/libvirtd.init.in +--- libvirt-0.7.1/qemud/libvirtd.init.in 2009-07-22 09:37:32.000000000 -0400 ++++ audio/qemud/libvirtd.init.in 2010-05-26 12:05:50.584822000 -0400 +@@ -47,6 +47,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 +diff -rup libvirt-0.7.1/qemud/libvirtd_qemu.aug audio/qemud/libvirtd_qemu.aug +--- libvirt-0.7.1/qemud/libvirtd_qemu.aug 2009-09-08 10:16:02.000000000 -0400 ++++ audio/qemud/libvirtd_qemu.aug 2010-05-26 12:07:24.169216000 -0400 +@@ -36,6 +36,7 @@ module Libvirtd_qemu = + | str_array_entry "cgroup_device_acl" + | str_entry "save_image_format" + | str_entry "hugetlbfs_mount" ++ | bool_entry "vnc_allow_host_audio" + + (* Each enty in the config is one of the following three ... *) + let entry = vnc_entry +diff -rup libvirt-0.7.1/qemud/libvirtd.sysconf audio/qemud/libvirtd.sysconf +--- libvirt-0.7.1/qemud/libvirtd.sysconf 2010-05-26 12:04:08.379130000 -0400 ++++ audio/qemud/libvirtd.sysconf 2010-05-26 12:10:28.263486000 -0400 +@@ -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 +diff -rup libvirt-0.7.1/qemud/test_libvirtd_qemu.aug audio/qemud/test_libvirtd_qemu.aug +--- libvirt-0.7.1/qemud/test_libvirtd_qemu.aug 2009-09-08 10:16:02.000000000 -0400 ++++ audio/qemud/test_libvirtd_qemu.aug 2010-05-26 12:11:19.540907000 -0400 +@@ -92,6 +92,8 @@ cgroup_device_acl = [ \"/dev/null\", \"/ + + save_image_format = \"gzip\" + ++vnc_allow_host_audio = 1 ++ + hugetlbfs_mount = \"/dev/hugepages\" + " + +@@ -195,4 +197,6 @@ hugetlbfs_mount = \"/dev/hugepages\" + { "#empty" } + { "save_image_format" = "gzip" } + { "#empty" } +-{ "hugetlbfs_mount" = "/dev/hugepages" } +\ No newline at end of file ++{ "hugetlbfs_mount" = "/dev/hugepages" } ++{ "#empty" } ++{ "vnc_allow_host_audio" = "1" } +diff -rup libvirt-0.7.1/src/qemu.conf audio/src/qemu.conf +--- libvirt-0.7.1/src/qemu.conf 2009-09-10 05:15:56.000000000 -0400 ++++ audio/src/qemu.conf 2010-05-26 12:08:12.419811000 -0400 +@@ -152,3 +152,13 @@ + # in a location of $MOUNTPOINT/libvirt/qemu + + # hugetlbfs_mount = "/dev/hugepages" ++# ++ ++# 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 -rup libvirt-0.7.1/src/qemu_conf.c audio/src/qemu_conf.c +--- libvirt-0.7.1/src/qemu_conf.c 2010-05-26 12:04:08.578062000 -0400 ++++ audio/src/qemu_conf.c 2010-05-26 12:09:31.174206000 -0400 +@@ -318,6 +318,10 @@ int qemudLoadDriverConfig(struct qemud_d + } + } + ++ 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; + } +@@ -2113,12 +2117,15 @@ int qemudBuildCommandLine(virConnectPtr + 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 -rup libvirt-0.7.1/src/qemu_conf.h audio/src/qemu_conf.h +--- libvirt-0.7.1/src/qemu_conf.h 2009-09-10 09:45:00.000000000 -0400 ++++ audio/src/qemu_conf.h 2010-05-26 12:10:07.196992000 -0400 +@@ -110,6 +110,8 @@ struct qemud_driver { + char *hugetlbfs_mount; + char *hugepage_path; + ++ unsigned int vncAllowHostAudio : 1; ++ + virCapsPtr caps; + + /* An array of callbacks */ diff --git a/libvirt-0.7.1-backing-perms.patch b/libvirt-0.7.1-backing-perms.patch new file mode 100644 index 0000000..9cc3318 --- /dev/null +++ b/libvirt-0.7.1-backing-perms.patch @@ -0,0 +1,99 @@ +--- libvirt-0.7.1/src/qemu_driver.c 2010-06-17 11:30:54.501983000 -0400 ++++ new/src/qemu_driver.c 2010-06-17 11:20:13.032900000 -0400 +@@ -69,7 +69,7 @@ + #include "hostusb.h" + #include "security.h" + #include "cgroup.h" +- ++#include "storage_file.h" + + #define VIR_FROM_THIS VIR_FROM_QEMU + +@@ -1895,6 +1895,7 @@ static int qemuDomainSetDeviceOwnership( + { + uid_t uid; + gid_t gid; ++ const char *path; + + if (!driver->privileged) + return 0; +@@ -1912,6 +1913,35 @@ static int qemuDomainSetDeviceOwnership( + (def->data.disk->readonly || def->data.disk->shared)) + return 0; + ++ if (!def->data.disk->src) ++ return 0; ++ ++ path = def->data.disk->src; ++ do { ++ virStorageFileMetadata meta; ++ int ret; ++ ++ memset(&meta, 0, sizeof(meta)); ++ ++ ret = virStorageFileGetMetadata(conn, path, &meta); ++ ++ if (path != def->data.disk->src) ++ VIR_FREE(path); ++ path = NULL; ++ ++ if (ret < 0) ++ return -1; ++ ++ if (meta.backingStore != NULL && ++ qemuDomainSetFileOwnership(conn, ++ meta.backingStore, uid, gid) < 0) { ++ VIR_FREE(meta.backingStore); ++ return -1; ++ } ++ ++ path = meta.backingStore; ++ } while (path != NULL); ++ + return qemuDomainSetFileOwnership(conn, def->data.disk->src, uid, gid); + + case VIR_DOMAIN_DEVICE_HOSTDEV: +@@ -1929,6 +1959,7 @@ static int qemuDomainSetAllDeviceOwnersh + int i; + uid_t uid; + gid_t gid; ++ const char *path; + + if (!driver->privileged) + return 0; +@@ -1949,6 +1980,35 @@ static int qemuDomainSetAllDeviceOwnersh + (def->disks[i]->readonly || def->disks[i]->shared)) + continue; + ++ if (!def->disks[i]->src) ++ continue; ++ ++ path = def->disks[i]->src; ++ do { ++ virStorageFileMetadata meta; ++ int ret; ++ ++ memset(&meta, 0, sizeof(meta)); ++ ++ ret = virStorageFileGetMetadata(conn, path, &meta); ++ ++ if (path != def->disks[i]->src) ++ VIR_FREE(path); ++ path = NULL; ++ ++ if (ret < 0) ++ return -1; ++ ++ if (meta.backingStore != NULL && ++ qemuDomainSetFileOwnership(conn, ++ meta.backingStore, uid, gid) < 0) { ++ VIR_FREE(meta.backingStore); ++ return -1; ++ } ++ ++ path = meta.backingStore; ++ } while (path != NULL); ++ + if (qemuDomainSetFileOwnership(conn, def->disks[i]->src, uid, gid) < 0) + return -1; + } diff --git a/libvirt-0.7.1-caps-option.patch b/libvirt-0.7.1-caps-option.patch new file mode 100644 index 0000000..354f017 --- /dev/null +++ b/libvirt-0.7.1-caps-option.patch @@ -0,0 +1,82 @@ +diff -rup libvirt-0.7.1/src/qemu.conf new/src/qemu.conf +--- libvirt-0.7.1/src/qemu.conf 2010-06-03 15:01:14.288848000 -0400 ++++ new/src/qemu.conf 2010-06-03 15:04:05.062031000 -0400 +@@ -162,3 +162,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.1/src/qemu_conf.c new/src/qemu_conf.c +--- libvirt-0.7.1/src/qemu_conf.c 2010-06-03 15:01:14.302852000 -0400 ++++ new/src/qemu_conf.c 2010-06-03 15:05:09.755183000 -0400 +@@ -98,7 +98,9 @@ int qemudLoadDriverConfig(struct qemud_d + char *group; + int i; + +- /* Setup 2 critical defaults */ ++ /* Setup critical defaults */ ++ driver->clearEmulatorCapabilities = 1; ++ + if (!(driver->vncListen = strdup("127.0.0.1"))) { + virReportOOMError(NULL); + return -1; +@@ -322,6 +324,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.1/src/qemu_conf.h new/src/qemu_conf.h +--- libvirt-0.7.1/src/qemu_conf.h 2010-06-03 15:01:14.306860000 -0400 ++++ new/src/qemu_conf.h 2010-06-03 15:05:27.968796000 -0400 +@@ -111,6 +111,7 @@ struct qemud_driver { + char *hugepage_path; + + unsigned int vncAllowHostAudio : 1; ++ unsigned int clearEmulatorCapabilities : 1; + + virCapsPtr caps; + +diff -rup libvirt-0.7.1/src/qemu_driver.c new/src/qemu_driver.c +--- libvirt-0.7.1/src/qemu_driver.c 2010-06-03 15:01:14.413848000 -0400 ++++ new/src/qemu_driver.c 2010-06-03 15:06:08.186798000 -0400 +@@ -2063,7 +2063,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; +@@ -2205,9 +2205,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(conn, argv, progenv, &keepfd, &child, + stdin_fd, &logfile, &logfile, +- VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS, ++ runflags, + qemudSecurityHook, &hookData, + pidfile); + VIR_FREE(pidfile); diff --git a/libvirt-0.7.1-fix-cgroup-crash.patch b/libvirt-0.7.1-fix-cgroup-crash.patch new file mode 100644 index 0000000..d74de81 --- /dev/null +++ b/libvirt-0.7.1-fix-cgroup-crash.patch @@ -0,0 +1,12 @@ +diff -rup libvirt-0.7.1/src/qemu_driver.c new/src/qemu_driver.c +--- libvirt-0.7.1/src/qemu_driver.c 2010-06-03 13:51:14.398483000 -0400 ++++ new/src/qemu_driver.c 2010-06-03 13:56:05.667092000 -0400 +@@ -5988,7 +5988,7 @@ static int qemudDomainAttachDevice(virDo + virDomainDiskDeviceTypeToString(dev->data.disk->device)); + /* Fallthrough */ + } +- if (ret != 0) { ++ if (ret != 0 && cgroup) { + virCgroupDenyDevicePath(cgroup, + dev->data.disk->src); + } diff --git a/libvirt-0.7.1-fix-usb-parsing.patch b/libvirt-0.7.1-fix-usb-parsing.patch new file mode 100644 index 0000000..5efc109 --- /dev/null +++ b/libvirt-0.7.1-fix-usb-parsing.patch @@ -0,0 +1,13 @@ +Only in new: qemu_driver.c +diff -rup libvirt-0.7.1/src/hostusb.c new/src/hostusb.c +--- libvirt-0.7.1/src/hostusb.c 2010-06-03 13:51:14.392459000 -0400 ++++ new/src/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.1-lxc-uri-crash.patch b/libvirt-0.7.1-lxc-uri-crash.patch new file mode 100644 index 0000000..0a72d98 --- /dev/null +++ b/libvirt-0.7.1-lxc-uri-crash.patch @@ -0,0 +1,13 @@ +diff -rup libvirt-0.7.1/src/lxc_driver.c new/src/lxc_driver.c +--- libvirt-0.7.1/src/lxc_driver.c 2009-09-10 09:45:00.000000000 -0400 ++++ new/src/lxc_driver.c 2010-06-03 15:03:11.524069000 -0400 +@@ -96,7 +96,8 @@ static virDrvOpenStatus lxcOpen(virConne + return VIR_DRV_OPEN_DECLINED; + + /* If path isn't '/' then they typoed, tell them correct path */ +- if (STRNEQ(conn->uri->path, "/")) { ++ if (conn->uri->path != NULL && ++ STRNEQ(conn->uri->path, "/")) { + lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR, + _("unexpected LXC URI path '%s', try lxc:///"), + conn->uri->path); diff --git a/libvirt-0.7.1-man-page-list.patch b/libvirt-0.7.1-man-page-list.patch new file mode 100644 index 0000000..a7ce030 --- /dev/null +++ b/libvirt-0.7.1-man-page-list.patch @@ -0,0 +1,65 @@ +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/docs/virsh.pod ++++ b/docs/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.1-migrate-errreport.patch b/libvirt-0.7.1-migrate-errreport.patch new file mode 100644 index 0000000..081edd1 --- /dev/null +++ b/libvirt-0.7.1-migrate-errreport.patch @@ -0,0 +1,401 @@ +diff -rup libvirt-0.7.1/src/libvirt.c new/src/libvirt.c +--- libvirt-0.7.1/src/libvirt.c 2010-06-03 15:30:32.615164000 -0400 ++++ new/src/libvirt.c 2010-06-03 15:33:22.863409000 -0400 +@@ -3054,6 +3054,7 @@ virDomainMigrateVersion2 (virDomainPtr d + char *cookie = NULL; + char *dom_xml = NULL; + int cookielen = 0, ret; ++ virErrorPtr orig_err = NULL; + + /* Prepare the migration. + * +@@ -3102,6 +3103,10 @@ virDomainMigrateVersion2 (virDomainPtr d + ret = domain->conn->driver->domainMigratePerform + (domain, cookie, cookielen, uri, flags, dname, bandwidth); + ++ /* Perform failed. Make sure Finish doesn't overwrite the error */ ++ if (ret < 0) ++ orig_err = virSaveLastError(); ++ + /* In version 2 of the migration protocol, we pass the + * status code from the sender to the destination host, + * so it can do any cleanup if the migration failed. +@@ -3111,6 +3116,10 @@ virDomainMigrateVersion2 (virDomainPtr d + (dconn, dname, cookie, cookielen, uri, flags, ret); + + done: ++ if (orig_err) { ++ virSetError(orig_err); ++ virFreeError(orig_err); ++ } + VIR_FREE (uri_out); + VIR_FREE (cookie); + return ddomain; +@@ -3222,7 +3231,7 @@ virDomainMigrate (virDomainPtr domain, + + error: + /* Copy to connection error object for back compatability */ +- virSetConnError(domain->conn); ++ virDispatchError(domain->conn); + return NULL; + } + +@@ -3269,8 +3278,7 @@ virDomainMigratePrepare (virConnectPtr d + virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + + error: +- /* Copy to connection error object for back compatability */ +- virSetConnError(dconn); ++ virDispatchError(dconn); + return -1; + } + +@@ -3318,8 +3326,7 @@ virDomainMigratePerform (virDomainPtr do + virLibDomainError (domain, VIR_ERR_NO_SUPPORT, __FUNCTION__); + + error: +- /* Copy to connection error object for back compatability */ +- virSetConnError(domain->conn); ++ virDispatchError(domain->conn); + return -1; + } + +@@ -3364,8 +3371,7 @@ virDomainMigrateFinish (virConnectPtr dc + virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + + error: +- /* Copy to connection error object for back compatability */ +- virSetConnError(dconn); ++ virDispatchError(dconn); + return NULL; + } + +@@ -3416,8 +3422,7 @@ virDomainMigratePrepare2 (virConnectPtr + virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + + error: +- /* Copy to connection error object for back compatability */ +- virSetConnError(dconn); ++ virDispatchError(dconn); + return -1; + } + +@@ -3464,8 +3469,7 @@ virDomainMigrateFinish2 (virConnectPtr d + virLibConnError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + + error: +- /* Copy to connection error object for back compatability */ +- virSetConnError(dconn); ++ virDispatchError(dconn); + return NULL; + } + +diff -rup libvirt-0.7.1/src/libvirt_private.syms new/src/libvirt_private.syms +--- libvirt-0.7.1/src/libvirt_private.syms 2010-06-03 15:30:33.051186000 -0400 ++++ new/src/libvirt_private.syms 2010-06-03 15:33:22.869400000 -0400 +@@ -461,6 +461,7 @@ virRaiseErrorFull; + virReportSystemErrorFull; + virReportOOMErrorFull; + virStrerror; ++virSetError; + + + # xml.h +diff -rup libvirt-0.7.1/src/qemu_driver.c new/src/qemu_driver.c +--- libvirt-0.7.1/src/qemu_driver.c 2010-06-03 15:30:33.111159000 -0400 ++++ new/src/qemu_driver.c 2010-06-03 15:35:22.809404000 -0400 +@@ -2297,12 +2297,17 @@ static void qemudShutdownVMDaemon(virCon + virDomainObjPtr vm) { + int ret; + int retries = 0; ++ virErrorPtr orig_err; + + if (!virDomainIsActive(vm)) + return; + + VIR_DEBUG(_("Shutting down VM '%s'\n"), vm->def->name); + ++ /* This method is routinely used in clean up paths. Disable error ++ * reporting so we don't squash a legit error. */ ++ orig_err = virSaveLastError(); ++ + if (virKillProcess(vm->pid, 0) == 0 && + virKillProcess(vm->pid, SIGTERM) < 0) + virReportSystemError(conn, errno, +@@ -2377,6 +2382,11 @@ retry: + vm->def->id = -1; + vm->newDef = NULL; + } ++ ++ if (orig_err) { ++ virSetError(orig_err); ++ virFreeError(orig_err); ++ } + } + + +@@ -7497,6 +7507,10 @@ qemudDomainMigrateFinish2 (virConnectPtr + virDomainObjPtr vm; + virDomainPtr dom = NULL; + virDomainEventPtr event = NULL; ++ virErrorPtr orig_err; ++ ++ /* Migration failed. Save the current error so nothing squashes it */ ++ orig_err = virSaveLastError(); + + qemuDriverLock(driver); + vm = virDomainFindByName(&driver->domains, dname); +@@ -7540,6 +7554,10 @@ qemudDomainMigrateFinish2 (virConnectPtr + } + + cleanup: ++ if (orig_err) { ++ virSetError(orig_err); ++ virFreeError(orig_err); ++ } + if (vm) + virDomainObjUnlock(vm); + if (event) +diff -rup libvirt-0.7.1/src/util.c new/src/util.c +--- libvirt-0.7.1/src/util.c 2010-06-03 15:30:33.064159000 -0400 ++++ new/src/util.c 2010-06-03 15:33:22.881417000 -0400 +@@ -1764,31 +1764,82 @@ int virDiskNameToIndex(const char *name) + #define AI_CANONIDN 0 + #endif + +-char *virGetHostname(void) ++/* Who knew getting a hostname could be so delicate. In Linux (and Unices ++ * in general), many things depend on "hostname" returning a value that will ++ * resolve one way or another. In the modern world where networks frequently ++ * come and go this is often being hard-coded to resolve to "localhost". If ++ * it *doesn't* resolve to localhost, then we would prefer to have the FQDN. ++ * That leads us to 3 possibilities: ++ * ++ * 1) gethostname() returns an FQDN (not localhost) - we return the string ++ * as-is, it's all of the information we want ++ * 2) gethostname() returns "localhost" - we return localhost; doing further ++ * work to try to resolve it is pointless ++ * 3) gethostname() returns a shortened hostname - in this case, we want to ++ * try to resolve this to a fully-qualified name. Therefore we pass it ++ * to getaddrinfo(). There are two possible responses: ++ * a) getaddrinfo() resolves to a FQDN - return the FQDN ++ * b) getaddrinfo() resolves to localhost - in this case, the data we got ++ * from gethostname() is actually more useful than what we got from ++ * getaddrinfo(). Return the value from gethostname() and hope for ++ * the best. ++ */ ++char *virGetHostname() + { + int r; + char hostname[HOST_NAME_MAX+1], *result; + struct addrinfo hints, *info; + + r = gethostname (hostname, sizeof(hostname)); +- if (r == -1) ++ if (r == -1) { ++ virReportSystemError(NULL, errno, ++ "%s", _("failed to determine host name")); + return NULL; ++ } + NUL_TERMINATE(hostname); + ++ if (STRPREFIX(hostname, "localhost") || strchr(hostname, '.')) { ++ /* in this case, gethostname returned localhost (meaning we can't ++ * do any further canonicalization), or it returned an FQDN (and ++ * we don't need to do any further canonicalization). Return the ++ * string as-is; it's up to callers to check whether "localhost" ++ * is allowed. ++ */ ++ result = strdup(hostname); ++ goto check_and_return; ++ } ++ ++ /* otherwise, it's a shortened, non-localhost, hostname. Attempt to ++ * canonicalize the hostname by running it through getaddrinfo ++ */ ++ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME|AI_CANONIDN; + hints.ai_family = AF_UNSPEC; + r = getaddrinfo(hostname, NULL, &hints, &info); +- if (r != 0) +- return NULL; +- if (info->ai_canonname == NULL) { +- freeaddrinfo(info); ++ if (r != 0) { ++ ReportError(NULL, VIR_ERR_INTERNAL_ERROR, ++ _("getaddrinfo failed for '%s': %s"), ++ hostname, gai_strerror(r)); + return NULL; + } + +- /* Caller frees this string. */ +- result = strdup (info->ai_canonname); ++ if (info->ai_canonname == NULL || ++ STRPREFIX(info->ai_canonname, "localhost")) ++ /* in this case, we tried to canonicalize and we ended up back with ++ * localhost. Ignore the canonicalized name and just return the ++ * original hostname ++ */ ++ result = strdup(hostname); ++ else ++ /* Caller frees this string. */ ++ result = strdup (info->ai_canonname); ++ + freeaddrinfo(info); ++ ++check_and_return: ++ if (result == NULL) ++ virReportOOMError(NULL); + return result; + } + +diff -rup libvirt-0.7.1/src/virterror.c new/src/virterror.c +--- libvirt-0.7.1/src/virterror.c 2009-09-14 06:12:53.000000000 -0400 ++++ new/src/virterror.c 2010-06-03 15:33:22.886409000 -0400 +@@ -287,6 +287,28 @@ virGetLastError(void) + } + + /** ++ * virSetError: ++ * ++ * Set the current error from a previously saved error object ++ * ++ * Can be used to re-set an old error, which may have been squashed by ++ * other functions (like cleanup routines). ++ * ++ * Returns 0 on success, 1 on failure ++ */ ++int ++virSetError(virErrorPtr newerr) ++{ ++ virErrorPtr err; ++ err = virGetLastError(); ++ if (!err) ++ return -1; ++ ++ virResetError(err); ++ return virCopyError(newerr, err); ++} ++ ++/** + * virCopyLastError: + * @to: target to receive the copy + * +@@ -596,6 +618,52 @@ virSetConnError(virConnectPtr conn) + } + } + ++/** ++ * virDispatchError: ++ * @conn: pointer to the hypervisor connection ++ * ++ * Internal helper to do final stage of error ++ * reporting in public APIs. ++ * ++ * - Copy the global error to per-connection error if needed ++ * - Set a generic error message if none is already set ++ * - Invoke the error callback functions ++ */ ++void ++virDispatchError(virConnectPtr conn) ++{ ++ virErrorPtr err = virLastErrorObject(); ++ virErrorFunc handler = virErrorHandler; ++ void *userData = virUserData; ++ ++ /* Should never happen, but doesn't hurt to check */ ++ if (!err) ++ return; ++ ++ /* Set a generic error message if none is already set */ ++ if (err->code == VIR_ERR_OK) ++ virErrorGenericFailure(err); ++ ++ /* Copy the global error to per-connection error if needed */ ++ if (conn) { ++ virMutexLock(&conn->lock); ++ virCopyError(err, &conn->err); ++ ++ if (conn->handler != NULL) { ++ handler = conn->handler; ++ userData = conn->userData; ++ } ++ virMutexUnlock(&conn->lock); ++ } ++ ++ /* Invoke the error callback functions */ ++ if (handler != NULL) { ++ (handler)(userData, err); ++ } else { ++ virDefaultErrorFunc(err); ++ } ++} ++ + + + /** +@@ -634,8 +702,6 @@ virRaiseErrorFull(virConnectPtr conn, + const char *fmt, ...) + { + virErrorPtr to; +- void *userData = virUserData; +- virErrorFunc handler = virErrorHandler; + char *str; + + /* +@@ -653,18 +719,6 @@ virRaiseErrorFull(virConnectPtr conn, + return; + + /* +- * try to find the best place to save and report the error +- */ +- if (conn != NULL) { +- virMutexLock(&conn->lock); +- if (conn->handler != NULL) { +- handler = conn->handler; +- userData = conn->userData; +- } +- virMutexUnlock(&conn->lock); +- } +- +- /* + * formats the message + */ + if (fmt == NULL) { +@@ -683,7 +737,6 @@ virRaiseErrorFull(virConnectPtr conn, + /* + * Save the information about the error + */ +- virResetError(to); + /* + * Delibrately not setting conn, dom & net fields since + * they're utterly unsafe +@@ -701,14 +754,7 @@ virRaiseErrorFull(virConnectPtr conn, + to->int1 = int1; + to->int2 = int2; + +- /* +- * now, report it +- */ +- if (handler != NULL) { +- handler(userData, to); +- } else { +- virDefaultErrorFunc(to); +- } ++ virDispatchError(conn); + } + + /** +diff -rup libvirt-0.7.1/src/virterror_internal.h new/src/virterror_internal.h +--- libvirt-0.7.1/src/virterror_internal.h 2009-07-23 12:33:02.000000000 -0400 ++++ new/src/virterror_internal.h 2010-06-03 15:33:22.890402000 -0400 +@@ -89,6 +89,8 @@ void virReportOOMErrorFull(virConnectPtr + + void virSetGlobalError(void); + void virSetConnError(virConnectPtr conn); ++int virSetError(virErrorPtr newerr); ++void virDispatchError(virConnectPtr conn); + const char *virStrerror(int theerrno, char *errBuf, size_t errBufLen); + + #endif diff --git a/libvirt-0.7.1-network-collision.patch b/libvirt-0.7.1-network-collision.patch new file mode 100644 index 0000000..abc81e8 --- /dev/null +++ b/libvirt-0.7.1-network-collision.patch @@ -0,0 +1,126 @@ +diff -rup libvirt-0.7.1/src/network_driver.c new/src/network_driver.c +--- libvirt-0.7.1/src/network_driver.c 2009-09-15 03:49:04.000000000 -0400 ++++ new/src/network_driver.c 2010-06-15 13:33:01.900912000 -0400 +@@ -43,6 +43,8 @@ + #include + #include + #include ++#include ++#include + + #include "virterror_internal.h" + #include "datatypes.h" +@@ -843,6 +845,102 @@ cleanup: + return ret; + } + ++#define PROC_NET_ROUTE "/proc/net/route" ++ ++static int networkCheckRouteCollision(virNetworkObjPtr network) ++{ ++ int ret = -1, len; ++ char *cur, *buf = NULL; ++ enum {MAX_ROUTE_SIZE = 1024*64}; ++ struct in_addr inaddress, innetmask; ++ unsigned int net_dest; ++ ++ if (!network->def->ipAddress || !network->def->netmask) ++ return 0; ++ ++ if (inet_pton(AF_INET, network->def->ipAddress, &inaddress) <= 0) { ++ networkReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, ++ _("cannot parse IP address '%s'"), ++ network->def->ipAddress); ++ goto error; ++ } ++ if (inet_pton(AF_INET, network->def->netmask, &innetmask) <= 0) { ++ networkReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, ++ _("cannot parse netmask '%s'"), ++ network->def->netmask); ++ goto error; ++ } ++ ++ net_dest = (inaddress.s_addr & innetmask.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.s_addr == mask_val)) { ++ networkReportError(NULL, NULL, NULL, 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(virConnectPtr conn, + struct network_driver *driver, + virNetworkObjPtr network) { +@@ -854,6 +952,10 @@ static int networkStartNetworkDaemon(vir + 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(conn, err, + _("cannot create bridge '%s'"), diff --git a/libvirt-0.7.1-sanitize-pool.patch b/libvirt-0.7.1-sanitize-pool.patch new file mode 100644 index 0000000..37b95eb --- /dev/null +++ b/libvirt-0.7.1-sanitize-pool.patch @@ -0,0 +1,143 @@ +diff -rup libvirt-0.7.1/src/libvirt_private.syms paths/src/libvirt_private.syms +--- libvirt-0.7.1/src/libvirt_private.syms 2010-05-26 12:48:49.276277000 -0400 ++++ paths/src/libvirt_private.syms 2010-05-26 13:00:47.501023000 -0400 +@@ -417,6 +417,7 @@ virParseMacAddr; + virFileDeletePid; + virFindFileInPath; + virFileExists; ++virFileSanitizePath; + virFileHasSuffix; + virFileLinkPointsTo; + virFileMakePath; +diff -rup libvirt-0.7.1/src/storage_conf.c paths/src/storage_conf.c +--- libvirt-0.7.1/src/storage_conf.c 2010-05-26 12:48:48.885306000 -0400 ++++ paths/src/storage_conf.c 2010-05-26 13:00:17.027330000 -0400 +@@ -463,6 +463,7 @@ virStoragePoolDefParseXML(virConnectPtr + char *type = NULL; + char *uuid = NULL; + char *authType = NULL; ++ char *tmppath; + + if (VIR_ALLOC(ret) < 0) { + virReportOOMError(conn); +@@ -610,11 +611,15 @@ virStoragePoolDefParseXML(virConnectPtr + goto cleanup; + } + +- if ((ret->target.path = virXPathString(conn, "string(./target/path)", ctxt)) == NULL) { ++ if ((tmppath = virXPathString(conn, "string(./target/path)", ctxt)) == NULL) { + virStorageReportError(conn, 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(conn, ctxt, &ret->target.perms, + "./target/permissions", 0700) < 0) +diff -rup libvirt-0.7.1/src/storage_driver.c paths/src/storage_driver.c +--- libvirt-0.7.1/src/storage_driver.c 2009-09-10 09:45:00.000000000 -0400 ++++ paths/src/storage_driver.c 2010-05-26 12:59:14.815537000 -0400 +@@ -1152,6 +1152,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++) { +@@ -1162,7 +1167,7 @@ storageVolumeLookupByPath(virConnectPtr + + stable_path = virStorageBackendStablePath(conn, + driver->pools.objs[i], +- path); ++ cleanpath); + /* + * virStorageBackendStablePath already does + * virStorageReportError if it fails; we just need to keep +@@ -1191,6 +1196,7 @@ storageVolumeLookupByPath(virConnectPtr + "%s", _("no storage vol with matching path")); + + cleanup: ++ VIR_FREE(cleanpath); + storageDriverUnlock(driver); + return ret; + } +diff -rup libvirt-0.7.1/src/util.c paths/src/util.c +--- libvirt-0.7.1/src/util.c 2010-05-26 12:48:48.840341000 -0400 ++++ paths/src/util.c 2010-05-26 12:58:02.088721000 -0400 +@@ -1126,6 +1126,55 @@ int virFileExists(const char *path) + 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(NULL); ++ 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; ++} ++ + int virFileMakePath(const char *path) + { + struct stat st; +diff -rup libvirt-0.7.1/src/util.h paths/src/util.h +--- libvirt-0.7.1/src/util.h 2010-05-26 12:48:48.749342000 -0400 ++++ paths/src/util.h 2010-05-26 12:56:57.494264000 -0400 +@@ -107,6 +107,9 @@ char *virFindFileInPath(const char *file + + int virFileExists(const char *path); + ++char *virFileSanitizePath(const char *path); ++ ++ + int virFileMakePath(const char *path); + + int virFileBuildPath(const char *dir, diff --git a/libvirt.spec b/libvirt.spec index 7270f08..ee67bca 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -151,7 +151,7 @@ Summary: Library providing a simple API virtualization Name: libvirt Version: 0.7.1 -Release: 16%{?dist}%{?extra_release} +Release: 17%{?dist}%{?extra_release} License: LGPLv2+ Group: Development/Libraries Source: http://libvirt.org/sources/libvirt-%{version}.tar.gz @@ -223,6 +223,26 @@ Patch27: %{name}-%{version}-fix-usb-busaddr.patch Patch28: %{name}-%{version}-fix-selinux-save.patch # Fix USB devices attached via virt-manager (bz 537227) Patch29: %{name}-%{version}-fix-usb-product.patch +# Fix attach-device crash on cgroup cleanup (bz 556791) +Patch30: %{name}-%{version}-fix-cgroup-crash.patch +# Fix crash on bad LXC URI (bz 554191) +Patch31: %{name}-%{version}-lxc-uri-crash.patch +# Add qemu.conf options for audio workaround +Patch32: %{name}-%{version}-audio-config.patch +# Fix permissions of storage backing stores (bz 579067) +Patch33: %{name}-%{version}-backing-perms.patch +# Fix parsing certain USB sysfs files (bz 598272) +Patch34: %{name}-%{version}-fix-usb-parsing.patch +# Improve migration error reporting (bz 499750) +Patch35: %{name}-%{version}-migrate-errreport.patch +# Sanitize pool target paths (bz 494005) +Patch36: %{name}-%{version}-sanitize-pool.patch +# Add qemu.conf for clear emulator capabilities +Patch37: %{name}-%{version}-caps-option.patch +# Prevent libvirtd inside a VM from breaking network access (bz 235961) +Patch38: %{name}-%{version}-network-collision.patch +# Mention --all in 'virsh list' docs (bz 575512) +Patch39: %{name}-%{version}-man-page-list.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root URL: http://libvirt.org/ @@ -468,6 +488,16 @@ of recent versions of Linux (and other OSes). %patch27 -p1 %patch28 -p1 %patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +#%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 %build # Needed for libvirt-logrotate-create-lxc-uml-dirs.patch @@ -862,6 +892,18 @@ fi %endif %changelog +* Tue Jun 15 2010 Cole Robinson - 0.7.1-17.fc12 +- Fix attach-device crash on cgroup cleanup (bz 556791) +- Fix crash on bad LXC URI (bz 554191) +- Add qemu.conf options for audio workaround +- Fix permissions of storage backing stores (bz 579067) +- Fix parsing certain USB sysfs files (bz 598272) +- Improve migration error reporting (bz 499750) +- Sanitize pool target paths (bz 494005) +- Add qemu.conf for clear emulator capabilities +- Prevent libvirtd inside a VM from breaking network access (bz 235961) +- Mention --all in 'virsh list' docs (bz 575512) + * Mon May 17 2010 Cole Robinson - 0.7.1-16.fc12 - Fix crash with invalid QEmu URI (bz 566070) - Fix VNC TLS crash (bz 544305)