From 43fe83eaf730f3f7762e8a227cf503f95f7ca084 Mon Sep 17 00:00:00 2001 From: CentOS Buildsys Date: Nov 08 2013 15:21:16 +0000 Subject: import libvirt-1.1.1-12.el7.src.rpm --- diff --git a/.libvirt.metadata b/.libvirt.metadata new file mode 100644 index 0000000..3e79f1f --- /dev/null +++ b/.libvirt.metadata @@ -0,0 +1 @@ +a0c72cd89f702fe23974bc4e14f73756ad721571 SOURCES/libvirt-1.1.1.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/libvirt-Add-APIs-for-formatting-systemd-slice-scope-names.patch b/SOURCES/libvirt-Add-APIs-for-formatting-systemd-slice-scope-names.patch new file mode 100644 index 0000000..a651a2c --- /dev/null +++ b/SOURCES/libvirt-Add-APIs-for-formatting-systemd-slice-scope-names.patch @@ -0,0 +1,233 @@ +From 640ff93b2835c02f2f317912e7e2abb20cf3c35d Mon Sep 17 00:00:00 2001 +Message-Id: <640ff93b2835c02f2f317912e7e2abb20cf3c35d.1375465853.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Wed, 31 Jul 2013 19:48:17 +0100 +Subject: [PATCH] Add APIs for formatting systemd slice/scope names + +https://bugzilla.redhat.com/show_bug.cgi?id=980929 + +There are some interesting escaping rules to consider when dealing +with systemd slice/scope names. Thus it is helpful to have APIs +for formatting names + +Signed-off-by: Daniel P. Berrange + +(cherry picked from commit 4574b475df830da437aa6384fd1452cecbb4b7d2) +--- + src/libvirt_private.syms | 2 ++ + src/util/virsystemd.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++-- + src/util/virsystemd.h | 5 +++ + tests/virsystemdtest.c | 49 ++++++++++++++++++++++++++ + 4 files changed, 145 insertions(+), 2 deletions(-) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index d9615ea..0247a46 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1935,6 +1935,8 @@ virSysinfoSetup; + + # util/virsystemd.h + virSystemdCreateMachine; ++virSystemdMakeScopeName; ++virSystemdMakeSliceName; + + + # util/virthread.h +diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c +index 11d1153..251b846 100644 +--- a/src/util/virsystemd.c ++++ b/src/util/virsystemd.c +@@ -27,9 +27,96 @@ + #include "viralloc.h" + #include "virutil.h" + #include "virlog.h" ++#include "virerror.h" + + #define VIR_FROM_THIS VIR_FROM_SYSTEMD + ++ ++static void virSystemdEscapeName(virBufferPtr buf, ++ const char *name) ++{ ++ static const char hextable[16] = "0123456789abcdef"; ++ ++#define ESCAPE(c) \ ++ do { \ ++ virBufferAddChar(buf, '\\'); \ ++ virBufferAddChar(buf, 'x'); \ ++ virBufferAddChar(buf, hextable[(c >> 4) & 15]); \ ++ virBufferAddChar(buf, hextable[c & 15]); \ ++ } while (0) ++ ++#define VALID_CHARS \ ++ "0123456789" \ ++ "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ ":-_.\\" ++ ++ if (*name == '.') { ++ ESCAPE(*name); ++ name++; ++ } ++ ++ while (*name) { ++ if (*name == '/') ++ virBufferAddChar(buf, '-'); ++ else if (*name == '-' || ++ *name == '\\' || ++ !strchr(VALID_CHARS, *name)) ++ ESCAPE(*name); ++ else ++ virBufferAddChar(buf, *name); ++ name++; ++ } ++ ++#undef ESCAPE ++#undef VALID_CHARS ++} ++ ++ ++char *virSystemdMakeScopeName(const char *name, ++ const char *drivername, ++ const char *partition) ++{ ++ virBuffer buf = VIR_BUFFER_INITIALIZER; ++ ++ if (*partition == '/') ++ partition++; ++ ++ virSystemdEscapeName(&buf, partition); ++ virBufferAddChar(&buf, '-'); ++ virSystemdEscapeName(&buf, drivername); ++ virBufferAddLit(&buf, "\\x2d"); ++ virSystemdEscapeName(&buf, name); ++ virBufferAddLit(&buf, ".scope"); ++ ++ if (virBufferError(&buf)) { ++ virReportOOMError(); ++ return NULL; ++ } ++ ++ return virBufferContentAndReset(&buf); ++} ++ ++ ++char *virSystemdMakeSliceName(const char *partition) ++{ ++ virBuffer buf = VIR_BUFFER_INITIALIZER; ++ ++ if (*partition == '/') ++ partition++; ++ ++ virSystemdEscapeName(&buf, partition); ++ virBufferAddLit(&buf, ".slice"); ++ ++ if (virBufferError(&buf)) { ++ virReportOOMError(); ++ return NULL; ++ } ++ ++ return virBufferContentAndReset(&buf); ++} ++ ++ + /** + * virSystemdCreateMachine: + * @name: driver unique name of the machine +@@ -75,8 +162,8 @@ int virSystemdCreateMachine(const char *name, + goto cleanup; + + if (partition) { +- if (virAsprintf(&slicename, "%s.slice", partition) < 0) +- goto cleanup; ++ if (!(slicename = virSystemdMakeSliceName(partition))) ++ goto cleanup; + } else { + if (VIR_STRDUP(slicename, "") < 0) + goto cleanup; +diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h +index 9ca4e0b..414ae5a 100644 +--- a/src/util/virsystemd.h ++++ b/src/util/virsystemd.h +@@ -24,6 +24,11 @@ + + # include "internal.h" + ++char *virSystemdMakeScopeName(const char *name, ++ const char *drivername, ++ const char *slicename); ++char *virSystemdMakeSliceName(const char *partition); ++ + int virSystemdCreateMachine(const char *name, + const char *drivername, + bool privileged, +diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c +index bcf3ad3..a9c6d32 100644 +--- a/tests/virsystemdtest.c ++++ b/tests/virsystemdtest.c +@@ -138,6 +138,38 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED) + return 0; + } + ++ ++struct testScopeData { ++ const char *name; ++ const char *partition; ++ const char *expected; ++}; ++ ++static int ++testScopeName(const void *opaque) ++{ ++ const struct testScopeData *data = opaque; ++ int ret = -1; ++ char *actual = NULL; ++ ++ if (!(actual = virSystemdMakeScopeName(data->name, ++ "lxc", ++ data->partition))) ++ goto cleanup; ++ ++ if (STRNEQ(actual, data->expected)) { ++ fprintf(stderr, "Expected '%s' but got '%s'\n", ++ data->expected, actual); ++ goto cleanup; ++ } ++ ++ ret = 0; ++ ++ cleanup: ++ VIR_FREE(actual); ++ return ret; ++} ++ + static int + mymain(void) + { +@@ -152,6 +184,23 @@ mymain(void) + if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0) + ret = -1; + ++#define TEST_SCOPE(name, partition, unitname) \ ++ do { \ ++ struct testScopeData data = { \ ++ name, partition, unitname \ ++ }; \ ++ if (virtTestRun("Test scopename", 1, testScopeName, &data) < 0) \ ++ ret = -1; \ ++ } while (0) ++ ++ TEST_SCOPE("demo", "/machine", "machine-lxc\\x2ddemo.scope"); ++ TEST_SCOPE("demo-name", "/machine", "machine-lxc\\x2ddemo\\x2dname.scope"); ++ TEST_SCOPE("demo!name", "/machine", "machine-lxc\\x2ddemo\\x21name.scope"); ++ TEST_SCOPE(".demo", "/machine", "machine-lxc\\x2d\\x2edemo.scope"); ++ TEST_SCOPE("demo", "/machine/eng-dept", "machine-eng\\x2ddept-lxc\\x2ddemo.scope"); ++ TEST_SCOPE("demo", "/machine/eng-dept/testing!stuff", ++ "machine-eng\\x2ddept-testing\\x21stuff-lxc\\x2ddemo.scope"); ++ + return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; + } + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-a-man-page-for-virtlockd-daemon.patch b/SOURCES/libvirt-Add-a-man-page-for-virtlockd-daemon.patch new file mode 100644 index 0000000..33cdcf4 --- /dev/null +++ b/SOURCES/libvirt-Add-a-man-page-for-virtlockd-daemon.patch @@ -0,0 +1,225 @@ +From 69da992ba2381c0a8e49c5c05c3f8f5d3f0b5407 Mon Sep 17 00:00:00 2001 +Message-Id: <69da992ba2381c0a8e49c5c05c3f8f5d3f0b5407.1377873638.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 11:35:59 +0100 +Subject: [PATCH] Add a man page for virtlockd daemon + +For https://bugzilla.redhat.com/show_bug.cgi?id=991494 + +Create a virtlockd.pod.in file containing the man page +content for virtlockd. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 6ff0cffd55dae2fa07e6e8dc844312a87946678c) +--- + .gitignore | 2 + + libvirt.spec.in | 1 + + src/Makefile.am | 24 ++++++- + src/locking/virtlockd.pod.in | 158 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 184 insertions(+), 1 deletion(-) + create mode 100644 src/locking/virtlockd.pod.in + +diff --git a/src/Makefile.am b/src/Makefile.am +index 62e427e..5a7e05a 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -1997,9 +1997,31 @@ virtlockd.init: locking/virtlockd.init.in $(top_builddir)/config.status + chmod a+x $@-t && \ + mv $@-t $@ + ++POD2MAN = pod2man -c "Virtualization Support" \ ++ -r "$(PACKAGE)-$(VERSION)" -s 8 + ++$(srcdir)/virtlockd.8.in: locking/virtlockd.pod.in $(top_srcdir)/configure.ac ++ $(AM_V_GEN)$(POD2MAN) --name VIRTLOCKD $< $@ \ ++ && if grep 'POD ERROR' $@ ; then rm $@; exit 1; fi ++ ++virtlockd.8: $(srcdir)/virtlockd.8.in ++ $(AM_V_GEN)sed \ ++ -e 's|[@]sysconfdir[@]|$(sysconfdir)|g' \ ++ -e 's|[@]localstatedir[@]|$(localstatedir)|g' \ ++ < $< > $@-t && \ ++ mv $@-t $@ ++ ++man8_MANS = virtlockd.8 ++ ++MAINTAINERCLEANFILES += $(srcdir)/virtlockd.8.in ++ ++EXTRA_DIST += \ ++ locking/virtlockd.service.in \ ++ locking/virtlockd.socket.in \ ++ locking/virtlockd.pod.in \ ++ virtlockd.8.in \ ++ $(NULL) + +-EXTRA_DIST += locking/virtlockd.service.in locking/virtlockd.socket.in + + if WITH_LIBVIRTD + if LIBVIRT_INIT_SCRIPT_SYSTEMD +diff --git a/src/locking/virtlockd.pod.in b/src/locking/virtlockd.pod.in +new file mode 100644 +index 0000000..f5748ca +--- /dev/null ++++ b/src/locking/virtlockd.pod.in +@@ -0,0 +1,158 @@ ++=head1 NAME ++ ++virtlockd - libvirt lock management daemon ++ ++=head1 SYNOPSIS ++ ++B [ -dv ] [ -f config_file ] [ -p pid_file ] ++ ++B --version ++ ++=head1 DESCRIPTION ++ ++The B program is a server side daemon component of the libvirt ++virtualization management system that is used to manage locks held against ++virtual machine resources, such as their disks. ++ ++This daemon is not used directly by libvirt client applications, rather it ++is called on their behalf by B. By maintaining the locks in a ++standalone daemon, the main libvirtd daemon can be restarted without risk ++of losing locks. The B daemon has the ability to re-exec() ++itself upon receiving SIGUSR1, to allow live upgrades without downtime. ++ ++The virtlockd daemon listens for requests on a local Unix domain socket. ++ ++=head1 OPTIONS ++ ++=over ++ ++=item B<-d, --daemon> ++ ++Run as a daemon and write PID file. ++ ++=item B<-f, --config> I ++ ++Use this configuration file, overriding the default value. ++ ++=item B<-p, --pid-file> I ++ ++Use this name for the PID file, overriding the default value. ++ ++=item B<-v, --verbose> ++ ++Enable output of verbose messages. ++ ++=item B< --version> ++ ++Display version information then exit. ++ ++=back ++ ++=head1 SIGNALS ++ ++On receipt of B virtlockd will re-exec() its binary, while ++maintaining all current locks and clients. This allows for live ++upgrades of the virtlockd service. ++ ++=head1 FILES ++ ++=head2 When run as B. ++ ++=over ++ ++=item F ++ ++The default configuration file used by virtlockd, unless overridden on the ++command line using the B<-f>|B<--config> option. ++ ++=item F ++ ++The sockets libvirtd will use. ++ ++=item F ++ ++The PID file to use, unless overridden by the B<-p>|B<--pid-file> option. ++ ++=back ++ ++=head2 When run as B. ++ ++=over ++ ++=item F<$XDG_CONFIG_HOME/virtlockd.conf> ++ ++The default configuration file used by libvirtd, unless overridden on the ++command line using the B<-f>|B<--config> option. ++ ++=item F<$XDG_RUNTIME_DIR/libvirt/virtlockd-sock> ++ ++The socket libvirtd will use. ++ ++=item F<$XDG_RUNTIME_DIR/libvirt/virtlockd.pid> ++ ++The PID file to use, unless overridden by the B<-p>|B<--pid-file> option. ++ ++=item If $XDG_CONFIG_HOME is not set in your environment, libvirtd will use F<$HOME/.config> ++ ++=item If $XDG_RUNTIME_DIR is not set in your environment, libvirtd will use F<$HOME/.cache> ++ ++=back ++ ++=head1 EXAMPLES ++ ++To retrieve the version of virtlockd: ++ ++ # virtlockd --version ++ virtlockd (libvirt) 1.1.1 ++ # ++ ++To start virtlockd, instructing it to daemonize and create a PID file: ++ ++ # virtlockd -d ++ # ls -la LOCALSTATEDIR/run/virtlockd.pid ++ -rw-r--r-- 1 root root 6 Jul 9 02:40 LOCALSTATEDIR/run/virtlockd.pid ++ # ++ ++=head1 BUGS ++ ++Please report all bugs you discover. This should be done via either: ++ ++=over ++ ++=item a) the mailing list ++ ++L ++ ++=item or, ++ ++B<> ++ ++=item b) the bug tracker ++ ++L ++ ++=item Alternatively, you may report bugs to your software distributor / vendor. ++ ++=back ++ ++=head1 AUTHORS ++ ++Please refer to the AUTHORS file distributed with libvirt. ++ ++=head1 COPYRIGHT ++ ++Copyright (C) 2006-2013 Red Hat, Inc., and the authors listed in the ++libvirt AUTHORS file. ++ ++=head1 LICENSE ++ ++virtlockd is distributed under the terms of the GNU LGPL v2.1+. ++This is free software; see the source for copying conditions. There ++is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR ++PURPOSE ++ ++=head1 SEE ALSO ++ ++L, L ++ ++=cut +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-a-method-for-closing-the-dbus-system-bus-connection.patch b/SOURCES/libvirt-Add-a-method-for-closing-the-dbus-system-bus-connection.patch new file mode 100644 index 0000000..fb44ac0 --- /dev/null +++ b/SOURCES/libvirt-Add-a-method-for-closing-the-dbus-system-bus-connection.patch @@ -0,0 +1,79 @@ +From bc84df329033b0162efd5e4fd2753666d44be3ee Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Mon, 14 Oct 2013 16:45:18 +0100 +Subject: [PATCH] Add a method for closing the dbus system bus connection + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=998365 + +If the dbus system bus connection is marked as private, then +allow it to be closed. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 489beb0aba5aad0e5423e123db9a7ab67421ca48) +Signed-off-by: Jiri Denemark +--- + src/libvirt_private.syms | 1 + + src/util/virdbus.c | 12 ++++++++++++ + src/util/virdbus.h | 1 + + 3 files changed, 14 insertions(+) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index c91a9f9..5e4de67 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1292,6 +1292,7 @@ virConfWriteMem; + + # util/virdbus.h + virDBusCallMethod; ++virDBusCloseSystemBus; + virDBusGetSessionBus; + virDBusGetSystemBus; + virDBusHasSystemBus; +diff --git a/src/util/virdbus.c b/src/util/virdbus.c +index bcc5b1c..da69430 100644 +--- a/src/util/virdbus.c ++++ b/src/util/virdbus.c +@@ -122,6 +122,14 @@ virDBusHasSystemBus(void) + } + + ++void virDBusCloseSystemBus(void) ++{ ++ if (systembus && !sharedBus) { ++ dbus_connection_close(systembus); ++ systembus = NULL; ++ } ++} ++ + static void virDBusSessionBusInit(void) + { + sessionbus = virDBusBusInit(DBUS_BUS_SESSION, &sessiondbuserr); +@@ -1293,6 +1301,10 @@ virDBusHasSystemBus(void) + return false; + } + ++void virDBusCloseSystemBus(void) ++{ ++ /* nothing */ ++} + + DBusConnection *virDBusGetSessionBus(void) + { +diff --git a/src/util/virdbus.h b/src/util/virdbus.h +index 125a405..979c566 100644 +--- a/src/util/virdbus.h ++++ b/src/util/virdbus.h +@@ -35,6 +35,7 @@ void virDBusSetSharedBus(bool shared); + + DBusConnection *virDBusGetSystemBus(void); + bool virDBusHasSystemBus(void); ++void virDBusCloseSystemBus(void); + DBusConnection *virDBusGetSessionBus(void); + + int virDBusCallMethod(DBusConnection *conn, +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-an-example-config-file-for-virtlockd.patch b/SOURCES/libvirt-Add-an-example-config-file-for-virtlockd.patch new file mode 100644 index 0000000..efa95f2 --- /dev/null +++ b/SOURCES/libvirt-Add-an-example-config-file-for-virtlockd.patch @@ -0,0 +1,220 @@ +From 07ed15bbbd7c0fc2c946620f15f1963882144633 Mon Sep 17 00:00:00 2001 +Message-Id: <07ed15bbbd7c0fc2c946620f15f1963882144633.1377873638.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 11:36:00 +0100 +Subject: [PATCH] Add an example config file for virtlockd + +For https://bugzilla.redhat.com/show_bug.cgi?id=991494 + +The virtlockd daemon supports an /etc/libvirt/virtlockd.conf +config file, but we never installed a default config, nor +created any augeas scripts. This change addresses that omission. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 38550ae80978d590a0dccf79108ec96180771fe1) +--- + .gitignore | 1 + + libvirt.spec.in | 3 ++ + src/Makefile.am | 20 ++++++++++++- + src/locking/test_virtlockd.aug.in | 12 ++++++++ + src/locking/virtlockd.aug | 44 ++++++++++++++++++++++++++++ + src/locking/virtlockd.conf | 60 +++++++++++++++++++++++++++++++++++++++ + 6 files changed, 139 insertions(+), 1 deletion(-) + create mode 100644 src/locking/test_virtlockd.aug.in + create mode 100644 src/locking/virtlockd.aug + create mode 100644 src/locking/virtlockd.conf + +diff --git a/src/Makefile.am b/src/Makefile.am +index 5a7e05a..12ca204 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -1586,7 +1586,7 @@ check-local: check-augeas + $(NULL) + + check-augeas: check-augeas-qemu check-augeas-lxc check-augeas-sanlock \ +- check-augeas-lockd ++ check-augeas-lockd check-augeas-virtlockd + + AUG_GENTEST = $(PERL) $(top_srcdir)/build-aux/augeas-gentest.pl + EXTRA_DIST += $(top_srcdir)/build-aux/augeas-gentest.pl +@@ -1634,11 +1634,20 @@ test_libvirt_lockd.aug: locking/test_libvirt_lockd.aug.in \ + locking/qemu-lockd.conf $(AUG_GENTEST) + $(AM_V_GEN)$(AUG_GENTEST) locking/qemu-lockd.conf $< $@ + ++test_virtlockd.aug: locking/test_virtlockd.aug.in \ ++ locking/virtlockd.conf $(AUG_GENTEST) ++ $(AM_V_GEN)$(AUG_GENTEST) locking/virtlockd.conf $< $@ ++ + check-augeas-lockd: test_libvirt_lockd.aug + $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \ + '$(AUGPARSE)' -I $(srcdir)/locking test_libvirt_lockd.aug; \ + fi + ++check-augeas-virtlockd: test_virtlockd.aug ++ $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \ ++ '$(AUGPARSE)' -I $(srcdir)/locking test_virtlockd.aug; \ ++ fi ++ + # + # Build our version script. This is composed of three parts: + # +@@ -2013,6 +2022,12 @@ virtlockd.8: $(srcdir)/virtlockd.8.in + + man8_MANS = virtlockd.8 + ++conf_DATA += locking/virtlockd.conf ++ ++augeas_DATA += locking/virtlockd.aug ++augeastest_DATA += test_virtlockd.aug ++ ++CLEANFILES += test_virtlockd.aug + MAINTAINERCLEANFILES += $(srcdir)/virtlockd.8.in + + EXTRA_DIST += \ +@@ -2020,6 +2035,9 @@ EXTRA_DIST += \ + locking/virtlockd.socket.in \ + locking/virtlockd.pod.in \ + virtlockd.8.in \ ++ locking/virtlockd.aug \ ++ locking/virtlockd.conf \ ++ locking/test_virtlockd.aug.in \ + $(NULL) + + +diff --git a/src/locking/test_virtlockd.aug.in b/src/locking/test_virtlockd.aug.in +new file mode 100644 +index 0000000..dcd47c3 +--- /dev/null ++++ b/src/locking/test_virtlockd.aug.in +@@ -0,0 +1,12 @@ ++module Test_virtlockd = ++ let conf = "log_level = 3 ++log_filters=\"3:remote 4:event\" ++log_outputs=\"3:syslog:libvirtd\" ++log_buffer_size = 64 ++" ++ ++ test Libvirtd.lns get conf = ++ { "log_level" = "3" } ++ { "log_filters" = "3:remote 4:event" } ++ { "log_outputs" = "3:syslog:libvirtd" } ++ { "log_buffer_size" = "64" } +diff --git a/src/locking/virtlockd.aug b/src/locking/virtlockd.aug +new file mode 100644 +index 0000000..9d20e72 +--- /dev/null ++++ b/src/locking/virtlockd.aug +@@ -0,0 +1,44 @@ ++(* /etc/libvirt/libvirtd.conf *) ++ ++module Libvirtd = ++ autoload xfm ++ ++ let eol = del /[ \t]*\n/ "\n" ++ let value_sep = del /[ \t]*=[ \t]*/ " = " ++ let indent = del /[ \t]*/ "" ++ ++ let array_sep = del /,[ \t\n]*/ ", " ++ let array_start = del /\[[ \t\n]*/ "[ " ++ let array_end = del /\]/ "]" ++ ++ let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\"" ++ let bool_val = store /0|1/ ++ let int_val = store /[0-9]+/ ++ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ "" ++ let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end ++ ++ let str_entry (kw:string) = [ key kw . value_sep . str_val ] ++ let bool_entry (kw:string) = [ key kw . value_sep . bool_val ] ++ let int_entry (kw:string) = [ key kw . value_sep . int_val ] ++ let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ] ++ ++ ++ (* Config entry grouped by function - same order as example config *) ++ let logging_entry = int_entry "log_level" ++ | str_entry "log_filters" ++ | str_entry "log_outputs" ++ | int_entry "log_buffer_size" ++ ++ (* Each enty in the config is one of the following three ... *) ++ let entry = logging_entry ++ let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ] ++ let empty = [ label "#empty" . eol ] ++ ++ let record = indent . entry . eol ++ ++ let lns = ( record | comment | empty ) * ++ ++ let filter = incl "/etc/libvirt/virtlockd.conf" ++ . Util.stdexcl ++ ++ let xfm = transform lns filter +diff --git a/src/locking/virtlockd.conf b/src/locking/virtlockd.conf +new file mode 100644 +index 0000000..b6450b4 +--- /dev/null ++++ b/src/locking/virtlockd.conf +@@ -0,0 +1,60 @@ ++# Master virtlockd daemon configuration file ++# ++ ++################################################################# ++# ++# Logging controls ++# ++ ++# Logging level: 4 errors, 3 warnings, 2 information, 1 debug ++# basically 1 will log everything possible ++#log_level = 3 ++ ++# Logging filters: ++# A filter allows to select a different logging level for a given category ++# of logs ++# The format for a filter is one of: ++# x:name ++# x:+name ++# where name is a string which is matched against source file name, ++# e.g., "remote", "qemu", or "util/json", the optional "+" prefix ++# tells libvirt to log stack trace for each message matching name, ++# and x is the minimal level where matching messages should be logged: ++# 1: DEBUG ++# 2: INFO ++# 3: WARNING ++# 4: ERROR ++# ++# Multiple filter can be defined in a single @filters, they just need to be ++# separated by spaces. ++# ++# e.g. to only get warning or errors from the remote layer and only errors ++# from the event layer: ++#log_filters="3:remote 4:event" ++ ++# Logging outputs: ++# An output is one of the places to save logging information ++# The format for an output can be: ++# x:stderr ++# output goes to stderr ++# x:syslog:name ++# use syslog for the output and use the given name as the ident ++# x:file:file_path ++# output to a file, with the given filepath ++# In all case the x prefix is the minimal level, acting as a filter ++# 1: DEBUG ++# 2: INFO ++# 3: WARNING ++# 4: ERROR ++# ++# Multiple output can be defined, they just need to be separated by spaces. ++# e.g. to log all warnings and errors to syslog under the virtlockd ident: ++#log_outputs="3:syslog:virtlockd" ++# ++ ++# Log debug buffer size: default 64 ++# The daemon keeps an internal debug log buffer which will be dumped in case ++# of crash or upon receiving a SIGUSR2 signal. This setting allows to override ++# the default buffer size in kilobytes. ++# If value is 0 or less the debug log buffer is deactivated ++#log_buffer_size = 64 +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllDomains-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllDomains-RPC-call.patch new file mode 100644 index 0000000..d9749de --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllDomains-RPC-call.patch @@ -0,0 +1,131 @@ +From f79b8cfc288deb39dc652a7a552f8bcb85dc1148 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:06 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllDomains RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllDomains call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 9e97128ba5a1045b71b50adb23993f09628f0a24) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 15 +++++++++++---- + src/remote/remote_protocol.x | 15 +++++---------- + 3 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index e228cba..8289cb5 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -1050,6 +1050,13 @@ remoteDispatchConnectListAllDomains(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (ndomains > REMOTE_DOMAIN_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many domains '%d' for limit '%d'"), ++ ndomains, REMOTE_DOMAIN_LIST_MAX); ++ goto cleanup; ++ } ++ + if (doms && ndomains) { + if (VIR_ALLOC_N(ret->domains.domains_val, ndomains) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 14c16f6..cd2b9a9 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -1370,10 +1370,10 @@ remoteConnectListDomains(virConnectPtr conn, int *ids, int maxids) + + remoteDriverLock(priv); + +- if (maxids > REMOTE_DOMAIN_ID_LIST_MAX) { ++ if (maxids > REMOTE_DOMAIN_LIST_MAX) { + virReportError(VIR_ERR_RPC, +- _("too many remote domain IDs: %d > %d"), +- maxids, REMOTE_DOMAIN_ID_LIST_MAX); ++ _("Too many domains '%d' for limit '%d'"), ++ maxids, REMOTE_DOMAIN_LIST_MAX); + goto done; + } + args.maxids = maxids; +@@ -1386,7 +1386,7 @@ remoteConnectListDomains(virConnectPtr conn, int *ids, int maxids) + + if (ret.ids.ids_len > maxids) { + virReportError(VIR_ERR_RPC, +- _("too many remote domain IDs: %d > %d"), ++ _("Too many domains '%d' for limit '%d'"), + ret.ids.ids_len, maxids); + goto cleanup; + } +@@ -1433,6 +1433,13 @@ remoteConnectListAllDomains(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.domains.domains_len > REMOTE_DOMAIN_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many domains '%d' for limit '%d'"), ++ ret.domains.domains_len, REMOTE_DOMAIN_LIST_MAX); ++ goto cleanup; ++ } ++ + if (domains) { + if (VIR_ALLOC_N(doms, ret.domains.domains_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 9e3918c..718e398 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -73,13 +73,8 @@ typedef string remote_nonnull_string; + /* A long string, which may be NULL. */ + typedef remote_nonnull_string *remote_string; + +-/* This just places an upper limit on the length of lists of +- * domain IDs which may be sent via the protocol. +- */ +-const REMOTE_DOMAIN_ID_LIST_MAX = 16384; +- +-/* Upper limit on lists of domain names. */ +-const REMOTE_DOMAIN_NAME_LIST_MAX = 16384; ++/* Upper limit on lists of domains. */ ++const REMOTE_DOMAIN_LIST_MAX = 16384; + + /* Upper limit on cpumap (bytes) passed to virDomainPinVcpu. */ + const REMOTE_CPUMAP_MAX = 2048; +@@ -724,7 +719,7 @@ struct remote_connect_list_domains_args { + }; + + struct remote_connect_list_domains_ret { +- int ids; /* insert@1 */ ++ int ids; /* insert@1 */ + }; + + struct remote_connect_num_of_domains_ret { +@@ -990,7 +985,7 @@ struct remote_connect_list_defined_domains_args { + }; + + struct remote_connect_list_defined_domains_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_connect_num_of_defined_domains_ret { +@@ -2665,7 +2660,7 @@ struct remote_connect_list_all_domains_args { + }; + + struct remote_connect_list_all_domains_ret { +- remote_nonnull_domain domains<>; ++ remote_nonnull_domain domains; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllInterfaces-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllInterfaces-RPC-call.patch new file mode 100644 index 0000000..9f1cb25 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllInterfaces-RPC-call.patch @@ -0,0 +1,106 @@ +From 0c0ab54756999324d57973ff4b0102a54bc0b7af Mon Sep 17 00:00:00 2001 +Message-Id: <0c0ab54756999324d57973ff4b0102a54bc0b7af.1377873640.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:10 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllInterfaces RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllInterfaces call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 8be2172897c272ead150ad59a63946ab97562a11) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 13 +++++-------- + 3 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index b6501e0..871b0df 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4256,6 +4256,13 @@ remoteDispatchConnectListAllInterfaces(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (nifaces > REMOTE_INTERFACE_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many interfaces '%d' for limit '%d'"), ++ nifaces, REMOTE_INTERFACE_LIST_MAX); ++ goto cleanup; ++ } ++ + if (ifaces && nifaces) { + if (VIR_ALLOC_N(ret->ifaces.ifaces_val, nifaces) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index e555704..4d82452 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -2909,6 +2909,13 @@ remoteConnectListAllInterfaces(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.ifaces.ifaces_len > REMOTE_INTERFACE_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many interfaces '%d' for limit '%d'"), ++ ret.ifaces.ifaces_len, REMOTE_INTERFACE_LIST_MAX); ++ goto cleanup; ++ } ++ + if (ifaces) { + if (VIR_ALLOC_N(tmp_ifaces, ret.ifaces.ifaces_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index f1e27fa..573d63f 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -91,11 +91,8 @@ const REMOTE_MIGRATE_COOKIE_MAX = 16384; + /* Upper limit on lists of networks. */ + const REMOTE_NETWORK_LIST_MAX = 16384; + +-/* Upper limit on lists of interface names. */ +-const REMOTE_INTERFACE_NAME_LIST_MAX = 16384; +- +-/* Upper limit on lists of defined interface names. */ +-const REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX = 16384; ++/* Upper limit on lists of interfaces. */ ++const REMOTE_INTERFACE_LIST_MAX = 16384; + + /* Upper limit on lists of storage pools. */ + const REMOTE_STORAGE_POOL_LIST_MAX = 4096; +@@ -1478,7 +1475,7 @@ struct remote_connect_list_interfaces_args { + }; + + struct remote_connect_list_interfaces_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_connect_num_of_defined_interfaces_ret { +@@ -1490,7 +1487,7 @@ struct remote_connect_list_defined_interfaces_args { + }; + + struct remote_connect_list_defined_interfaces_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_interface_lookup_by_name_args { +@@ -2701,7 +2698,7 @@ struct remote_connect_list_all_interfaces_args { + }; + + struct remote_connect_list_all_interfaces_ret { +- remote_nonnull_interface ifaces<>; ++ remote_nonnull_interface ifaces; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNWFilters-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNWFilters-RPC-call.patch new file mode 100644 index 0000000..5b1bfc2 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNWFilters-RPC-call.patch @@ -0,0 +1,94 @@ +From d7fbd5a9272eeaadebf5511045a9904f4f26bd1e Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:12 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllNWFilters RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllNWFilters call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 12034511a195bdbcc06401dfec07ce4837e1f5b4) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 8 ++++---- + 3 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index 697aa58..e19b42d 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4374,6 +4374,13 @@ remoteDispatchConnectListAllNWFilters(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (nfilters > REMOTE_NWFILTER_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many network filters '%d' for limit '%d'"), ++ nfilters, REMOTE_NWFILTER_LIST_MAX); ++ goto cleanup; ++ } ++ + if (filters && nfilters) { + if (VIR_ALLOC_N(ret->filters.filters_val, nfilters) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index b170a06..d486fa5 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -3041,6 +3041,13 @@ remoteConnectListAllNWFilters(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.filters.filters_len > REMOTE_NWFILTER_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many network filters '%d' for limit '%d'"), ++ ret.filters.filters_len, REMOTE_NWFILTER_LIST_MAX); ++ goto cleanup; ++ } ++ + if (filters) { + if (VIR_ALLOC_N(tmp_filters, ret.filters.filters_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 21059c8..b2841a7 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -106,8 +106,8 @@ const REMOTE_NODE_DEVICE_LIST_MAX = 16384; + /* Upper limit on lists of node device capabilities. */ + const REMOTE_NODE_DEVICE_CAPS_LIST_MAX = 65536; + +-/* Upper limit on lists of network filter names. */ +-const REMOTE_NWFILTER_NAME_LIST_MAX = 1024; ++/* Upper limit on lists of network filters. */ ++const REMOTE_NWFILTER_LIST_MAX = 1024; + + /* Upper limit on list of scheduler parameters. */ + const REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX = 16; +@@ -1423,7 +1423,7 @@ struct remote_connect_list_nwfilters_args { + }; + + struct remote_connect_list_nwfilters_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_nwfilter_lookup_by_uuid_args { +@@ -2718,7 +2718,7 @@ struct remote_connect_list_all_nwfilters_args { + }; + + struct remote_connect_list_all_nwfilters_ret { +- remote_nonnull_nwfilter filters<>; ++ remote_nonnull_nwfilter filters; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNetworks-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNetworks-RPC-call.patch new file mode 100644 index 0000000..6711ed1 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNetworks-RPC-call.patch @@ -0,0 +1,103 @@ +From c492435723a14ee2fa5991228c98a791ad68c7ac Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:09 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllNetworks RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllNetworks call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 174f7dd5bafb1a6d8e341078149855cd2d790082) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 10 +++++----- + 3 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index 512170b..b6501e0 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4197,6 +4197,13 @@ remoteDispatchConnectListAllNetworks(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (nnets > REMOTE_NETWORK_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many networks '%d' for limit '%d'"), ++ nnets, REMOTE_NETWORK_LIST_MAX); ++ goto cleanup; ++ } ++ + if (nets && nnets) { + if (VIR_ALLOC_N(ret->nets.nets_val, nnets) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 542cb39..e555704 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -2843,6 +2843,13 @@ remoteConnectListAllNetworks(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.nets.nets_len > REMOTE_NETWORK_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many networks '%d' for limit '%d'"), ++ ret.nets.nets_len, REMOTE_NETWORK_LIST_MAX); ++ goto cleanup; ++ } ++ + if (nets) { + if (VIR_ALLOC_N(tmp_nets, ret.nets.nets_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 2034aa1..f1e27fa 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -88,8 +88,8 @@ const REMOTE_CPUMAPS_MAX = 8388608; + /* Upper limit on migrate cookie. */ + const REMOTE_MIGRATE_COOKIE_MAX = 16384; + +-/* Upper limit on lists of network names. */ +-const REMOTE_NETWORK_NAME_LIST_MAX = 16384; ++/* Upper limit on lists of networks. */ ++const REMOTE_NETWORK_LIST_MAX = 16384; + + /* Upper limit on lists of interface names. */ + const REMOTE_INTERFACE_NAME_LIST_MAX = 16384; +@@ -1317,7 +1317,7 @@ struct remote_connect_list_networks_args { + }; + + struct remote_connect_list_networks_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_connect_num_of_defined_networks_ret { +@@ -1329,7 +1329,7 @@ struct remote_connect_list_defined_networks_args { + }; + + struct remote_connect_list_defined_networks_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_network_lookup_by_uuid_args { +@@ -2691,7 +2691,7 @@ struct remote_connect_list_all_networks_args { + }; + + struct remote_connect_list_all_networks_ret { +- remote_nonnull_network nets<>; ++ remote_nonnull_network nets; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNodeDevices-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNodeDevices-RPC-call.patch new file mode 100644 index 0000000..b053555 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllNodeDevices-RPC-call.patch @@ -0,0 +1,94 @@ +From d7661c0cf4ed8d2fbb974659a329e52b28b5e178 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:11 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllNodeDevices RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllNodeDevices call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 1dcff6a7ea668feeeec55ee577e5182a1c0082e4) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 8 ++++---- + 3 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index 871b0df..697aa58 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4315,6 +4315,13 @@ remoteDispatchConnectListAllNodeDevices(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (ndevices > REMOTE_NODE_DEVICE_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many node devices '%d' for limit '%d'"), ++ ndevices, REMOTE_NODE_DEVICE_LIST_MAX); ++ goto cleanup; ++ } ++ + if (devices && ndevices) { + if (VIR_ALLOC_N(ret->devices.devices_val, ndevices) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 4d82452..b170a06 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -2975,6 +2975,13 @@ remoteConnectListAllNodeDevices(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.devices.devices_len > REMOTE_NODE_DEVICE_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many node devices '%d' for limit '%d'"), ++ ret.devices.devices_len, REMOTE_NODE_DEVICE_LIST_MAX); ++ goto cleanup; ++ } ++ + if (devices) { + if (VIR_ALLOC_N(tmp_devices, ret.devices.devices_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 573d63f..21059c8 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -100,8 +100,8 @@ const REMOTE_STORAGE_POOL_LIST_MAX = 4096; + /* Upper limit on lists of storage vols. */ + const REMOTE_STORAGE_VOL_LIST_MAX = 16384; + +-/* Upper limit on lists of node device names. */ +-const REMOTE_NODE_DEVICE_NAME_LIST_MAX = 16384; ++/* Upper limit on lists of node devices. */ ++const REMOTE_NODE_DEVICE_LIST_MAX = 16384; + + /* Upper limit on lists of node device capabilities. */ + const REMOTE_NODE_DEVICE_CAPS_LIST_MAX = 65536; +@@ -1863,7 +1863,7 @@ struct remote_node_list_devices_args { + }; + + struct remote_node_list_devices_ret { +- remote_nonnull_string names; /* insert@2 */ ++ remote_nonnull_string names; /* insert@2 */ + }; + + struct remote_node_device_lookup_by_name_args { +@@ -2708,7 +2708,7 @@ struct remote_connect_list_all_node_devices_args { + }; + + struct remote_connect_list_all_node_devices_ret { +- remote_nonnull_node_device devices<>; ++ remote_nonnull_node_device devices; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllSecrets-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllSecrets-RPC-call.patch new file mode 100644 index 0000000..4b88488 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllSecrets-RPC-call.patch @@ -0,0 +1,92 @@ +From 6040b8ad9a04434782f7cd037db33768456e151a Mon Sep 17 00:00:00 2001 +Message-Id: <6040b8ad9a04434782f7cd037db33768456e151a.1377873640.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:13 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllSecrets RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllSecrets call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 47fb5672f2f4e9efcd4e9ec30f5e723c46fa8e6f) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 6 +++--- + 3 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index e19b42d..6ace7af 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4433,6 +4433,13 @@ remoteDispatchConnectListAllSecrets(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (nsecrets > REMOTE_SECRET_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many secrets '%d' for limit '%d'"), ++ nsecrets, REMOTE_SECRET_LIST_MAX); ++ goto cleanup; ++ } ++ + if (secrets && nsecrets) { + if (VIR_ALLOC_N(ret->secrets.secrets_val, nsecrets) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index d486fa5..62e77a5 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -3107,6 +3107,13 @@ remoteConnectListAllSecrets(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.secrets.secrets_len > REMOTE_SECRET_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many secrets '%d' for limit '%d'"), ++ ret.secrets.secrets_len, REMOTE_SECRET_LIST_MAX); ++ goto cleanup; ++ } ++ + if (secrets) { + if (VIR_ALLOC_N(tmp_secrets, ret.secrets.secrets_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index b2841a7..a1c23da 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -188,7 +188,7 @@ const REMOTE_SECRET_VALUE_MAX = 65536; + /* + * Upper limit on list of secrets. + */ +-const REMOTE_SECRET_UUID_LIST_MAX = 16384; ++const REMOTE_SECRET_LIST_MAX = 16384; + + /* + * Upper limit on list of CPUs accepted when computing a baseline CPU. +@@ -2002,7 +2002,7 @@ struct remote_connect_list_secrets_args { + }; + + struct remote_connect_list_secrets_ret { +- remote_nonnull_string uuids; /* insert@1 */ ++ remote_nonnull_string uuids; /* insert@1 */ + }; + + struct remote_secret_lookup_by_uuid_args { +@@ -2728,7 +2728,7 @@ struct remote_connect_list_all_secrets_args { + }; + + struct remote_connect_list_all_secrets_ret { +- remote_nonnull_secret secrets<>; ++ remote_nonnull_secret secrets; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllStoragePools-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllStoragePools-RPC-call.patch new file mode 100644 index 0000000..9d1a77e --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virConnectListAllStoragePools-RPC-call.patch @@ -0,0 +1,103 @@ +From 68580ef359c7940d5f4b88f2ed2612d99a32cbf0 Mon Sep 17 00:00:00 2001 +Message-Id: <68580ef359c7940d5f4b88f2ed2612d99a32cbf0.1377873640.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:07 +0100 +Subject: [PATCH] Add bounds checking on virConnectListAllStoragePools RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virConnectListAllStoragePools call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit c853fa8febad5c4990936521f9426f3e3df74f98) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 10 +++++----- + 3 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index 8289cb5..42c1c47 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4073,6 +4073,13 @@ remoteDispatchConnectListAllStoragePools(virNetServerPtr server ATTRIBUTE_UNUSED + args->flags)) < 0) + goto cleanup; + ++ if (npools > REMOTE_STORAGE_POOL_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many storage pools '%d' for limit '%d'"), ++ npools, REMOTE_STORAGE_POOL_LIST_MAX); ++ goto cleanup; ++ } ++ + if (pools && npools) { + if (VIR_ALLOC_N(ret->pools.pools_val, npools) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index cd2b9a9..622647b 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -3276,6 +3276,13 @@ remoteConnectListAllStoragePools(virConnectPtr conn, + (char *) &ret) == -1) + goto done; + ++ if (ret.pools.pools_len > REMOTE_STORAGE_POOL_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many storage pools '%d' for limit '%d'"), ++ ret.pools.pools_len, REMOTE_STORAGE_POOL_LIST_MAX); ++ goto cleanup; ++ } ++ + if (pools) { + if (VIR_ALLOC_N(tmp_pools, ret.pools.pools_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 718e398..6e996b4 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -97,8 +97,8 @@ const REMOTE_INTERFACE_NAME_LIST_MAX = 16384; + /* Upper limit on lists of defined interface names. */ + const REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX = 16384; + +-/* Upper limit on lists of storage pool names. */ +-const REMOTE_STORAGE_POOL_NAME_LIST_MAX = 4096; ++/* Upper limit on lists of storage pools. */ ++const REMOTE_STORAGE_POOL_LIST_MAX = 4096; + + /* Upper limit on lists of storage vol names. */ + const REMOTE_STORAGE_VOL_NAME_LIST_MAX = 16384; +@@ -1604,7 +1604,7 @@ struct remote_connect_list_storage_pools_args { + }; + + struct remote_connect_list_storage_pools_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_connect_num_of_defined_storage_pools_ret { +@@ -1616,7 +1616,7 @@ struct remote_connect_list_defined_storage_pools_args { + }; + + struct remote_connect_list_defined_storage_pools_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_connect_find_storage_pool_sources_args { +@@ -2670,7 +2670,7 @@ struct remote_connect_list_all_storage_pools_args { + }; + + struct remote_connect_list_all_storage_pools_ret { +- remote_nonnull_storage_pool pools<>; ++ remote_nonnull_storage_pool pools; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virDomain-SnapshotListAllChildren-ListAllSnapshots-RPC-calls.patch b/SOURCES/libvirt-Add-bounds-checking-on-virDomain-SnapshotListAllChildren-ListAllSnapshots-RPC-calls.patch new file mode 100644 index 0000000..21b5387 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virDomain-SnapshotListAllChildren-ListAllSnapshots-RPC-calls.patch @@ -0,0 +1,141 @@ +From c0d1584975c670974915498f02da48887f26fb9e Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:05 +0100 +Subject: [PATCH] Add bounds checking on virDomain{SnapshotListAllChildren, + ListAllSnapshots} RPC calls + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virDomain{SnapshotListAllChildren,ListAllSnapshots} +calls were not bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit a43d4f543c31a17ab3a29ad8e01828ff30390622) +--- + daemon/remote.c | 14 ++++++++++++++ + src/remote/remote_driver.c | 16 ++++++++++++++++ + src/remote/remote_protocol.x | 10 +++++----- + 3 files changed, 35 insertions(+), 5 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index ad78011..e228cba 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -3934,6 +3934,13 @@ remoteDispatchDomainListAllSnapshots(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (nsnaps > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many domain snapshots '%d' for limit '%d'"), ++ nsnaps, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX); ++ goto cleanup; ++ } ++ + if (snaps && nsnaps) { + if (VIR_ALLOC_N(ret->snapshots.snapshots_val, nsnaps) < 0) + goto cleanup; +@@ -3996,6 +4003,13 @@ remoteDispatchDomainSnapshotListAllChildren(virNetServerPtr server ATTRIBUTE_UNU + args->flags)) < 0) + goto cleanup; + ++ if (nsnaps > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many domain snapshots '%d' for limit '%d'"), ++ nsnaps, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX); ++ goto cleanup; ++ } ++ + if (snaps && nsnaps) { + if (VIR_ALLOC_N(ret->snapshots.snapshots_val, nsnaps) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 33b2b0f..14c16f6 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -5760,6 +5760,14 @@ remoteDomainListAllSnapshots(virDomainPtr dom, + (char *) &ret) == -1) + goto done; + ++ if (ret.snapshots.snapshots_len > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many domain snapshots '%d' for limit '%d'"), ++ ret.snapshots.snapshots_len, ++ REMOTE_DOMAIN_SNAPSHOT_LIST_MAX); ++ goto cleanup; ++ } ++ + if (snapshots) { + if (VIR_ALLOC_N(snaps, ret.snapshots.snapshots_len + 1) < 0) + goto cleanup; +@@ -5819,6 +5827,14 @@ remoteDomainSnapshotListAllChildren(virDomainSnapshotPtr parent, + (char *) &ret) == -1) + goto done; + ++ if (ret.snapshots.snapshots_len > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many domain snapshots '%d' for limit '%d'"), ++ ret.snapshots.snapshots_len, ++ REMOTE_DOMAIN_SNAPSHOT_LIST_MAX); ++ goto cleanup; ++ } ++ + if (snapshots) { + if (VIR_ALLOC_N(snaps, ret.snapshots.snapshots_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index eff7e1c..9e3918c 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -154,7 +154,7 @@ const REMOTE_AUTH_TYPE_LIST_MAX = 20; + const REMOTE_DOMAIN_MEMORY_STATS_MAX = 1024; + + /* Upper limit on lists of domain snapshots. */ +-const REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX = 1024; ++const REMOTE_DOMAIN_SNAPSHOT_LIST_MAX = 1024; + + /* Maximum length of a block peek buffer message. + * Note applications need to be aware of this limit and issue multiple +@@ -2396,7 +2396,7 @@ struct remote_domain_snapshot_list_names_args { + }; + + struct remote_domain_snapshot_list_names_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_domain_list_all_snapshots_args { +@@ -2406,7 +2406,7 @@ struct remote_domain_list_all_snapshots_args { + }; + + struct remote_domain_list_all_snapshots_ret { +- remote_nonnull_domain_snapshot snapshots<>; ++ remote_nonnull_domain_snapshot snapshots; + int ret; + }; + +@@ -2426,7 +2426,7 @@ struct remote_domain_snapshot_list_children_names_args { + }; + + struct remote_domain_snapshot_list_children_names_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + struct remote_domain_snapshot_list_all_children_args { +@@ -2436,7 +2436,7 @@ struct remote_domain_snapshot_list_all_children_args { + }; + + struct remote_domain_snapshot_list_all_children_ret { +- remote_nonnull_domain_snapshot snapshots<>; ++ remote_nonnull_domain_snapshot snapshots; + int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virDomainGetJobStats-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virDomainGetJobStats-RPC-call.patch new file mode 100644 index 0000000..f92db94 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virDomainGetJobStats-RPC-call.patch @@ -0,0 +1,85 @@ +From d6add35e43b45b892ad9eb015d29c0b2720001c2 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:04 +0100 +Subject: [PATCH] Add bounds checking on virDomainGetJobStats RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virDomainGetJobStats call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 6d7d0b1869ed293e3208d11f375cecea0129dfc5) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 8 ++++++++ + src/remote/remote_protocol.x | 5 ++++- + 3 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index a11ba94..ad78011 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4579,6 +4579,13 @@ remoteDispatchDomainGetJobStats(virNetServerPtr server ATTRIBUTE_UNUSED, + &nparams, args->flags) < 0) + goto cleanup; + ++ if (nparams > REMOTE_DOMAIN_JOB_STATS_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many job stats '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_JOB_STATS_MAX); ++ goto cleanup; ++ } ++ + if (remoteSerializeTypedParameters(params, nparams, + &ret->params.params_val, + &ret->params.params_len, +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 30f8f90..33b2b0f 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -5998,6 +5998,14 @@ remoteDomainGetJobStats(virDomainPtr domain, + (xdrproc_t) xdr_remote_domain_get_job_stats_ret, (char *) &ret) == -1) + goto done; + ++ if (ret.params.params_len > REMOTE_DOMAIN_JOB_STATS_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many job stats '%d' for limit '%d'"), ++ ret.params.params_len, ++ REMOTE_DOMAIN_JOB_STATS_MAX); ++ goto cleanup; ++ } ++ + *type = ret.type; + + if (remoteDeserializeTypedParameters(ret.params.params_val, +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 4262c34..eff7e1c 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -237,6 +237,9 @@ const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64; + /* Upper limit on migrate parameters */ + const REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX = 64; + ++/* Upper limit on number of job stats */ ++const REMOTE_DOMAIN_JOB_STATS_MAX = 16; ++ + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ + typedef opaque remote_uuid[VIR_UUID_BUFLEN]; + +@@ -2196,7 +2199,7 @@ struct remote_domain_get_job_stats_args { + + struct remote_domain_get_job_stats_ret { + int type; +- remote_typed_param params<>; ++ remote_typed_param params; + }; + + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virDomainMigrate-Params-RPC-calls-CVE-2013-4292.patch b/SOURCES/libvirt-Add-bounds-checking-on-virDomainMigrate-Params-RPC-calls-CVE-2013-4292.patch new file mode 100644 index 0000000..53d6543 --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virDomainMigrate-Params-RPC-calls-CVE-2013-4292.patch @@ -0,0 +1,272 @@ +From b88f552daa9be63938e79092f078ce06da185cb6 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:03 +0100 +Subject: [PATCH] Add bounds checking on virDomainMigrate*Params RPC calls + (CVE-2013-4292) + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The parameters for the virDomainMigrate*Params RPC calls were +not bounds checks, meaning a malicious client can cause libvirtd +to consume arbitrary memory + +This issue was introduced in the 1.1.0 release of libvirt + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit fd6f6a48619eb221afeb1c5965537534cd54e01d) +--- + daemon/remote.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + src/remote/remote_driver.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + src/remote/remote_protocol.x | 15 +++++++++------ + 3 files changed, 93 insertions(+), 6 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index 03d5557..a11ba94 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4620,6 +4620,13 @@ remoteDispatchDomainMigrateBegin3Params( + goto cleanup; + } + ++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + +@@ -4671,6 +4678,13 @@ remoteDispatchDomainMigratePrepare3Params( + goto cleanup; + } + ++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (!(params = remoteDeserializeTypedParameters(args->params.params_val, + args->params.params_len, + 0, &nparams))) +@@ -4726,6 +4740,13 @@ remoteDispatchDomainMigratePrepareTunnel3Params( + goto cleanup; + } + ++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (!(params = remoteDeserializeTypedParameters(args->params.params_val, + args->params.params_len, + 0, &nparams))) +@@ -4790,6 +4811,13 @@ remoteDispatchDomainMigratePerform3Params( + goto cleanup; + } + ++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + +@@ -4845,6 +4873,13 @@ remoteDispatchDomainMigrateFinish3Params( + goto cleanup; + } + ++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (!(params = remoteDeserializeTypedParameters(args->params.params_val, + args->params.params_len, + 0, &nparams))) +@@ -4897,6 +4932,13 @@ remoteDispatchDomainMigrateConfirm3Params( + goto cleanup; + } + ++ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ args->params.params_len, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 71d0034..30f8f90 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -6037,6 +6037,13 @@ remoteDomainMigrateBegin3Params(virDomainPtr domain, + make_nonnull_domain(&args.dom, domain); + args.flags = flags; + ++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (remoteSerializeTypedParameters(params, nparams, + &args.params.params_val, + &args.params.params_len) < 0) { +@@ -6096,6 +6103,13 @@ remoteDomainMigratePrepare3Params(virConnectPtr dconn, + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + ++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + if (remoteSerializeTypedParameters(params, nparams, + &args.params.params_val, + &args.params.params_len) < 0) { +@@ -6171,6 +6185,13 @@ remoteDomainMigratePrepareTunnel3Params(virConnectPtr dconn, + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + ++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + args.cookie_in.cookie_in_val = (char *)cookiein; + args.cookie_in.cookie_in_len = cookieinlen; + args.flags = flags; +@@ -6250,6 +6271,13 @@ remoteDomainMigratePerform3Params(virDomainPtr dom, + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + ++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + make_nonnull_domain(&args.dom, dom); + args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri; + args.cookie_in.cookie_in_val = (char *)cookiein; +@@ -6315,6 +6343,13 @@ remoteDomainMigrateFinish3Params(virConnectPtr dconn, + memset(&args, 0, sizeof(args)); + memset(&ret, 0, sizeof(ret)); + ++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + args.cookie_in.cookie_in_val = (char *)cookiein; + args.cookie_in.cookie_in_len = cookieinlen; + args.flags = flags; +@@ -6380,6 +6415,13 @@ remoteDomainMigrateConfirm3Params(virDomainPtr domain, + + memset(&args, 0, sizeof(args)); + ++ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many migration parameters '%d' for limit '%d'"), ++ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX); ++ goto cleanup; ++ } ++ + make_nonnull_domain(&args.dom, domain); + args.cookie_in.cookie_in_len = cookieinlen; + args.cookie_in.cookie_in_val = (char *) cookiein; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 7cfebdf..4262c34 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -234,6 +234,9 @@ const REMOTE_DOMAIN_DISK_ERRORS_MAX = 256; + */ + const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64; + ++/* Upper limit on migrate parameters */ ++const REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX = 64; ++ + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ + typedef opaque remote_uuid[VIR_UUID_BUFLEN]; + +@@ -2770,7 +2773,7 @@ struct remote_domain_fstrim_args { + + struct remote_domain_migrate_begin3_params_args { + remote_nonnull_domain dom; +- remote_typed_param params<>; ++ remote_typed_param params; + unsigned int flags; + }; + +@@ -2780,7 +2783,7 @@ struct remote_domain_migrate_begin3_params_ret { + }; + + struct remote_domain_migrate_prepare3_params_args { +- remote_typed_param params<>; ++ remote_typed_param params; + opaque cookie_in; + unsigned int flags; + }; +@@ -2791,7 +2794,7 @@ struct remote_domain_migrate_prepare3_params_ret { + }; + + struct remote_domain_migrate_prepare_tunnel3_params_args { +- remote_typed_param params<>; ++ remote_typed_param params; + opaque cookie_in; + unsigned int flags; + }; +@@ -2803,7 +2806,7 @@ struct remote_domain_migrate_prepare_tunnel3_params_ret { + struct remote_domain_migrate_perform3_params_args { + remote_nonnull_domain dom; + remote_string dconnuri; +- remote_typed_param params<>; ++ remote_typed_param params; + opaque cookie_in; + unsigned int flags; + }; +@@ -2813,7 +2816,7 @@ struct remote_domain_migrate_perform3_params_ret { + }; + + struct remote_domain_migrate_finish3_params_args { +- remote_typed_param params<>; ++ remote_typed_param params; + opaque cookie_in; + unsigned int flags; + int cancelled; +@@ -2826,7 +2829,7 @@ struct remote_domain_migrate_finish3_params_ret { + + struct remote_domain_migrate_confirm3_params_args { + remote_nonnull_domain dom; +- remote_typed_param params<>; ++ remote_typed_param params; + opaque cookie_in; + unsigned int flags; + int cancelled; +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-bounds-checking-on-virStoragePoolListAllVolumes-RPC-call.patch b/SOURCES/libvirt-Add-bounds-checking-on-virStoragePoolListAllVolumes-RPC-call.patch new file mode 100644 index 0000000..226f50c --- /dev/null +++ b/SOURCES/libvirt-Add-bounds-checking-on-virStoragePoolListAllVolumes-RPC-call.patch @@ -0,0 +1,94 @@ +From 6a7837f5eaf8dd9c6cf0b4319a0ae0ee747d3227 Mon Sep 17 00:00:00 2001 +Message-Id: <6a7837f5eaf8dd9c6cf0b4319a0ae0ee747d3227.1377873640.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Fri, 30 Aug 2013 11:16:08 +0100 +Subject: [PATCH] Add bounds checking on virStoragePoolListAllVolumes RPC call + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1002667 + +The return values for the virStoragePoolListAllVolumes call were not +bounds checked. This is a robustness issue for clients if +something where to cause corruption of the RPC stream data. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 046acaf37bc95d895f0a7d04a3a06ac992701711) +--- + daemon/remote.c | 7 +++++++ + src/remote/remote_driver.c | 7 +++++++ + src/remote/remote_protocol.x | 8 ++++---- + 3 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/daemon/remote.c b/daemon/remote.c +index 42c1c47..512170b 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -4136,6 +4136,13 @@ remoteDispatchStoragePoolListAllVolumes(virNetServerPtr server ATTRIBUTE_UNUSED, + args->flags)) < 0) + goto cleanup; + ++ if (nvols > REMOTE_STORAGE_VOL_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many storage volumes '%d' for limit '%d'"), ++ nvols, REMOTE_STORAGE_VOL_LIST_MAX); ++ goto cleanup; ++ } ++ + if (vols && nvols) { + if (VIR_ALLOC_N(ret->vols.vols_val, nvols) < 0) + goto cleanup; +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 622647b..542cb39 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -3343,6 +3343,13 @@ remoteStoragePoolListAllVolumes(virStoragePoolPtr pool, + (char *) &ret) == -1) + goto done; + ++ if (ret.vols.vols_len > REMOTE_STORAGE_VOL_LIST_MAX) { ++ virReportError(VIR_ERR_RPC, ++ _("Too many storage volumes '%d' for limit '%d'"), ++ ret.vols.vols_len, REMOTE_STORAGE_VOL_LIST_MAX); ++ goto cleanup; ++ } ++ + if (vols) { + if (VIR_ALLOC_N(tmp_vols, ret.vols.vols_len + 1) < 0) + goto cleanup; +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index 6e996b4..2034aa1 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -100,8 +100,8 @@ const REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX = 16384; + /* Upper limit on lists of storage pools. */ + const REMOTE_STORAGE_POOL_LIST_MAX = 4096; + +-/* Upper limit on lists of storage vol names. */ +-const REMOTE_STORAGE_VOL_NAME_LIST_MAX = 16384; ++/* Upper limit on lists of storage vols. */ ++const REMOTE_STORAGE_VOL_LIST_MAX = 16384; + + /* Upper limit on lists of node device names. */ + const REMOTE_NODE_DEVICE_NAME_LIST_MAX = 16384; +@@ -1746,7 +1746,7 @@ struct remote_storage_pool_list_volumes_args { + }; + + struct remote_storage_pool_list_volumes_ret { +- remote_nonnull_string names; /* insert@1 */ ++ remote_nonnull_string names; /* insert@1 */ + }; + + +@@ -2681,7 +2681,7 @@ struct remote_storage_pool_list_all_volumes_args { + }; + + struct remote_storage_pool_list_all_volumes_ret { +- remote_nonnull_storage_vol vols<>; ++ remote_nonnull_storage_vol vols; + unsigned int ret; + }; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-documentation-for-access-control-system.patch b/SOURCES/libvirt-Add-documentation-for-access-control-system.patch new file mode 100644 index 0000000..9b97925 --- /dev/null +++ b/SOURCES/libvirt-Add-documentation-for-access-control-system.patch @@ -0,0 +1,828 @@ +From bdb62336234cc454d7c5b1e539ad764984c946e2 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 11:38:28 +0100 +Subject: [PATCH] Add documentation for access control system + +For https://bugzilla.redhat.com/show_bug.cgi?id=700443 + +This adds two new pages to the website, acl.html describing +the general access control framework and permissions models, +and aclpolkit.html describing the use of polkit as an +access control driver. + +page.xsl is modified to support a new syntax + +
+ +which will cause the XSL transform to replace that
+with the contents of 'somefile.htmlinc'. We use this in +the acl.html.in file, to pull the table of permissions +for each libvirt object. This table is autogenerated +from the enums in src/access/viraccessperms.h by the +genaclperms.pl script. + +newapi.xsl is modified so that the list of permissions +checks shown against each API will link to the description +of the permissions in acl.html + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit da13f2c70c06c38c4f8feba1a5725652d2f1efc7) +--- + .gitignore | 1 + + docs/Makefile.am | 12 +- + docs/acl.html.in | 100 ++++++++++++ + docs/aclpolkit.html.in | 410 +++++++++++++++++++++++++++++++++++++++++++++++++ + docs/auth.html.in | 6 +- + docs/genaclperms.pl | 124 +++++++++++++++ + docs/newapi.xsl | 4 +- + docs/page.xsl | 11 ++ + docs/sitemap.html.in | 10 ++ + src/Makefile.am | 2 +- + 10 files changed, 674 insertions(+), 6 deletions(-) + create mode 100644 docs/acl.html.in + create mode 100644 docs/aclpolkit.html.in + create mode 100755 docs/genaclperms.pl + +diff --git a/docs/Makefile.am b/docs/Makefile.am +index aabee44..0b0d2d4 100644 +--- a/docs/Makefile.am ++++ b/docs/Makefile.am +@@ -128,7 +128,7 @@ fig = \ + migration-unmanaged-direct.fig + + EXTRA_DIST= \ +- apibuild.py \ ++ apibuild.py genaclperms.pl \ + site.xsl newapi.xsl news.xsl page.xsl \ + hacking1.xsl hacking2.xsl wrapstring.xsl \ + $(dot_html) $(dot_html_in) $(gif) $(apihtml) $(apipng) \ +@@ -139,6 +139,16 @@ EXTRA_DIST= \ + sitemap.html.in \ + todo.pl hvsupport.pl todo.cfg-example + ++BUILT_SOURCES += aclperms.htmlinc ++ ++CLEANFILES = $(srcdir)/aclperms.htmlinc ++ ++acl.html:: $(srcdir)/aclperms.htmlinc ++ ++$(srcdir)/aclperms.htmlinc: $(top_srcdir)/src/access/viraccessperm.h \ ++ $(srcdir)/genaclperms.pl Makefile.am ++ $(PERL) $(srcdir)/genaclperms.pl $< > $@ ++ + MAINTAINERCLEANFILES = \ + $(addprefix $(srcdir)/,$(dot_html)) \ + $(addprefix $(srcdir)/,$(apihtml)) \ +diff --git a/docs/acl.html.in b/docs/acl.html.in +new file mode 100644 +index 0000000..2d228e2 +--- /dev/null ++++ b/docs/acl.html.in +@@ -0,0 +1,100 @@ ++ ++ ++ ++ ++

Client access control

++

++ Libvirt's client access control framework allows administrators ++ to setup fine grained permission rules across client users, ++ managed objects and API operations. This allows client connections ++ to be locked down to a minimal set of privileges. ++

++ ++
    ++ ++

    Access control introduction

    ++ ++

    ++ In a default configuration, the libvirtd daemon has three levels ++ of access control. All connections start off in an unauthenticated ++ state, where the only API operations allowed are those required ++ to complete authentication. After successful authentication, a ++ connection either has full, unrestricted access to all libvirt ++ API calls, or is locked down to only "read only" operations, ++ according to what socket a client connection originated on. ++

    ++ ++

    ++ The access control framework allows authenticated connections to ++ have fine grained permission rules to be defined by the administrator. ++ Every API call in libvirt has a set of permissions that will ++ be validated against the object being used. For example, the ++ virDomainSetSchedulerParametersFlags method will ++ check whether the client user has the write ++ permission on the domain object instance passed ++ in as a parameter. Further permissions will also be checked ++ if certain flags are set in the API call. In addition to ++ checks on the object passed in to an API call, some methods ++ will filter their results. For example the virConnectListAllDomains ++ method will check the search_domains on the connect ++ object, but will also filter the returned domain ++ objects to only those on which the client user has the ++ getattr permission. ++

    ++ ++

    Access control drivers

    ++ ++

    ++ The access control framework is designed as a pluggable ++ system to enable future integration with arbitrary access ++ control technologies. By default, the none ++ driver is used, which does no access control checks at ++ all. At this time, libvirt ships with support for using ++ polkit as a real access ++ control driver. To learn how to use the polkit access ++ driver consult the configuration ++ docs. ++

    ++ ++

    ++ The access driver is configured in the libvirtd.conf ++ configuration file, using the access_drivers ++ parameter. This parameter accepts an array of access control ++ driver names. If more than one access driver is requested, ++ then all must succeed in order for access to be granted. ++ To enable 'polkit' as the driver: ++

    ++ ++
    ++# augtool -s set '/files/etc/libvirt/libvirtd.conf/access_drivers[1]' polkit
    ++    
    ++ ++

    ++ And to reset back to the default (no-op) driver ++

    ++ ++ ++
    ++# augtool -s rm /files/etc/libvirt/libvirtd.conf/access_drivers
    ++    
    ++ ++

    ++ Note: changes to libvirtd.conf require that ++ the libvirtd daemon be restarted. ++

    ++ ++

    Objects and permissions

    ++ ++

    ++ Libvirt applies access control to all the main object ++ types in its API. Each object type, in turn, has a set ++ of permissions defined. To determine what permissions ++ are checked for specific API call, consult the ++ API reference manual ++ documentation for the API in question. ++

    ++ ++
    ++ ++ ++ +diff --git a/docs/aclpolkit.html.in b/docs/aclpolkit.html.in +new file mode 100644 +index 0000000..3b0d81a +--- /dev/null ++++ b/docs/aclpolkit.html.in +@@ -0,0 +1,410 @@ ++ ++ ++ ++ ++

    Polkit access control

    ++ ++

    ++ Libvirt's client access control framework allows ++ administrators to setup fine grained permission rules across client users, ++ managed objects and API operations. This allows client connections ++ to be locked down to a minimal set of privileges. The polkit driver ++ provides a simple implementation of the access control framework. ++

    ++ ++
      ++ ++

      Introduction

      ++ ++

      ++ A default install of libvirt will typically use ++ polkit ++ to authenticate the initial user connection to libvirtd. This is a ++ very coarse grained check though, either allowing full read-write ++ access to all APIs, or just read-only access. The polkit access ++ control driver in libvirt builds on this capability to allow for ++ fine grained control over the operations a user may perform on an ++ object. ++

      ++ ++

      Permission names

      ++ ++

      ++ The libvirt object names and permission names ++ are mapped onto polkit action names using the simple pattern: ++

      ++ ++
      org.libvirt.api.$object.$permission
      ++
      ++ ++

      ++ The only caveat is that any underscore characters in the ++ object or permission names are converted to hyphens. So, ++ for example, the search_storage_vols permission ++ on the storage_pool object maps to the polkit ++ action: ++

      ++
      org.libvirt.api.storage-pool.search-storage-vols
      ++
      ++ ++

      ++ The default policy for any permission which corresponds to ++ a "read only" operation, is to allow access. All other ++ permissions default to deny access. ++

      ++ ++

      Object identity attributes

      ++ ++

      ++ To allow polkit authorization rules to be written to match ++ against individual object instances, libvirt provides a number ++ of authorization detail attributes when performing a permission ++ check. The set of attributes varies according to the type ++ of object being checked ++

      ++ ++

      virConnectPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      ++ ++

      virDomainPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      domain_nameName of the domain, unique to the local host
      domain_uuidUUID of the domain, globally unique
      ++ ++

      virInterfacePtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      interface_nameName of the network interface, unique to the local host
      interface_macMAC address of the network interface, not unique
      ++ ++

      virNetworkPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      network_nameName of the network, unique to the local host
      network_uuidUUID of the network, globally unique
      ++ ++

      virNodeDevicePtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      node_device_nameName of the node device, unique to the local host
      ++ ++

      virNWFilterPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      nwfilter_nameName of the network filter, unique to the local host
      nwfilter_uuidUUID of the network filter, globally unique
      ++ ++

      virSecretPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      secret_uuidUUID of the secret, globally unique
      secret_usage_volumeName of the associated volume, if any
      secret_usage_cephName of the associated Ceph server, if any
      secret_usage_targetName of the associated iSCSI target, if any
      ++ ++

      virStoragePoolPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      pool_nameName of the storage pool, unique to the local host
      pool_uuidUUID of the storage pool, globally unique
      ++ ++

      virStorageVolPtr

      ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      AttributeDescription
      connect_driverName of the libvirt connection driver
      pool_nameName of the storage pool, unique to the local host
      pool_uuidUUID of the storage pool, globally unique
      vol_nameName of the storage volume, unique to the pool
      vol_keyKey of the storage volume, globally unique
      ++ ++ ++

      User identity attributes

      ++ ++

      ++ At this point in time, the only attribute provided by ++ libvirt to identify the user invoking the operation ++ is the PID of the client program. This means that the ++ polkit access control driver is only useful if connections ++ to libvirt are restricted to its UNIX domain socket. If ++ connections are being made to a TCP socket, no identifying ++ information is available and access will be denied. ++ Also note that if the client is connecting via an SSH ++ tunnel, it is the local SSH user that will be identified. ++ In future versions, it is expected that more information ++ about the client user will be provided, including the ++ SASL / Kerberos username and/or x509 distinguished ++ name obtained from the authentication provider in use. ++

      ++ ++ ++

      Writing acces control policies

      ++ ++

      ++ If using versions of polkit prior to 0.106 then it is only ++ possible to validate (user, permission) pairs via the .pkla ++ files. Fully validation of the (user, permission, object) triple ++ requires the new JavaScript .rules support that ++ was introduced in version 0.106. The latter is what will be ++ described here. ++

      ++ ++

      ++ Libvirt does not ship any rules files by default. It merely ++ provides a definition of the default behaviour for each ++ action (permission). As noted earlier, permissions which ++ correspond to read-only operations in libvirt will be allowed ++ to all users by default; everything else is denied by default. ++ Defining custom rules requires creation of a file in the ++ /etc/polkit-1/rules.d directory with a name ++ chosen by the administrator (100-libvirt-acl.rules ++ would be a reasonable choice). See the polkit(8) ++ manual page for a description of how to write these files ++ in general. The key idea is to create a file containing ++ something like ++

      ++ ++
      ++      polkit.addRule(function(action, subject) {
      ++        ....logic to check 'action' and 'subject'...
      ++      });
      ++    
      ++ ++

      ++ In this code snippet above, the action object ++ instance will represent the libvirt permission being checked ++ along with identifying attributes for the object it is being ++ applied to. The subject meanwhile will identify ++ the libvirt client app (with the caveat above about it only ++ dealing with local clients connected via the UNIX socket). ++ On the action object, the permission name is ++ accessible via the id attribute, while the ++ object identifying attributes are exposed via a set of ++ attributes with the naming convention _detail_[attrname]. ++ For example, the 'domain_name' attribute would be exposed via ++ a property _detail_domain_name. ++

      ++ ++

      Example: restricting ability to connect to drivers

      ++ ++

      ++ Consider a local user berrange ++ who has been granted permission to connect to libvirt in ++ full read-write mode. The goal is to only allow them to ++ use the QEMU driver and not the Xen or LXC ++ drivers which are also available in libvirtd. ++ To achieve this we need to write a rule which checks ++ whether the _detail_connect_driver attribute ++ is QEMU, and match on an action ++ name of org.libvirt.api.connect.getattr. Using ++ the javascript rules format, this ends up written as ++

      ++ ++
      ++polkit.addRule(function(action, subject) {
      ++    if (action.id == "org.libvirt.api.connect.getattr" &&
      ++        subject.user == "berrange") {
      ++          if (action._detail_connect_driver == 'QEMU') {
      ++            return polkit.Result.YES;
      ++          } else {
      ++            return polkit.Result.NO;
      ++          }
      ++    }
      ++});
      ++    
      ++ ++

      Example: restricting access to a single domain

      ++ ++

      ++ Consider a local user berrange ++ who has been granted permission to connect to libvirt in ++ full read-write mode. The goal is to only allow them to ++ see the domain called demo on the LXC driver. ++ To achieve this we need to write a rule which checks ++ whether the _detail_connect_driver attribute ++ is LXC and the _detail_domain_name ++ attribute is demo, and match on a action ++ name of org.libvirt.api.domain.getattr. Using ++ the javascript rules format, this ends up written as ++

      ++ ++
      ++polkit.addRule(function(action, subject) {
      ++    if (action.id == "org.libvirt.api.domain.getattr" &&
      ++        subject.user == "berrange") {
      ++          if (action._detail_connect_driver == 'LXC' &&
      ++              action._detail_domain_name == 'busy') {
      ++            return polkit.Result.YES;
      ++          } else {
      ++            return polkit.Result.NO;
      ++          }
      ++    }
      ++});
      ++    
      ++ ++ +diff --git a/docs/auth.html.in b/docs/auth.html.in +index e5703c7..37f2978 100644 +--- a/docs/auth.html.in ++++ b/docs/auth.html.in +@@ -2,12 +2,14 @@ + + + +-

      Authentication & access control

      ++

      Connection authentication

      +

      + When connecting to libvirt, some connections may require client + authentication before allowing use of the APIs. The set of possible + authentication mechanisms is administrator controlled, independent +- of applications using libvirt. ++ of applications using libvirt. Once authenticated, libvirt can apply ++ fine grained access control to the operations ++ performed by a client. +

      + +
        +diff --git a/docs/genaclperms.pl b/docs/genaclperms.pl +new file mode 100755 +index 0000000..244a68e +--- /dev/null ++++ b/docs/genaclperms.pl +@@ -0,0 +1,124 @@ ++#!/usr/bin/perl ++# ++# Copyright (C) 2013 Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2.1 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library. If not, see ++# . ++# ++ ++use strict; ++use warnings; ++ ++my @objects = ( ++ "CONNECT", "DOMAIN", "INTERFACE", ++ "NETWORK","NODE_DEVICE", "NWFILTER", ++ "SECRET", "STORAGE_POOL", "STORAGE_VOL", ++ ); ++ ++my %class; ++ ++foreach my $object (@objects) { ++ my $class = lc $object; ++ ++ $class =~ s/(^\w|_\w)/uc $1/eg; ++ $class =~ s/_//g; ++ $class =~ s/Nwfilter/NWFilter/; ++ $class = "vir" . $class . "Ptr"; ++ ++ $class{$object} = $class; ++} ++ ++my $objects = join ("|", @objects); ++ ++my %opts; ++my $in_opts = 0; ++ ++my %perms; ++ ++while (<>) { ++ if ($in_opts) { ++ if (m,\*/,) { ++ $in_opts = 0; ++ } elsif (/\*\s*\@(\w+):\s*(.*?)\s*$/) { ++ $opts{$1} = $2; ++ } ++ } elsif (m,/\*\*,) { ++ $in_opts = 1; ++ } elsif (/VIR_ACCESS_PERM_($objects)_((?:\w|_)+),/) { ++ my $object = $1; ++ my $perm = lc $2; ++ next if $perm eq "last"; ++ ++ $perm =~ s/_/-/g; ++ ++ $perms{$object} = {} unless exists $perms{$object}; ++ $perms{$object}->{$perm} = { ++ desc => $opts{desc}, ++ message => $opts{message}, ++ anonymous => $opts{anonymous} ++ }; ++ %opts = (); ++ } ++} ++ ++print < ++ ++ ++ ++EOF ++ ++foreach my $object (sort { $a cmp $b } keys %perms) { ++ my $class = $class{$object}; ++ my $olink = lc "object_" . $object; ++ print <$class ++ ++ ++ ++ ++ ++ ++ ++ ++EOF ++ ++ foreach my $perm (sort { $a cmp $b } keys %{$perms{$object}}) { ++ my $description = $perms{$object}->{$perm}->{desc}; ++ ++ die "missing description for $object.$perm" unless ++ defined $description; ++ ++ my $plink = lc "perm_" . $object . "_" . $perm; ++ $plink =~ s/-/_/g; ++ ++ print < ++ ++ ++ ++EOF ++ ++ } ++ ++ print < ++
        PermissionDescription
        $perm$description
        ++EOF ++} ++ ++print < ++ ++EOF +diff --git a/docs/newapi.xsl b/docs/newapi.xsl +index 58f12eb..606d244 100644 +--- a/docs/newapi.xsl ++++ b/docs/newapi.xsl +@@ -71,8 +71,8 @@ + + + +- +- ++ ++ + + + +diff --git a/docs/page.xsl b/docs/page.xsl +index 7da34ff..a2da854 100644 +--- a/docs/page.xsl ++++ b/docs/page.xsl +@@ -26,6 +26,10 @@ + + + ++ ++ ++ ++ + + +@@ -174,4 +178,11 @@ + + + ++ ++ ++ ++ ++ ++ ++ + +diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in +index fd10caf..a8d2177 100644 +--- a/docs/sitemap.html.in ++++ b/docs/sitemap.html.in +@@ -69,6 +69,16 @@ + Configure authentication for the libvirt daemon + +
      • ++ Access control ++ Configure access control libvirt APIs ++ ++
      • ++
      • + Migration + Migrating guests between machines +
      • +diff --git a/src/Makefile.am b/src/Makefile.am +index 8c6f068..b049895 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -1654,7 +1654,7 @@ test_libvirt_lockd.aug: locking/test_libvirt_lockd.aug.in \ + + test_virtlockd.aug: locking/test_virtlockd.aug.in \ + locking/virtlockd.conf $(AUG_GENTEST) +- $(AM_V_GEN)$(AUG_GENTEST) locking/virtlockd.conf $< $@ ++ $(AM_V_GEN)$(AUG_GENTEST) $(srcdir)/locking/virtlockd.conf $< $@ + + check-augeas-lockd: test_libvirt_lockd.aug + $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \ +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-helpers-for-getting-env-vars-in-a-setuid-environment.patch b/SOURCES/libvirt-Add-helpers-for-getting-env-vars-in-a-setuid-environment.patch new file mode 100644 index 0000000..b36bf12 --- /dev/null +++ b/SOURCES/libvirt-Add-helpers-for-getting-env-vars-in-a-setuid-environment.patch @@ -0,0 +1,111 @@ +From ffe48a81783cc07e2f12e158e5b3985d1f313c9b Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Wed, 30 Oct 2013 17:01:41 +0000 +Subject: [PATCH] Add helpers for getting env vars in a setuid environment + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1015247 + +Care must be taken accessing env variables when running +setuid. Introduce a virGetEnvAllowSUID for env vars which +are safe to use in a setuid environment, and another +virGetEnvBlockSUID for vars which are not safe. Also add +a virIsSUID helper method for any other non-env var code +to use. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit ae53e5d10e434e07079d7e3ba11ec654ba6a256e) +Signed-off-by: Jiri Denemark +--- + bootstrap.conf | 1 + + src/libvirt_private.syms | 3 +++ + src/util/virutil.c | 39 +++++++++++++++++++++++++++++++++++++++ + src/util/virutil.h | 4 ++++ + 4 files changed, 47 insertions(+) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index f96f126..374a332 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -2046,6 +2046,8 @@ virFindFCHostCapableVport; + virFormatIntDecimal; + virGetDeviceID; + virGetDeviceUnprivSGIO; ++virGetEnvAllowSUID; ++virGetEnvBlockSUID; + virGetFCHostNameByWWN; + virGetGroupID; + virGetGroupList; +@@ -2064,6 +2066,7 @@ virIndexToDiskName; + virIsCapableFCHost; + virIsCapableVport; + virIsDevMapperDevice; ++virIsSUID; + virManageVport; + virParseNumber; + virParseOwnershipIds; +diff --git a/src/util/virutil.c b/src/util/virutil.c +index 3abcd53..a41117e 100644 +--- a/src/util/virutil.c ++++ b/src/util/virutil.c +@@ -2096,3 +2096,42 @@ cleanup: + + return rc; + } ++ ++ ++/** ++ * virGetEnvBlockSUID: ++ * @name: the environment variable name ++ * ++ * Obtain an environment variable which is unsafe to ++ * use when running setuid. If running setuid, a NULL ++ * value will be returned ++ */ ++const char *virGetEnvBlockSUID(const char *name) ++{ ++ return secure_getenv(name); ++} ++ ++ ++/** ++ * virGetEnvBlockSUID: ++ * @name: the environment variable name ++ * ++ * Obtain an environment variable which is safe to ++ * use when running setuid. The value will be returned ++ * even when running setuid ++ */ ++const char *virGetEnvAllowSUID(const char *name) ++{ ++ return getenv(name); ++} ++ ++ ++/** ++ * virIsSUID: ++ * Return a true value if running setuid. Does not ++ * check for elevated capabilities bits. ++ */ ++bool virIsSUID(void) ++{ ++ return getuid() != geteuid(); ++} +diff --git a/src/util/virutil.h b/src/util/virutil.h +index 4b06992..8739e4e 100644 +--- a/src/util/virutil.h ++++ b/src/util/virutil.h +@@ -172,4 +172,8 @@ int virCompareLimitUlong(unsigned long long a, unsigned long b); + + int virParseOwnershipIds(const char *label, uid_t *uidPtr, gid_t *gidPtr); + ++const char *virGetEnvBlockSUID(const char *name); ++const char *virGetEnvAllowSUID(const char *name); ++bool virIsSUID(void); ++ + #endif /* __VIR_UTIL_H__ */ +-- +1.8.4.2 + diff --git a/SOURCES/libvirt-Add-info-about-access-control-checks-into-API-reference.patch b/SOURCES/libvirt-Add-info-about-access-control-checks-into-API-reference.patch new file mode 100644 index 0000000..8711594 --- /dev/null +++ b/SOURCES/libvirt-Add-info-about-access-control-checks-into-API-reference.patch @@ -0,0 +1,313 @@ +From 87ab326e99c0c6b556bfff54a6e4e9bd09faa495 Mon Sep 17 00:00:00 2001 +Message-Id: <87ab326e99c0c6b556bfff54a6e4e9bd09faa495.1377873638.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 11:38:26 +0100 +Subject: [PATCH] Add info about access control checks into API reference + +For https://bugzilla.redhat.com/show_bug.cgi?id=700443 + +So that app developers / admins know what access control checks +are performed for each API, this patch extends the API docs +generator to include details of the ACLs for each. + +The gendispatch.pl script is extended so that it generates +a simple XML describing ACL rules, eg. + + + ... + + + + + + + + + + ... + + +The newapi.xsl template loads the XML files containing the ACL +rules and generates a short block of HTML for each API describing +the parameter checks and return value filters (if any). + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 664ab2801dfcb8e72fc4408cc50c279bf74e47a2) +--- + .gitignore | 3 +++ + docs/libvirt.css | 14 +++++++++++ + docs/newapi.xsl | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ + src/Makefile.am | 22 ++++++++++++++-- + src/rpc/gendispatch.pl | 59 ++++++++++++++++++++++++++++++++++++++++--- + 5 files changed, 160 insertions(+), 6 deletions(-) + +diff --git a/docs/libvirt.css b/docs/libvirt.css +index 8a00d12..ed67b2f 100644 +--- a/docs/libvirt.css ++++ b/docs/libvirt.css +@@ -477,3 +477,17 @@ dl.variablelist > dt { + dl.variablelist > dt:after { + content: ": "; + } ++ ++table.acl { ++ margin: 1em; ++ border-spacing: 0px; ++ border: 1px solid #ccc; ++} ++ ++table.acl tr, table.acl td { ++ padding: 0.3em; ++} ++ ++table.acl thead { ++ background: #ddd; ++} +diff --git a/docs/newapi.xsl b/docs/newapi.xsl +index d5b210e..58f12eb 100644 +--- a/docs/newapi.xsl ++++ b/docs/newapi.xsl +@@ -29,6 +29,69 @@ + html + ../ + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
        Access control parameter checks
        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
        ObjectPermissionCondition
        ++
        ++ ++
        Access control return value filters
        ++ ++ ++ ++ ++ ++ ++ ++ ++
        ObjectPermission
        ++
        ++
        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ - ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +@@ -553,6 +616,11 @@ + + + ++
        ++ ++ ++ ++
        +
        + + +diff --git a/src/Makefile.am b/src/Makefile.am +index 12ca204..8c6f068 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -826,6 +826,11 @@ ACCESS_DRIVER_SYM_FILES = \ + libvirt_access_qemu.syms \ + libvirt_access_lxc.syms + ++ACCESS_DRIVER_API_FILES = \ ++ libvirt_access.xml \ ++ libvirt_access_qemu.xml \ ++ libvirt_access_lxc.xml ++ + ACCESS_DRIVER_SOURCES = \ + access/viraccessperm.h access/viraccessperm.c \ + access/viraccessmanager.h access/viraccessmanager.c \ +@@ -1492,8 +1497,8 @@ EXTRA_DIST += $(ACCESS_DRIVER_POLKIT_SOURCES) + endif + + +-BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED) +-CLEANFILES += $(ACCESS_DRIVER_GENERATED) ++BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_API_FILES) ++CLEANFILES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_API_FILES) + + libvirt_access.syms: $(srcdir)/rpc/gendispatch.pl \ + $(REMOTE_PROTOCOL) Makefile.am +@@ -1508,6 +1513,19 @@ libvirt_access_lxc.syms: $(srcdir)/rpc/gendispatch.pl \ + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclsym \ + lxc LXC $(LXC_PROTOCOL) > $@ + ++libvirt_access.xml: $(srcdir)/rpc/gendispatch.pl \ ++ $(REMOTE_PROTOCOL) Makefile.am ++ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \ ++ remote REMOTE $(REMOTE_PROTOCOL) > $@ ++libvirt_access_qemu.xml: $(srcdir)/rpc/gendispatch.pl \ ++ $(QEMU_PROTOCOL) Makefile.am ++ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \ ++ qemu QEMU $(QEMU_PROTOCOL) > $@ ++libvirt_access_lxc.xml: $(srcdir)/rpc/gendispatch.pl \ ++ $(LXC_PROTOCOL) Makefile.am ++ $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \ ++ lxc LXC $(LXC_PROTOCOL) > $@ ++ + $(srcdir)/access/viraccessapicheck.h: $(srcdir)/rpc/gendispatch.pl \ + $(REMOTE_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclheader \ +diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl +index 8f41771..ac0c7ab 100755 +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -41,8 +41,8 @@ my $res = GetOptions("mode=s" => \$mode); + die "cannot parse command line options" unless $res; + + die "unknown mode '$mode', expecting 'client', 'server', " . +- "'aclheader', 'aclbody', 'aclsym' or 'debug'" +- unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|debug)$/; ++ "'aclheader', 'aclbody', 'aclsym', 'aclapi' or 'debug'" ++ unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|aclapi|debug)$/; + + my $structprefix = shift or die "missing struct prefix argument"; + my $procprefix = shift or die "missing procedure prefix argument"; +@@ -351,6 +351,13 @@ if ($mode eq "aclsym") { + # Automatically generated by gendispatch.pl. + # Do not edit this file. Any changes you make will be lost. + __EOF__ ++} elsif ($mode eq "aclapi") { ++ print <<__EOF__; ++ ++__EOF__ + } else { + print <<__EOF__; + /* Automatically generated by gendispatch.pl. +@@ -1641,7 +1648,8 @@ elsif ($mode eq "client") { + } + } elsif ($mode eq "aclheader" || + $mode eq "aclbody" || +- $mode eq "aclsym") { ++ $mode eq "aclsym" || ++ $mode eq "aclapi") { + my %generate = map { $_ => 1 } @autogen; + my @keys = keys %calls; + +@@ -1667,6 +1675,7 @@ elsif ($mode eq "client") { + foreach my $hdr (@headers) { + print "#include \"$hdr\"\n"; + } ++ print "\n"; + } elsif ($mode eq "aclbody") { + my $header = shift; + print "#include \n"; +@@ -1676,8 +1685,12 @@ elsif ($mode eq "client") { + print "#include \"virerror.h\"\n"; + print "\n"; + print "#define VIR_FROM_THIS VIR_FROM_ACCESS\n"; ++ print "\n"; ++ } elsif ($mode eq "aclapi") { ++ print "\n"; ++ } else { ++ print "\n"; + } +- print "\n"; + + foreach (@keys) { + my $call = $calls{$_}; +@@ -1699,6 +1712,8 @@ elsif ($mode eq "client") { + print $apiname . "CheckACL;\n"; + } + print $apiname . "EnsureACL;\n"; ++ } elsif ($mode eq "aclapi") { ++ &generate_aclapi($call); + } else { + &generate_acl($call, $call->{acl}, "Ensure"); + if (defined $call->{aclfilter}) { +@@ -1835,5 +1850,41 @@ elsif ($mode eq "client") { + print "}\n\n"; + } + } ++ ++ sub generate_aclapi { ++ my $call = shift; ++ ++ my $apiname = "vir" . $call->{ProcName}; ++ if ($structprefix eq "qemu") { ++ $apiname =~ s/virDomain/virDomainQemu/; ++ } elsif ($structprefix eq "lxc") { ++ $apiname =~ s/virDomain/virDomainLxc/; ++ } ++ ++ print " \n"; ++ ++ my $acl = $call->{acl}; ++ foreach (@{$acl}) { ++ my @bits = split /:/; ++ print " \n"; ++ } ++ ++ my $aclfilter = $call->{aclfilter}; ++ foreach (@{$aclfilter}) { ++ my @bits = split /:/; ++ print " \n"; ++ } ++ ++ print " \n"; ++ } ++ ++ } ++ ++ if ($mode eq "aclapi") { ++ print "\n"; + } + } +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-nat-element-to-forward-network-schemas.patch b/SOURCES/libvirt-Add-nat-element-to-forward-network-schemas.patch new file mode 100644 index 0000000..dab1983 --- /dev/null +++ b/SOURCES/libvirt-Add-nat-element-to-forward-network-schemas.patch @@ -0,0 +1,168 @@ +From 9e8eabdfdefe2d31282b7994d01c28dc8cd818e0 Mon Sep 17 00:00:00 2001 +Message-Id: <9e8eabdfdefe2d31282b7994d01c28dc8cd818e0.1378475168.git.jdenemar@redhat.com> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Thu, 5 Sep 2013 14:25:28 +0200 +Subject: [PATCH] Add '' element to '' network schemas + +Commits 905629f4 and 1716e7a6 have added support for specifying +an IPv4 range and a port range to be used by NAT: + + +
        + + + + +https://bugzilla.redhat.com/show_bug.cgi?id=1004364 +(cherry picked from commit 437b7944a81b648a15c657fef184f3bcd2427dac) + +Conflicts: + tests/networkxml2xmltest.c: + 4f595ba not backported (dns forwardPlainNames) + +A few spaces were needed in +networkxml2xmlout/nat-network-forward-nat-address.xml +because d8bd24a which removed them is not backported either. +--- + docs/schemas/network.rng | 26 +++++++++++++++++++++ + docs/schemas/networkcommon.rng | 7 ++++++ + .../nat-network-forward-nat-address.xml | 26 +++++++++++++++++++++ + .../nat-network-forward-nat-address.xml | 27 ++++++++++++++++++++++ + tests/networkxml2xmltest.c | 1 + + 5 files changed, 87 insertions(+) + create mode 100644 tests/networkxml2xmlin/nat-network-forward-nat-address.xml + create mode 100644 tests/networkxml2xmlout/nat-network-forward-nat-address.xml + +diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng +index ded8580..11adbac 100644 +--- a/docs/schemas/network.rng ++++ b/docs/schemas/network.rng +@@ -160,6 +160,32 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng +index e60f1fc..e26b7f3 100644 +--- a/docs/schemas/networkcommon.rng ++++ b/docs/schemas/networkcommon.rng +@@ -217,4 +217,11 @@ + + + ++ ++ ++ ++ 1 ++ 65535 ++ ++ + +diff --git a/tests/networkxml2xmlin/nat-network-forward-nat-address.xml b/tests/networkxml2xmlin/nat-network-forward-nat-address.xml +new file mode 100644 +index 0000000..403d058 +--- /dev/null ++++ b/tests/networkxml2xmlin/nat-network-forward-nat-address.xml +@@ -0,0 +1,26 @@ ++ ++ default ++ 81ff0d90-c91e-6742-64da-4a736edb9a9b ++ ++ ++ ++
        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/networkxml2xmlout/nat-network-forward-nat-address.xml b/tests/networkxml2xmlout/nat-network-forward-nat-address.xml +new file mode 100644 +index 0000000..796220d +--- /dev/null ++++ b/tests/networkxml2xmlout/nat-network-forward-nat-address.xml +@@ -0,0 +1,27 @@ ++ ++ default ++ 81ff0d90-c91e-6742-64da-4a736edb9a9b ++ ++ ++
        ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c +index 0dfed16..b48eed2 100644 +--- a/tests/networkxml2xmltest.c ++++ b/tests/networkxml2xmltest.c +@@ -104,6 +104,7 @@ mymain(void) + DO_TEST("netboot-proxy-network"); + DO_TEST("nat-network-dns-txt-record"); + DO_TEST("nat-network-dns-hosts"); ++ DO_TEST("nat-network-forward-nat-address"); + DO_TEST("8021Qbh-net"); + DO_TEST("direct-net"); + DO_TEST("host-bridge-net"); +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-stub-getegid-impl-for-platforms-lacking-it.patch b/SOURCES/libvirt-Add-stub-getegid-impl-for-platforms-lacking-it.patch new file mode 100644 index 0000000..089874f --- /dev/null +++ b/SOURCES/libvirt-Add-stub-getegid-impl-for-platforms-lacking-it.patch @@ -0,0 +1,40 @@ +From 0a0b9b0e2553d2bc26e88dc07859029124562ce2 Mon Sep 17 00:00:00 2001 +Message-Id: <0a0b9b0e2553d2bc26e88dc07859029124562ce2.1383321465.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Wed, 30 Oct 2013 17:01:55 +0000 +Subject: [PATCH] Add stub getegid impl for platforms lacking it + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1015247 + +We already have stubs for getuid, geteuid, getgid but +not for getegid. Something in gnulib already does a +check for it during configure, so we already have the +HAVE_GETEGID macro defined. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit c566fa1ad007a280bdf5132f7f91010459036ff6) +Signed-off-by: Jiri Denemark +--- + src/util/virutil.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/util/virutil.h b/src/util/virutil.h +index 8739e4e..2c8b0ec 100644 +--- a/src/util/virutil.h ++++ b/src/util/virutil.h +@@ -108,6 +108,10 @@ static inline int geteuid (void) { return 0; } + static inline int getgid (void) { return 0; } + # endif + ++# ifndef HAVE_GETEGID ++static inline int getegid (void) { return 0; } ++# endif ++ + char *virGetHostname(void); + + char *virGetUserDirectory(void); +-- +1.8.4.2 + diff --git a/SOURCES/libvirt-Add-support-for-systemd-cgroup-mount.patch b/SOURCES/libvirt-Add-support-for-systemd-cgroup-mount.patch new file mode 100644 index 0000000..7afeee7 --- /dev/null +++ b/SOURCES/libvirt-Add-support-for-systemd-cgroup-mount.patch @@ -0,0 +1,270 @@ +From d6a370721e1eb2bab9b5a7d66c6e4e935c69f30b Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Wed, 31 Jul 2013 19:48:18 +0100 +Subject: [PATCH] Add support for systemd cgroup mount + +https://bugzilla.redhat.com/show_bug.cgi?id=980929 + +Systemd uses a named cgroup mount for tracking processes. Add +it as another type of controller, albeit one which we have to +special case in a number of places. In particular we must +never create/delete directories there, nor add tasks. Essentially +the systemd mount is to be considered read-only for libvirt. + +With this change both the virCgroupDetectPlacement and +virCgroupCopyPlacement methods must be invoked. The copy +placement method will copy setup for resource controllers +only. The detect placement method will probe for any +named controllers, or resource controllers not already +setup. + +Signed-off-by: Daniel P. Berrange + +(cherry picked from commit aedd46e7e32956b4f360ba631b47064c2bafcbff) +--- + src/util/vircgroup.c | 68 +++++++++++++++++++++++++++++++++++++++------------ + src/util/vircgroup.h | 1 + + tests/vircgrouptest.c | 9 +++++++ + 3 files changed, 63 insertions(+), 15 deletions(-) + +diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c +index f9007e3..0e8bb79 100644 +--- a/src/util/vircgroup.c ++++ b/src/util/vircgroup.c +@@ -57,7 +57,8 @@ + + VIR_ENUM_IMPL(virCgroupController, VIR_CGROUP_CONTROLLER_LAST, + "cpu", "cpuacct", "cpuset", "memory", "devices", +- "freezer", "blkio", "net_cls", "perf_event"); ++ "freezer", "blkio", "net_cls", "perf_event", ++ "name=systemd"); + + typedef enum { + VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */ +@@ -117,6 +118,9 @@ virCgroupValidateMachineGroup(virCgroupPtr group, + for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) { + char *tmp; + ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) ++ continue; ++ + if (!group->controllers[i].placement) + continue; + +@@ -331,6 +335,9 @@ static int virCgroupCopyPlacement(virCgroupPtr group, + if (!group->controllers[i].mountPoint) + continue; + ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) ++ continue; ++ + if (path[0] == '/') { + if (VIR_STRDUP(group->controllers[i].placement, path) < 0) + return -1; +@@ -386,6 +393,8 @@ static int virCgroupDetectPlacement(virCgroupPtr group, + int ret = -1; + char *procfile; + ++ VIR_DEBUG("Detecting placement for pid %lld path %s", ++ (unsigned long long)pid, path); + if (pid == -1) { + if (VIR_STRDUP(procfile, "/proc/self/cgroup") < 0) + goto cleanup; +@@ -422,6 +431,7 @@ static int virCgroupDetectPlacement(virCgroupPtr group, + const char *typestr = virCgroupControllerTypeToString(i); + int typelen = strlen(typestr); + char *tmp = controllers; ++ + while (tmp) { + char *next = strchr(tmp, ','); + int len; +@@ -438,13 +448,20 @@ static int virCgroupDetectPlacement(virCgroupPtr group, + * selfpath=="/libvirt.service" + path="foo" -> "/libvirt.service/foo" + */ + if (typelen == len && STREQLEN(typestr, tmp, len) && +- group->controllers[i].mountPoint != NULL) { +- if (virAsprintf(&group->controllers[i].placement, +- "%s%s%s", selfpath, +- (STREQ(selfpath, "/") || +- STREQ(path, "") ? "" : "/"), +- path) < 0) +- goto cleanup; ++ group->controllers[i].mountPoint != NULL && ++ group->controllers[i].placement == NULL) { ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) { ++ if (VIR_STRDUP(group->controllers[i].placement, ++ selfpath) < 0) ++ goto cleanup; ++ } else { ++ if (virAsprintf(&group->controllers[i].placement, ++ "%s%s%s", selfpath, ++ (STREQ(selfpath, "/") || ++ STREQ(path, "") ? "" : "/"), ++ path) < 0) ++ goto cleanup; ++ } + } + + tmp = next; +@@ -535,13 +552,16 @@ static int virCgroupDetect(virCgroupPtr group, + return -1; + } + +- if (parent || path[0] == '/') { +- if (virCgroupCopyPlacement(group, path, parent) < 0) +- return -1; +- } else { +- if (virCgroupDetectPlacement(group, pid, path) < 0) +- return -1; +- } ++ /* In some cases we can copy part of the placement info ++ * based on the parent cgroup... ++ */ ++ if ((parent || path[0] == '/') && ++ virCgroupCopyPlacement(group, path, parent) < 0) ++ return -1; ++ ++ /* ... but use /proc/cgroups to fill in the rest */ ++ if (virCgroupDetectPlacement(group, pid, path) < 0) ++ return -1; + + /* Check that for every mounted controller, we found our placement */ + for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) { +@@ -833,6 +853,12 @@ static int virCgroupMakeGroup(virCgroupPtr parent, + for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) { + char *path = NULL; + ++ /* We must never mkdir() in systemd's hierarchy */ ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) { ++ VIR_DEBUG("Not creating systemd controller group"); ++ continue; ++ } ++ + /* Skip over controllers that aren't mounted */ + if (!group->controllers[i].mountPoint) { + VIR_DEBUG("Skipping unmounted controller %s", +@@ -1037,6 +1063,10 @@ int virCgroupRemove(virCgroupPtr group) + if (!group->controllers[i].mountPoint) + continue; + ++ /* We must never rmdir() in systemd's hierarchy */ ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) ++ continue; ++ + /* Don't delete the root group, if we accidentally + ended up in it for some reason */ + if (STREQ(group->controllers[i].placement, "/")) +@@ -1076,6 +1106,10 @@ int virCgroupAddTask(virCgroupPtr group, pid_t pid) + if (!group->controllers[i].mountPoint) + continue; + ++ /* We must never add tasks in systemd's hierarchy */ ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) ++ continue; ++ + if (virCgroupSetValueU64(group, i, "tasks", (unsigned long long)pid) < 0) + goto cleanup; + } +@@ -1177,6 +1211,10 @@ int virCgroupMoveTask(virCgroupPtr src_group, virCgroupPtr dest_group) + !dest_group->controllers[i].mountPoint) + continue; + ++ /* We must never move tasks in systemd's hierarchy */ ++ if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) ++ continue; ++ + /* New threads are created in the same group as their parent; + * but if a thread is created after we first read we aren't + * aware that it needs to move. Therefore, we must iterate +diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h +index 3aaf081..e579f41 100644 +--- a/src/util/vircgroup.h ++++ b/src/util/vircgroup.h +@@ -40,6 +40,7 @@ enum { + VIR_CGROUP_CONTROLLER_BLKIO, + VIR_CGROUP_CONTROLLER_NET_CLS, + VIR_CGROUP_CONTROLLER_PERF_EVENT, ++ VIR_CGROUP_CONTROLLER_SYSTEMD, + + VIR_CGROUP_CONTROLLER_LAST + }; +diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c +index 20ac494..4bdd4c9 100644 +--- a/tests/vircgrouptest.c ++++ b/tests/vircgrouptest.c +@@ -87,6 +87,7 @@ const char *mountsSmall[VIR_CGROUP_CONTROLLER_LAST] = { + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = NULL, + [VIR_CGROUP_CONTROLLER_BLKIO] = NULL, ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL, + }; + const char *mountsFull[VIR_CGROUP_CONTROLLER_LAST] = { + [VIR_CGROUP_CONTROLLER_CPU] = "/not/really/sys/fs/cgroup/cpu,cpuacct", +@@ -96,6 +97,7 @@ const char *mountsFull[VIR_CGROUP_CONTROLLER_LAST] = { + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/not/really/sys/fs/cgroup/freezer", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/not/really/sys/fs/cgroup/blkio", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/not/really/sys/fs/cgroup/systemd", + }; + + const char *links[VIR_CGROUP_CONTROLLER_LAST] = { +@@ -121,6 +123,7 @@ static int testCgroupNewForSelf(const void *args ATTRIBUTE_UNUSED) + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123", + }; + + if (virCgroupNewSelf(&cgroup) < 0) { +@@ -161,6 +164,7 @@ static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED) + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = NULL, + [VIR_CGROUP_CONTROLLER_BLKIO] = NULL, ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL, + }; + const char *placementFull[VIR_CGROUP_CONTROLLER_LAST] = { + [VIR_CGROUP_CONTROLLER_CPU] = "/virtualmachines.partition", +@@ -170,6 +174,7 @@ static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED) + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/virtualmachines.partition", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/virtualmachines.partition", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123", + }; + + if ((rv = virCgroupNewPartition("/virtualmachines", false, -1, &cgroup)) != -1) { +@@ -233,6 +238,7 @@ static int testCgroupNewForPartitionNested(const void *args ATTRIBUTE_UNUSED) + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/deployment.partition/production.partition", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/deployment.partition/production.partition", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123", + }; + + if ((rv = virCgroupNewPartition("/deployment/production", false, -1, &cgroup)) != -1) { +@@ -281,6 +287,7 @@ static int testCgroupNewForPartitionNestedDeep(const void *args ATTRIBUTE_UNUSED + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/user/berrange.user/production.partition", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/user/berrange.user/production.partition", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123", + }; + + if ((rv = virCgroupNewPartition("/user/berrange.user/production", false, -1, &cgroup)) != -1) { +@@ -336,6 +343,7 @@ static int testCgroupNewForPartitionDomain(const void *args ATTRIBUTE_UNUSED) + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/production.partition/foo.libvirt-lxc", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/production.partition/foo.libvirt-lxc", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123", + }; + + if ((rv = virCgroupNewPartition("/production", true, -1, &partitioncgroup)) != 0) { +@@ -372,6 +380,7 @@ static int testCgroupNewForPartitionDomainEscaped(const void *args ATTRIBUTE_UNU + [VIR_CGROUP_CONTROLLER_DEVICES] = NULL, + [VIR_CGROUP_CONTROLLER_FREEZER] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc", + [VIR_CGROUP_CONTROLLER_BLKIO] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc", ++ [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/user/berrange/123", + }; + + if ((rv = virCgroupNewPartition("/cgroup.evil", true, -1, &partitioncgroup1)) != 0) { +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-support-for-using-3-arg-pkcheck-syntax-for-process.patch b/SOURCES/libvirt-Add-support-for-using-3-arg-pkcheck-syntax-for-process.patch new file mode 100644 index 0000000..bd892c2 --- /dev/null +++ b/SOURCES/libvirt-Add-support-for-using-3-arg-pkcheck-syntax-for-process.patch @@ -0,0 +1,169 @@ +From 13572b2c50e079c5618870af7ae64bf3a73154d7 Mon Sep 17 00:00:00 2001 +Message-Id: <13572b2c50e079c5618870af7ae64bf3a73154d7.1379597659.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Wed, 28 Aug 2013 15:25:40 +0100 +Subject: [PATCH] Add support for using 3-arg pkcheck syntax for process + +CVE-2013-4311 + +With the existing pkcheck (pid, start time) tuple for identifying +the process, there is a race condition, where a process can make +a libvirt RPC call and in another thread exec a setuid application, +causing it to change to effective UID 0. This in turn causes polkit +to do its permission check based on the wrong UID. + +To address this, libvirt must get the UID the caller had at time +of connect() (from SO_PEERCRED) and pass a (pid, start time, uid) +triple to the pkcheck program. + +This fix requires that libvirt is re-built against a version of +polkit that has the fix for its CVE-2013-4288, so that libvirt +can see 'pkg-config --variable pkcheck_supports_uid polkit-gobject-1' + +Signed-off-by: Colin Walters +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 922b7fda77b094dbf022d625238262ea05335666) +--- + configure.ac | 8 ++++++++ + daemon/remote.c | 22 ++++++++++++++++++--- + libvirt.spec.in | 7 ++++--- + src/access/viraccessdriverpolkit.c | 40 +++++++++++++++++++++++++++++++++----- + 4 files changed, 66 insertions(+), 11 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 917db6a..7dd6ca3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1166,6 +1166,14 @@ if test "x$with_polkit" = "xyes" || test "x$with_polkit" = "xcheck"; then + AC_PATH_PROG([PKCHECK_PATH],[pkcheck], [], [/usr/sbin:$PATH]) + if test "x$PKCHECK_PATH" != "x" ; then + AC_DEFINE_UNQUOTED([PKCHECK_PATH],["$PKCHECK_PATH"],[Location of pkcheck program]) ++ AC_MSG_CHECKING([whether pkcheck supports uid value]) ++ pkcheck_supports_uid=`$PKG_CONFIG --variable pkcheck_supports_uid polkit-gobject-1` ++ if test "x$pkcheck_supports_uid" = "xtrue"; then ++ AC_MSG_RESULT([yes]) ++ AC_DEFINE_UNQUOTED([PKCHECK_SUPPORTS_UID], 1, [Pass uid to pkcheck]) ++ else ++ AC_MSG_RESULT([no]) ++ fi + AC_DEFINE_UNQUOTED([WITH_POLKIT], 1, + [use PolicyKit for UNIX socket access checks]) + AC_DEFINE_UNQUOTED([WITH_POLKIT1], 1, +diff --git a/daemon/remote.c b/daemon/remote.c +index 6ace7af..b5395dd 100644 +--- a/daemon/remote.c ++++ b/daemon/remote.c +@@ -2738,10 +2738,12 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED, + int status = -1; + char *ident = NULL; + bool authdismissed = 0; ++ bool supportsuid = false; + char *pkout = NULL; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + virCommandPtr cmd = NULL; ++ static bool polkitInsecureWarned; + + virMutexLock(&priv->lock); + action = virNetServerClientGetReadonly(client) ? +@@ -2763,14 +2765,28 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED, + goto authfail; + } + ++ if (timestamp == 0) { ++ VIR_WARN("Failing polkit auth due to missing client (pid=%lld) start time", ++ (long long)callerPid); ++ goto authfail; ++ } ++ + VIR_INFO("Checking PID %lld running as %d", + (long long) callerPid, callerUid); + + virCommandAddArg(cmd, "--process"); +- if (timestamp != 0) { +- virCommandAddArgFormat(cmd, "%lld,%llu", (long long) callerPid, timestamp); ++# ifdef PKCHECK_SUPPORTS_UID ++ supportsuid = true; ++# endif ++ if (supportsuid) { ++ virCommandAddArgFormat(cmd, "%lld,%llu,%lu", ++ (long long) callerPid, timestamp, (unsigned long) callerUid); + } else { +- virCommandAddArgFormat(cmd, "%lld", (long long) callerPid); ++ if (!polkitInsecureWarned) { ++ VIR_WARN("No support for caller UID with pkcheck. This deployment is known to be insecure."); ++ polkitInsecureWarned = true; ++ } ++ virCommandAddArgFormat(cmd, "%lld,%llu", (long long) callerPid, timestamp); + } + virCommandAddArg(cmd, "--allow-user-interaction"); + +diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c +index b472bc3..ff82583 100644 +--- a/src/access/viraccessdriverpolkit.c ++++ b/src/access/viraccessdriverpolkit.c +@@ -72,8 +72,12 @@ static char * + virAccessDriverPolkitFormatProcess(const char *actionid) + { + virIdentityPtr identity = virIdentityGetCurrent(); +- const char *process = NULL; ++ const char *callerPid = NULL; ++ const char *callerTime = NULL; ++ const char *callerUid = NULL; + char *ret = NULL; ++ bool supportsuid = false; ++ static bool polkitInsecureWarned; + + if (!identity) { + virAccessError(VIR_ERR_ACCESS_DENIED, +@@ -81,17 +85,43 @@ virAccessDriverPolkitFormatProcess(const char *actionid) + actionid); + return NULL; + } +- if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &process) < 0) ++ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &callerPid) < 0) ++ goto cleanup; ++ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME, &callerTime) < 0) ++ goto cleanup; ++ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_USER_ID, &callerUid) < 0) + goto cleanup; + +- if (!process) { ++ if (!callerPid) { + virAccessError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No UNIX process ID available")); + goto cleanup; + } +- +- if (VIR_STRDUP(ret, process) < 0) ++ if (!callerTime) { ++ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("No UNIX process start time available")); ++ goto cleanup; ++ } ++ if (!callerUid) { ++ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("No UNIX caller UID available")); + goto cleanup; ++ } ++ ++#ifdef PKCHECK_SUPPORTS_UID ++ supportsuid = true; ++#endif ++ if (supportsuid) { ++ if (virAsprintf(&ret, "%s,%s,%s", callerPid, callerTime, callerUid) < 0) ++ goto cleanup; ++ } else { ++ if (!polkitInsecureWarned) { ++ VIR_WARN("No support for caller UID with pkcheck. This deployment is known to be insecure."); ++ polkitInsecureWarned = true; ++ } ++ if (virAsprintf(&ret, "%s,%s", callerPid, callerTime) < 0) ++ goto cleanup; ++ } + + cleanup: + virObjectUnref(identity); +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Add-test-for-the-nodemask-double-free-crash.patch b/SOURCES/libvirt-Add-test-for-the-nodemask-double-free-crash.patch new file mode 100644 index 0000000..7838ac5 --- /dev/null +++ b/SOURCES/libvirt-Add-test-for-the-nodemask-double-free-crash.patch @@ -0,0 +1,87 @@ +From fe2d3ff5afa8c3c25a55a03690ebe844344d4636 Mon Sep 17 00:00:00 2001 +Message-Id: +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Thu, 12 Sep 2013 11:05:22 +0200 +Subject: [PATCH] Add test for the nodemask double free crash + +https://bugzilla.redhat.com/show_bug.cgi?id=1006722 + +Commit ef5d51d fixed a crash for numatune with auto placement and +nodeset specified: + + + +(cherry picked from commit fd72440a356bcfc205afcf5ab988e774610b2499) + +Commit a216e64 qemu: Set QEMU_AUDIO_DRV=none with -nographic +is not backported. +--- + ...qemuxml2argv-numatune-auto-nodeset-invalid.args | 4 +++ + .../qemuxml2argv-numatune-auto-nodeset-invalid.xml | 31 ++++++++++++++++++++++ + tests/qemuxml2argvtest.c | 1 + + 3 files changed, 36 insertions(+) + create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args + create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml + +diff --git a/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args +new file mode 100644 +index 0000000..11db342 +--- /dev/null ++++ b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.args +@@ -0,0 +1,4 @@ ++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \ ++/usr/bin/qemu -S -M pc -m 214 -smp 2 -nographic \ ++-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \ ++-hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none +diff --git a/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml +new file mode 100644 +index 0000000..d2315b4 +--- /dev/null ++++ b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-nodeset-invalid.xml +@@ -0,0 +1,31 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219136 ++ 219136 ++ 2 ++ ++ ++ ++ ++ hvm ++ ++ ++ ++ ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu ++ ++ ++ ++
        ++ ++ ++ ++ ++ +diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c +index 3a3c304..ca72947 100644 +--- a/tests/qemuxml2argvtest.c ++++ b/tests/qemuxml2argvtest.c +@@ -902,6 +902,7 @@ mymain(void) + DO_TEST("blkiotune-device", QEMU_CAPS_NAME); + DO_TEST("cputune", QEMU_CAPS_NAME); + DO_TEST("numatune-memory", NONE); ++ DO_TEST("numatune-auto-nodeset-invalid", NONE); + DO_TEST("numad", NONE); + DO_TEST("numad-auto-vcpu-static-numatune", NONE); + DO_TEST("numad-auto-memory-vcpu-cpuset", NONE); +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Address-missed-feedback-from-review-of-virt-login-shell.patch b/SOURCES/libvirt-Address-missed-feedback-from-review-of-virt-login-shell.patch new file mode 100644 index 0000000..06c3e00 --- /dev/null +++ b/SOURCES/libvirt-Address-missed-feedback-from-review-of-virt-login-shell.patch @@ -0,0 +1,227 @@ +From b76dda6c153e1251de6aa935b85942bb53213470 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 15:20:43 +0100 +Subject: [PATCH] Address missed feedback from review of virt-login-shell + +For https://bugzilla.redhat.com/show_bug.cgi?id=988491 + +Address a number of code, style and docs issues identified +in review of virt-login-shell after it was merged. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit a396473494dd099c2a0e6e03af9a9c7406a86108) +--- + tools/Makefile.am | 1 - + tools/virt-login-shell.c | 58 ++++++++++++++++++++++++++++++---------------- + tools/virt-login-shell.pod | 30 ++++++++++++++++++------ + 3 files changed, 61 insertions(+), 28 deletions(-) + +diff --git a/tools/Makefile.am b/tools/Makefile.am +index 00c582a..d48883c 100644 +--- a/tools/Makefile.am ++++ b/tools/Makefile.am +@@ -134,7 +134,6 @@ virt_host_validate_CFLAGS = \ + $(NULL) + + virt_login_shell_SOURCES = \ +- virt-login-shell.conf \ + virt-login-shell.c + + virt_login_shell_LDFLAGS = $(COVERAGE_LDFLAGS) +diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c +index b27e44f..1157cd0 100644 +--- a/tools/virt-login-shell.c ++++ b/tools/virt-login-shell.c +@@ -41,11 +41,11 @@ + #include "vircommand.h" + #define VIR_FROM_THIS VIR_FROM_NONE + +-static ssize_t nfdlist = 0; +-static int *fdlist = NULL; ++static ssize_t nfdlist; ++static int *fdlist; + static const char *conf_file = SYSCONFDIR "/libvirt/virt-login-shell.conf"; + +-static void virLoginShellFini(virConnectPtr conn, virDomainPtr dom) ++static void virLoginShellFini(virConnectPtr conn, virDomainPtr dom) + { + size_t i; + +@@ -105,7 +105,7 @@ static int virLoginShellAllowedUser(virConfPtr conf, + } + } + } +- virReportSystemError(EPERM, _("%s not listed as an allowed_users in %s"), name, conf_file); ++ virReportSystemError(EPERM, _("%s not matched against 'allowed_users' in %s"), name, conf_file); + cleanup: + VIR_FREE(gname); + return ret; +@@ -121,7 +121,7 @@ static char **virLoginShellGetShellArgv(virConfPtr conf) + if (!p) + return virStringSplit("/bin/sh -l", " ", 3); + +- if (p && p->type == VIR_CONF_LIST) { ++ if (p->type == VIR_CONF_LIST) { + size_t len; + virConfValuePtr pp; + +@@ -139,7 +139,6 @@ static char **virLoginShellGetShellArgv(virConfPtr conf) + if (VIR_STRDUP(shargv[i], pp->str) < 0) + goto error; + } +- shargv[len] = NULL; + } + return shargv; + error: +@@ -155,16 +154,27 @@ static char *progname; + static void + usage(void) + { +- fprintf(stdout, _("\n" +- "%s is a privileged program that allows non root users \n" +- "specified in %s to join a Linux container \n" +- "with a matching user name and launch a shell. \n" +- "\n%s [options]\n\n" +- " options:\n" +- " -h | --help this help:\n\n"), progname, conf_file, progname); ++ fprintf(stdout, ++ _("\n" ++ "Usage:\n" ++ " %s [options]\n\n" ++ "Options:\n" ++ " -h | --help Display program help:\n" ++ " -V | --version Display program version:\n" ++ "\n" ++ "libvirt login shell\n"), ++ progname); + return; + } + ++/* Display version information. */ ++static void ++show_version(void) ++{ ++ printf("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION); ++} ++ ++ + int + main(int argc, char **argv) + { +@@ -190,6 +200,7 @@ main(int argc, char **argv) + + struct option opt[] = { + {"help", no_argument, NULL, 'h'}, ++ {"version", optional_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; + if (virInitialize() < 0) { +@@ -214,20 +225,25 @@ main(int argc, char **argv) + return ret; + } + +- /* The only option we support is help +- */ +- while ((arg = getopt_long(argc, argv, "h", opt, &longindex)) != -1) { ++ while ((arg = getopt_long(argc, argv, "hV", opt, &longindex)) != -1) { + switch (arg) { + case 'h': + usage(); + exit(EXIT_SUCCESS); +- break; ++ ++ case 'V': ++ show_version(); ++ exit(EXIT_SUCCESS); ++ ++ case '?': ++ default: ++ usage(); ++ exit(EXIT_FAILURE); + } + } + + if (argc > optind) { + virReportSystemError(EINVAL, _("%s takes no options"), progname); +- errno = EINVAL; + goto cleanup; + } + +@@ -268,7 +284,9 @@ main(int argc, char **argv) + virErrorPtr last_error; + last_error = virGetLastError(); + if (last_error->code != VIR_ERR_OPERATION_INVALID) { +- virReportSystemError(last_error->code,_("Can't create %s container: %s"), name, virGetLastErrorMessage()); ++ virReportSystemError(last_error->code, ++ _("Can't create %s container: %s"), ++ name, last_error->message); + goto cleanup; + } + } +@@ -327,7 +345,7 @@ main(int argc, char **argv) + } + if (execv(shargv[0], (char *const*) shargv) < 0) { + virReportSystemError(errno, _("Unable exec shell %s"), shargv[0]); +- return -errno; ++ return EXIT_FAILURE; + } + } + return virProcessWait(ccpid, &status2); +diff --git a/tools/virt-login-shell.pod b/tools/virt-login-shell.pod +index 0cd35cf..e27d500 100644 +--- a/tools/virt-login-shell.pod ++++ b/tools/virt-login-shell.pod +@@ -8,26 +8,42 @@ B + + =head1 DESCRIPTION + +-The B program is setuid shell that is used to join +-an LXC container that matches the users name. If the container is not +-running virt-login-shell will attempt to start the container. ++The B program is a setuid shell that is used to join ++an LXC container that matches the user's name. If the container is not ++running, virt-login-shell will attempt to start the container. + virt-sandbox-shell is not allowed to be run by root. Normal users will get +-added to a container that matches their username, if it exists. And they are ++added to a container that matches their username, if it exists, and they are + configured in /etc/libvirt/virt-login-shell.conf. + + The basic structure of most virt-login-shell usage is: + + virt-login-shell + ++=head1 OPTIONS ++ ++=over ++ ++=item B<-h, --help> ++ ++Display command line help usage then exit. ++ ++=item B<-V, --version> ++ ++Display version information then exit. ++ ++=back ++ + =head1 CONFIG + + By default, virt-login-shell will execute the /bin/sh program for the user. +-You can modify this behaviour by defining the shell variable in /etc/libvirt/virt-login-shell.conf. ++You can modify this behaviour by defining the shell variable in ++/etc/libvirt/virt-login-shell.conf. + + eg. shell = [ "/bin/ksh", "--login"] + +-By default no users are allowed to user virt-login-shell, if you want to allow +-certain users to use virt-login-shell, you need to modify the allowed_users variable in /etc/libvirt/virt-login-shell.conf. ++By default no users are allowed to use virt-login-shell, if you want to allow ++certain users to use virt-login-shell, you need to modify the allowed_users ++variable in /etc/libvirt/virt-login-shell.conf. + + eg. allowed_users = [ "tom", "dick", "harry" ] + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Adjust-legacy-max-payload-size-to-account-for-header-information.patch b/SOURCES/libvirt-Adjust-legacy-max-payload-size-to-account-for-header-information.patch new file mode 100644 index 0000000..bbc9732 --- /dev/null +++ b/SOURCES/libvirt-Adjust-legacy-max-payload-size-to-account-for-header-information.patch @@ -0,0 +1,38 @@ +From 68d414af5fc764e92cc3beadc700964fdb348b1b Mon Sep 17 00:00:00 2001 +Message-Id: <68d414af5fc764e92cc3beadc700964fdb348b1b.1382534060.git.jdenemar@redhat.com> +From: Claudio Bley +Date: Wed, 16 Oct 2013 23:12:56 +0800 +Subject: [PATCH] Adjust legacy max payload size to account for header + information + +https://bugzilla.redhat.com/show_bug.cgi?id=950416 + +Commit 27e81517a87 set the payload size to 256 KB, which is +actually the max packet size, including the size of the header. + +Reduce this by VIR_NET_MESSAGE_HEADER_MAX (24) and set +VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX to 262120, which was the original +value before increasing the limit in commit eb635de1fed. +(cherry picked from commit 609eb987c6cef9082486e66b666f7b9351b783ed) + +Signed-off-by: Jiri Denemark +--- + src/rpc/virnetprotocol.x | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/rpc/virnetprotocol.x b/src/rpc/virnetprotocol.x +index 1eae7cb..7b6f753 100644 +--- a/src/rpc/virnetprotocol.x ++++ b/src/rpc/virnetprotocol.x +@@ -55,7 +55,7 @@ const VIR_NET_MESSAGE_INITIAL = 65536; + * payload size. We need to remember this for compat with + * old clients. + */ +-const VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX = 262144; ++const VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX = 262120; + + /* Maximum total message size (serialised). */ + const VIR_NET_MESSAGE_MAX = 16777216; +-- +1.8.4 + diff --git a/SOURCES/libvirt-Allow-root-directory-in-filesystem-source-dir-schema.patch b/SOURCES/libvirt-Allow-root-directory-in-filesystem-source-dir-schema.patch new file mode 100644 index 0000000..1058a5c --- /dev/null +++ b/SOURCES/libvirt-Allow-root-directory-in-filesystem-source-dir-schema.patch @@ -0,0 +1,119 @@ +From 88c5f4f82ea78857962ff3bd601aaa25dcb7d8bf Mon Sep 17 00:00:00 2001 +Message-Id: <88c5f4f82ea78857962ff3bd601aaa25dcb7d8bf.1383922565.git.jdenemar@redhat.com> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Thu, 7 Nov 2013 18:55:21 +0100 +Subject: [PATCH] Allow root directory in filesystem source dir schema + +Use absDirPath instead of absFilePath. + +https://bugzilla.redhat.com/show_bug.cgi?id=1028107 +(cherry picked from commit eab51940bd9d3b5f8b73f52c50ba6d00648f0909) + +Signed-off-by: Jiri Denemark +--- + docs/schemas/domaincommon.rng | 4 ++-- + tests/lxcxml2xmldata/lxc-filesystem-ram.xml | 4 ++++ + tests/lxcxml2xmldata/lxc-filesystem-root.xml | 25 +++++++++++++++++++++++++ + tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml | 4 ++++ + tests/lxcxml2xmltest.c | 1 + + 5 files changed, 36 insertions(+), 2 deletions(-) + create mode 100644 tests/lxcxml2xmldata/lxc-filesystem-root.xml + +diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng +index 5540745..c7eaf00 100644 +--- a/docs/schemas/domaincommon.rng ++++ b/docs/schemas/domaincommon.rng +@@ -1628,7 +1628,7 @@ + + + +- ++ + + + +@@ -1646,7 +1646,7 @@ + + + +- ++ + + + +diff --git a/tests/lxcxml2xmldata/lxc-filesystem-ram.xml b/tests/lxcxml2xmldata/lxc-filesystem-ram.xml +index 002fde6..58ae344 100644 +--- a/tests/lxcxml2xmldata/lxc-filesystem-ram.xml ++++ b/tests/lxcxml2xmldata/lxc-filesystem-ram.xml +@@ -14,6 +14,10 @@ + destroy + + /usr/libexec/libvirt_lxc ++ ++ ++ ++ + + + +diff --git a/tests/lxcxml2xmldata/lxc-filesystem-root.xml b/tests/lxcxml2xmldata/lxc-filesystem-root.xml +new file mode 100644 +index 0000000..1ce2b32 +--- /dev/null ++++ b/tests/lxcxml2xmldata/lxc-filesystem-root.xml +@@ -0,0 +1,25 @@ ++ ++ demo ++ 8369f1ac-7e46-e869-4ca5-759d51478066 ++ 500000 ++ 500000 ++ 1 ++ ++ exe ++ /bin/sh ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/libexec/libvirt_lxc ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml b/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml +index d2369a2..93162b3 100644 +--- a/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml ++++ b/tests/lxcxml2xmloutdata/lxc-filesystem-ram.xml +@@ -14,6 +14,10 @@ + destroy + + /usr/libexec/libvirt_lxc ++ ++ ++ ++ + + + +diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c +index f8b5959..8f66f82 100644 +--- a/tests/lxcxml2xmltest.c ++++ b/tests/lxcxml2xmltest.c +@@ -132,6 +132,7 @@ mymain(void) + DO_TEST("hostdev"); + DO_TEST("disk-formats"); + DO_TEST_DIFFERENT("filesystem-ram"); ++ DO_TEST("filesystem-root"); + + virObjectUnref(caps); + virObjectUnref(xmlopt); +-- +1.8.4.2 + diff --git a/SOURCES/libvirt-Allow-use-of-a-private-dbus-bus-connection.patch b/SOURCES/libvirt-Allow-use-of-a-private-dbus-bus-connection.patch new file mode 100644 index 0000000..fd1d9fb --- /dev/null +++ b/SOURCES/libvirt-Allow-use-of-a-private-dbus-bus-connection.patch @@ -0,0 +1,103 @@ +From 00c107bc1ef5a9ab3ad04f15d87fa529c17efefb Mon Sep 17 00:00:00 2001 +Message-Id: <00c107bc1ef5a9ab3ad04f15d87fa529c17efefb.1381871412.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Mon, 14 Oct 2013 16:45:17 +0100 +Subject: [PATCH] Allow use of a private dbus bus connection + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=998365 + +The dbus_bus_get() function returns a shared bus connection that +all libraries in a process can use. You are forbidden from calling +close on this connection though, since you can never know if any +other code might be using it. + +Add an option to use private dbus bus connections, if the app +wants to be able to close the connection. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 0cb774f051a3549dd3968e6f48b36e6f93ac79fc) +Signed-off-by: Jiri Denemark +--- + src/libvirt_private.syms | 1 + + src/util/virdbus.c | 16 +++++++++++++++- + src/util/virdbus.h | 2 ++ + 3 files changed, 18 insertions(+), 1 deletion(-) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index d9561b8..c91a9f9 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1298,6 +1298,7 @@ virDBusHasSystemBus; + virDBusMessageDecode; + virDBusMessageEncode; + virDBusMessageRead; ++virDBusSetSharedBus; + + + # util/virdnsmasq.h +diff --git a/src/util/virdbus.c b/src/util/virdbus.c +index a2c4b4e..bcc5b1c 100644 +--- a/src/util/virdbus.c ++++ b/src/util/virdbus.c +@@ -32,6 +32,7 @@ + + #ifdef WITH_DBUS + ++static bool sharedBus = true; + static DBusConnection *systembus = NULL; + static DBusConnection *sessionbus = NULL; + static virOnceControl systemonce = VIR_ONCE_CONTROL_INITIALIZER; +@@ -43,6 +44,11 @@ static dbus_bool_t virDBusAddWatch(DBusWatch *watch, void *data); + static void virDBusRemoveWatch(DBusWatch *watch, void *data); + static void virDBusToggleWatch(DBusWatch *watch, void *data); + ++void virDBusSetSharedBus(bool shared) ++{ ++ sharedBus = shared; ++} ++ + static DBusConnection *virDBusBusInit(DBusBusType type, DBusError *dbuserr) + { + DBusConnection *bus; +@@ -52,7 +58,10 @@ static DBusConnection *virDBusBusInit(DBusBusType type, DBusError *dbuserr) + dbus_threads_init_default(); + + dbus_error_init(dbuserr); +- if (!(bus = dbus_bus_get(type, dbuserr))) ++ bus = sharedBus ? ++ dbus_bus_get(type, dbuserr) : ++ dbus_bus_get_private(type, dbuserr); ++ if (!bus) + return NULL; + + dbus_connection_set_exit_on_disconnect(bus, FALSE); +@@ -1264,6 +1273,11 @@ int virDBusIsServiceEnabled(const char *name) + + + #else /* ! WITH_DBUS */ ++void virDBusSetSharedBus(bool shared ATTRIBUTE_UNUSED) ++{ ++ /* nothing */ ++} ++ + DBusConnection *virDBusGetSystemBus(void) + { + virReportError(VIR_ERR_INTERNAL_ERROR, +diff --git a/src/util/virdbus.h b/src/util/virdbus.h +index 194a01a..125a405 100644 +--- a/src/util/virdbus.h ++++ b/src/util/virdbus.h +@@ -31,6 +31,8 @@ + # endif + # include "internal.h" + ++void virDBusSetSharedBus(bool shared); ++ + DBusConnection *virDBusGetSystemBus(void); + bool virDBusHasSystemBus(void); + DBusConnection *virDBusGetSessionBus(void); +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Also-store-user-group-ID-values-in-virIdentity.patch b/SOURCES/libvirt-Also-store-user-group-ID-values-in-virIdentity.patch new file mode 100644 index 0000000..ac185d5 --- /dev/null +++ b/SOURCES/libvirt-Also-store-user-group-ID-values-in-virIdentity.patch @@ -0,0 +1,160 @@ +From 0401b6b48f3743fb819cfe494d1b23ecb8796198 Mon Sep 17 00:00:00 2001 +Message-Id: <0401b6b48f3743fb819cfe494d1b23ecb8796198.1379597659.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Thu, 22 Aug 2013 16:00:01 +0100 +Subject: [PATCH] Also store user & group ID values in virIdentity + +https://bugzilla.redhat.com/show_bug.cgi?id=1006272 + +Future improvements to the polkit code will require access to +the numeric user ID, not merely user name. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit db7a5688c05f3fd60d9d2b74c72427eb9ee9c176) +--- + src/rpc/virnetserverclient.c | 18 ++++++++++++++++++ + src/util/viridentity.c | 23 +++++++++++++++++++---- + src/util/viridentity.h | 2 ++ + 3 files changed, 39 insertions(+), 4 deletions(-) + +diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c +index 83d5cf1..19c4100 100644 +--- a/src/rpc/virnetserverclient.c ++++ b/src/rpc/virnetserverclient.c +@@ -652,7 +652,9 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client) + char *processid = NULL; + char *processtime = NULL; + char *username = NULL; ++ char *userid = NULL; + char *groupname = NULL; ++ char *groupid = NULL; + #if WITH_SASL + char *saslname = NULL; + #endif +@@ -672,8 +674,12 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client) + + if (!(username = virGetUserName(uid))) + goto cleanup; ++ if (virAsprintf(&userid, "%d", (int)uid) < 0) ++ goto cleanup; + if (!(groupname = virGetGroupName(gid))) + goto cleanup; ++ if (virAsprintf(&userid, "%d", (int)gid) < 0) ++ goto cleanup; + if (virAsprintf(&processid, "%llu", + (unsigned long long)pid) < 0) + goto cleanup; +@@ -710,11 +716,21 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client) + VIR_IDENTITY_ATTR_UNIX_USER_NAME, + username) < 0) + goto error; ++ if (userid && ++ virIdentitySetAttr(ret, ++ VIR_IDENTITY_ATTR_UNIX_USER_ID, ++ userid) < 0) ++ goto error; + if (groupname && + virIdentitySetAttr(ret, + VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, + groupname) < 0) + goto error; ++ if (groupid && ++ virIdentitySetAttr(ret, ++ VIR_IDENTITY_ATTR_UNIX_GROUP_ID, ++ groupid) < 0) ++ goto error; + if (processid && + virIdentitySetAttr(ret, + VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, +@@ -745,7 +761,9 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client) + + cleanup: + VIR_FREE(username); ++ VIR_FREE(userid); + VIR_FREE(groupname); ++ VIR_FREE(groupid); + VIR_FREE(processid); + VIR_FREE(processtime); + VIR_FREE(seccontext); +diff --git a/src/util/viridentity.c b/src/util/viridentity.c +index 781f660..03c375b 100644 +--- a/src/util/viridentity.c ++++ b/src/util/viridentity.c +@@ -133,7 +133,9 @@ int virIdentitySetCurrent(virIdentityPtr ident) + virIdentityPtr virIdentityGetSystem(void) + { + char *username = NULL; ++ char *userid = NULL; + char *groupname = NULL; ++ char *groupid = NULL; + char *seccontext = NULL; + virIdentityPtr ret = NULL; + #if WITH_SELINUX +@@ -147,8 +149,13 @@ virIdentityPtr virIdentityGetSystem(void) + + if (!(username = virGetUserName(getuid()))) + goto cleanup; ++ if (virAsprintf(&userid, "%d", (int)getuid()) < 0) ++ goto cleanup; ++ + if (!(groupname = virGetGroupName(getgid()))) + goto cleanup; ++ if (virAsprintf(&groupid, "%d", (int)getgid()) < 0) ++ goto cleanup; + + #if WITH_SELINUX + if (getcon(&con) < 0) { +@@ -166,16 +173,22 @@ virIdentityPtr virIdentityGetSystem(void) + if (!(ret = virIdentityNew())) + goto cleanup; + +- if (username && +- virIdentitySetAttr(ret, ++ if (virIdentitySetAttr(ret, + VIR_IDENTITY_ATTR_UNIX_USER_NAME, + username) < 0) + goto error; +- if (groupname && +- virIdentitySetAttr(ret, ++ if (virIdentitySetAttr(ret, ++ VIR_IDENTITY_ATTR_UNIX_USER_ID, ++ userid) < 0) ++ goto error; ++ if (virIdentitySetAttr(ret, + VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, + groupname) < 0) + goto error; ++ if (virIdentitySetAttr(ret, ++ VIR_IDENTITY_ATTR_UNIX_GROUP_ID, ++ groupid) < 0) ++ goto error; + if (seccontext && + virIdentitySetAttr(ret, + VIR_IDENTITY_ATTR_SELINUX_CONTEXT, +@@ -188,7 +201,9 @@ virIdentityPtr virIdentityGetSystem(void) + + cleanup: + VIR_FREE(username); ++ VIR_FREE(userid); + VIR_FREE(groupname); ++ VIR_FREE(groupid); + VIR_FREE(seccontext); + VIR_FREE(processid); + return ret; +diff --git a/src/util/viridentity.h b/src/util/viridentity.h +index 4bae8d6..a240c2d 100644 +--- a/src/util/viridentity.h ++++ b/src/util/viridentity.h +@@ -29,7 +29,9 @@ typedef virIdentity *virIdentityPtr; + + typedef enum { + VIR_IDENTITY_ATTR_UNIX_USER_NAME, ++ VIR_IDENTITY_ATTR_UNIX_USER_ID, + VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, ++ VIR_IDENTITY_ATTR_UNIX_GROUP_ID, + VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, + VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME, + VIR_IDENTITY_ATTR_SASL_USER_NAME, +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Always-specify-qcow2-compat-level-on-qemu-img-command-line.patch b/SOURCES/libvirt-Always-specify-qcow2-compat-level-on-qemu-img-command-line.patch new file mode 100644 index 0000000..c9e0a7e --- /dev/null +++ b/SOURCES/libvirt-Always-specify-qcow2-compat-level-on-qemu-img-command-line.patch @@ -0,0 +1,199 @@ +From d86f8ca314a4209b19d2ea425c2447b006afc84e Mon Sep 17 00:00:00 2001 +Message-Id: +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 4 Sep 2013 12:46:10 +0200 +Subject: [PATCH] Always specify qcow2 compat level on qemu-img command line + +qemu-img is going to switch the default for QCOW2 +to QCOW2v3 (compat=1.1) [1] + +Extend the probing for qemu-img command line options to check +if -o compat is supported. If the volume definition specifies +the qcow2 format but no compat level and -o compat is supported, +specify -o compat=0.10 to create a QCOW2v2 image. + +https://bugzilla.redhat.com/show_bug.cgi?id=997977 +(cherry picked from commit bab2eda6ada1bf832decdc64cc5062e54eb105df) +--- + src/storage/storage_backend.c | 47 +++++++++++++++++++--- + tests/storagevolxml2argvdata/qcow2-compat.argv | 3 ++ + .../qcow2-from-logical-compat.argv | 3 ++ + .../qcow2-nobacking-convert-prealloc-compat.argv | 3 ++ + .../qcow2-nobacking-prealloc-compat.argv | 3 ++ + tests/storagevolxml2argvtest.c | 26 ++++++++++++ + 6 files changed, 79 insertions(+), 6 deletions(-) + create mode 100644 tests/storagevolxml2argvdata/qcow2-compat.argv + create mode 100644 tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv + create mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv + create mode 100644 tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv + +diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c +index 8d5880e..4ebe11b 100644 +--- a/src/storage/storage_backend.c ++++ b/src/storage/storage_backend.c +@@ -581,8 +581,34 @@ enum { + QEMU_IMG_BACKING_FORMAT_NONE = 0, + QEMU_IMG_BACKING_FORMAT_FLAG, + QEMU_IMG_BACKING_FORMAT_OPTIONS, ++ QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT, + }; + ++static bool ++virStorageBackendQemuImgSupportsCompat(const char *qemuimg) ++{ ++ bool ret = false; ++ char *output; ++ virCommandPtr cmd = NULL; ++ ++ cmd = virCommandNewArgList(qemuimg, "create", "-o", "?", "-f", "qcow2", ++ "/dev/null", NULL); ++ ++ virCommandAddEnvString(cmd, "LC_ALL=C"); ++ virCommandSetOutputBuffer(cmd, &output); ++ ++ if (virCommandRun(cmd, NULL) < 0) ++ goto cleanup; ++ ++ if (strstr(output, "\ncompat ")) ++ ret = true; ++ ++cleanup: ++ virCommandFree(cmd); ++ VIR_FREE(output); ++ return ret; ++} ++ + static int + virStorageBackendQEMUImgBackingFormat(const char *qemuimg) + { +@@ -612,12 +638,16 @@ virStorageBackendQEMUImgBackingFormat(const char *qemuimg) + goto cleanup; + } + if (((tmp = strstr(start, "-F fmt")) && tmp < end) || +- ((tmp = strstr(start, "-F backing_fmt")) && tmp < end)) ++ ((tmp = strstr(start, "-F backing_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 ++ } else if ((tmp = strstr(start, "[-o options]")) && tmp < end) { ++ if (virStorageBackendQemuImgSupportsCompat(qemuimg)) ++ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT; ++ else ++ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS; ++ } else { + ret = QEMU_IMG_BACKING_FORMAT_NONE; ++ } + + cleanup: + virCommandFree(cmd); +@@ -705,6 +735,7 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn, + const char *backingType = NULL; + const char *inputPath = NULL; + const char *inputType = NULL; ++ const char *compat = vol->target.compat; + char *opts = NULL; + bool convert = false; + bool backing = false; +@@ -854,12 +885,16 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn, + if (backing) + virCommandAddArgList(cmd, "-b", vol->backingStore.path, NULL); + +- if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS) { ++ if (imgformat >= QEMU_IMG_BACKING_FORMAT_OPTIONS) { ++ if (vol->target.format == VIR_STORAGE_FILE_QCOW2 && !compat && ++ imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS_COMPAT) ++ compat = "0.10"; ++ + if (virStorageBackendCreateQemuImgOpts(&opts, + backing ? backingType : NULL, + do_encryption, preallocate, + vol->target.format, +- vol->target.compat, ++ compat, + vol->target.features) < 0) { + virCommandFree(cmd); + return NULL; +diff --git a/tests/storagevolxml2argvdata/qcow2-compat.argv b/tests/storagevolxml2argvdata/qcow2-compat.argv +new file mode 100644 +index 0000000..37ad2c0 +--- /dev/null ++++ b/tests/storagevolxml2argvdata/qcow2-compat.argv +@@ -0,0 +1,3 @@ ++qemu-img create -f qcow2 -b /dev/null \ ++-o backing_fmt=raw,encryption=on,compat=0.10 \ ++/var/lib/libvirt/images/OtherDemo.img 5242880K +diff --git a/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv b/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv +new file mode 100644 +index 0000000..5f365b1 +--- /dev/null ++++ b/tests/storagevolxml2argvdata/qcow2-from-logical-compat.argv +@@ -0,0 +1,3 @@ ++qemu-img convert -f raw -O qcow2 \ ++-o encryption=on,compat=0.10 \ ++/dev/HostVG/Swap /var/lib/libvirt/images/OtherDemo.img +diff --git a/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv b/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv +new file mode 100644 +index 0000000..3d93ec8 +--- /dev/null ++++ b/tests/storagevolxml2argvdata/qcow2-nobacking-convert-prealloc-compat.argv +@@ -0,0 +1,3 @@ ++qemu-img convert -f raw -O qcow2 \ ++-o encryption=on,preallocation=metadata,compat=0.10 \ ++/var/lib/libvirt/images/sparse.img /var/lib/libvirt/images/OtherDemo.img +diff --git a/tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv b/tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv +new file mode 100644 +index 0000000..903c94e +--- /dev/null ++++ b/tests/storagevolxml2argvdata/qcow2-nobacking-prealloc-compat.argv +@@ -0,0 +1,3 @@ ++qemu-img create -f qcow2 \ ++-o encryption=on,preallocation=metadata,compat=0.10 \ ++/var/lib/libvirt/images/OtherDemo.img 5242880K +diff --git a/tests/storagevolxml2argvtest.c b/tests/storagevolxml2argvtest.c +index b1cf09f..cafcaad 100644 +--- a/tests/storagevolxml2argvtest.c ++++ b/tests/storagevolxml2argvtest.c +@@ -195,6 +195,7 @@ enum { + FMT_NONE = 0, + FMT_FLAG, + FMT_OPTIONS, ++ FMT_COMPAT, + }; + + +@@ -271,6 +272,31 @@ mymain(void) + "pool-dir", "vol-qcow2-nobacking", + "logical-from-qcow2", 0, FMT_OPTIONS); + ++ DO_TEST("pool-dir", "vol-qcow2", ++ NULL, NULL, ++ "qcow2-compat", 0, FMT_COMPAT); ++ DO_TEST("pool-dir", "vol-qcow2-nobacking", ++ NULL, NULL, ++ "qcow2-nobacking-prealloc-compat", flags, FMT_COMPAT); ++ DO_TEST("pool-dir", "vol-qcow2-nobacking", ++ "pool-dir", "vol-file", ++ "qcow2-nobacking-convert-prealloc-compat", flags, FMT_COMPAT); ++ DO_TEST("pool-dir", "vol-qcow2-lazy", ++ NULL, NULL, ++ "qcow2-lazy", 0, FMT_COMPAT); ++ DO_TEST("pool-dir", "vol-qcow2-1.1", ++ NULL, NULL, ++ "qcow2-1.1", 0, FMT_COMPAT); ++ DO_TEST_FAIL("pool-dir", "vol-qcow2-0.10-lazy", ++ NULL, NULL, ++ "qcow2-0.10-lazy", 0, FMT_COMPAT); ++ DO_TEST("pool-dir", "vol-qcow2-nobacking", ++ "pool-logical", "vol-logical", ++ "qcow2-from-logical-compat", 0, FMT_COMPAT); ++ DO_TEST("pool-logical", "vol-logical", ++ "pool-dir", "vol-qcow2-nobacking", ++ "logical-from-qcow2", 0, FMT_COMPAT); ++ + return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; + } + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Avoid-crash-if-NULL-is-passed-for-filename-funcname-in-logging.patch b/SOURCES/libvirt-Avoid-crash-if-NULL-is-passed-for-filename-funcname-in-logging.patch new file mode 100644 index 0000000..e5d3af7 --- /dev/null +++ b/SOURCES/libvirt-Avoid-crash-if-NULL-is-passed-for-filename-funcname-in-logging.patch @@ -0,0 +1,41 @@ +From df25234304fb6ec02e20df31956946df53a3d941 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Fri, 2 Aug 2013 12:15:57 +0100 +Subject: [PATCH] Avoid crash if NULL is passed for filename/funcname in + logging + +https://bugzilla.redhat.com/show_bug.cgi?id=991348 + +The journald code would crash if a NULL was passed for the +filename / funcname in the logging code. This shouldn't +happen in general, but it is better to be safe, since there +have been bugs triggering this. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit b4ca2999020ab4adf7a73ccbff1de2b40a097874) +--- + src/util/virlog.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/util/virlog.c b/src/util/virlog.c +index d1fb0b3..047a131 100644 +--- a/src/util/virlog.c ++++ b/src/util/virlog.c +@@ -1181,9 +1181,11 @@ virLogOutputToJournald(virLogSource source, + journalAddInt(&state, "PRIORITY", priority); + journalAddString(&state, "LIBVIRT_SOURCE", + virLogSourceTypeToString(source)); +- journalAddString(&state, "CODE_FILE", filename); ++ if (filename) ++ journalAddString(&state, "CODE_FILE", filename); + journalAddInt(&state, "CODE_LINE", linenr); +- journalAddString(&state, "CODE_FUNC", funcname); ++ if (funcname) ++ journalAddString(&state, "CODE_FUNC", funcname); + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Avoid-deleting-NULL-veth-device-name.patch b/SOURCES/libvirt-Avoid-deleting-NULL-veth-device-name.patch new file mode 100644 index 0000000..0de1283 --- /dev/null +++ b/SOURCES/libvirt-Avoid-deleting-NULL-veth-device-name.patch @@ -0,0 +1,37 @@ +From d6fe3f01e405113c9ff5ada2d75e62530608d353 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Mon, 7 Oct 2013 17:17:29 +0100 +Subject: [PATCH] Avoid deleting NULL veth device name + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1014604 + +If veth device allocation has a fatal error, the veths +array may contain NULL device names. Avoid calling the +virNetDevVethDelete function on such names. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 8766e9b5a56109155b5c952af91d384d7e0555ec) +Signed-off-by: Jiri Denemark +--- + src/lxc/lxc_process.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c +index bc9bdfb..47e6dd7 100644 +--- a/src/lxc/lxc_process.c ++++ b/src/lxc/lxc_process.c +@@ -1280,7 +1280,7 @@ cleanup: + rc = -1; + } + for (i = 0; i < nveths; i++) { +- if (rc != 0) ++ if (rc != 0 && veths[i]) + ignore_value(virNetDevVethDelete(veths[i])); + VIR_FREE(veths[i]); + } +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Avoid-re-generating-certs-every-time.patch b/SOURCES/libvirt-Avoid-re-generating-certs-every-time.patch new file mode 100644 index 0000000..78932b2 --- /dev/null +++ b/SOURCES/libvirt-Avoid-re-generating-certs-every-time.patch @@ -0,0 +1,1048 @@ +From 1f5e6cb8df70b658f48d5b562b5b483778dd911e Mon Sep 17 00:00:00 2001 +Message-Id: <1f5e6cb8df70b658f48d5b562b5b483778dd911e.1377873637.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 11:32:46 +0100 +Subject: [PATCH] Avoid re-generating certs every time + +For https://bugzilla.redhat.com/show_bug.cgi?id=994158 + +Currently every test case in the TLS test suite generates the +certs fresh. This is a waste of time, since its parameters +don't change across test cases. Create certs once in main +method. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 90811c5987870f348ebc545b5a6d127cc2076723) +--- + tests/virnettlscontexttest.c | 670 +++++++++++++++++++++++-------------------- + tests/virnettlshelpers.c | 9 +- + tests/virnettlshelpers.h | 4 +- + tests/virnettlssessiontest.c | 152 +++++----- + 4 files changed, 445 insertions(+), 390 deletions(-) + +diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c +index 0a0d31a..4211a74 100644 +--- a/tests/virnettlscontexttest.c ++++ b/tests/virnettlscontexttest.c +@@ -62,10 +62,6 @@ static int testTLSContextInit(const void *opaque) + virNetTLSContextPtr ctxt = NULL; + int ret = -1; + +- testTLSGenerateCert(&data->careq); +- data->certreq.cacrt = data->careq.crt; +- testTLSGenerateCert(&data->certreq); +- + if (data->isServer) { + ctxt = virNetTLSContextNewServer(data->careq.filename, + NULL, +@@ -103,8 +99,6 @@ static int testTLSContextInit(const void *opaque) + + cleanup: + virObjectUnref(ctxt); +- testTLSDiscardCert(&data->careq); +- testTLSDiscardCert(&data->certreq); + return ret; + } + +@@ -124,38 +118,54 @@ mymain(void) + data.careq = _caReq; \ + data.certreq = _certReq; \ + data.expectFail = _expectFail; \ +- if (virtTestRun("TLS Context", 1, testTLSContextInit, &data) < 0) \ ++ if (virtTestRun("TLS Context " #_caReq " + " #_certReq, 1, \ ++ testTLSContextInit, &data) < 0) \ + ret = -1; \ + } while (0) + ++# define TLS_CERT_REQ(varname, cavarname, \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ ++ static struct testTLSCertReq varname = { \ ++ NULL, #varname ".pem", \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \ ++ }; \ ++ testTLSGenerateCert(&varname, cavarname.crt) ++ ++# define TLS_ROOT_REQ(varname, \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ ++ static struct testTLSCertReq varname = { \ ++ NULL, #varname ".pem", \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \ ++ }; \ ++ testTLSGenerateCert(&varname, NULL) ++ ++ + /* A perfect CA, perfect client & perfect server */ + + /* Basic:CA:critical */ +- static struct testTLSCertReq cacertreq = { +- NULL, NULL, "cacert.pem", "UK", +- "libvirt CA", NULL, NULL, NULL, NULL, +- true, true, true, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; +- static struct testTLSCertReq servercertreq = { +- NULL, NULL, "servercert.pem", "UK", +- "libvirt.org", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; +- static struct testTLSCertReq clientcertreq = { +- NULL, NULL, "clientcert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 0, 0, +- }; +- ++ TLS_ROOT_REQ(cacertreq, ++ "UK", "libvirt CA", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); ++ ++ TLS_CERT_REQ(servercertreq, cacertreq, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ TLS_CERT_REQ(clientcertreq, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, 0); + + DO_CTX_TEST(true, cacertreq, servercertreq, false); + DO_CTX_TEST(false, cacertreq, clientcertreq, false); +@@ -164,249 +174,241 @@ mymain(void) + /* Some other CAs which are good */ + + /* Basic:CA:critical */ +- static struct testTLSCertReq cacert1req = { +- NULL, NULL, "cacert1.pem", "UK", +- "libvirt CA 1", NULL, NULL, NULL, NULL, +- true, true, true, +- false, false, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_ROOT_REQ(cacert1req, ++ "UK", "libvirt CA 1", NULL, NULL, NULL, NULL, ++ true, true, true, ++ false, false, 0, ++ false, false, NULL, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercert1req, cacert1req, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ + /* Basic:CA:not-critical */ +- static struct testTLSCertReq cacert2req = { +- NULL, NULL, "cacert2.pem", "UK", +- "libvirt CA 2", NULL, NULL, NULL, NULL, +- true, false, true, +- false, false, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_ROOT_REQ(cacert2req, ++ "UK", "libvirt CA 2", NULL, NULL, NULL, NULL, ++ true, false, true, ++ false, false, 0, ++ false, false, NULL, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercert2req, cacert2req, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ + /* Key usage:cert-sign:critical */ +- static struct testTLSCertReq cacert3req = { +- NULL, NULL, "cacert3.pem", "UK", +- "libvirt CA 3", NULL, NULL, NULL, NULL, +- true, true, true, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; +- +- DO_CTX_TEST(true, cacert1req, servercertreq, false); +- DO_CTX_TEST(true, cacert2req, servercertreq, false); +- DO_CTX_TEST(true, cacert3req, servercertreq, false); ++ TLS_ROOT_REQ(cacert3req, ++ "UK", "libvirt CA 3", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercert3req, cacert3req, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ ++ DO_CTX_TEST(true, cacert1req, servercert1req, false); ++ DO_CTX_TEST(true, cacert2req, servercert2req, false); ++ DO_CTX_TEST(true, cacert3req, servercert3req, false); + + /* Now some bad certs */ + + /* Key usage:dig-sig:not-critical */ +- static struct testTLSCertReq cacert4req = { +- NULL, NULL, "cacert4.pem", "UK", +- "libvirt CA 4", NULL, NULL, NULL, NULL, +- true, true, true, +- true, false, GNUTLS_KEY_DIGITAL_SIGNATURE, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_ROOT_REQ(cacert4req, ++ "UK", "libvirt CA 4", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, false, GNUTLS_KEY_DIGITAL_SIGNATURE, ++ false, false, NULL, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercert4req, cacert4req, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + /* no-basic */ +- static struct testTLSCertReq cacert5req = { +- NULL, NULL, "cacert5.pem", "UK", +- "libvirt CA 5", NULL, NULL, NULL, NULL, +- false, false, false, +- false, false, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_ROOT_REQ(cacert5req, ++ "UK", "libvirt CA 5", NULL, NULL, NULL, NULL, ++ false, false, false, ++ false, false, 0, ++ false, false, NULL, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercert5req, cacert5req, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + /* Key usage:dig-sig:critical */ +- static struct testTLSCertReq cacert6req = { +- NULL, NULL, "cacert6.pem", "UK", +- "libvirt CA 6", NULL, NULL, NULL, NULL, +- true, true, true, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_ROOT_REQ(cacert6req, ++ "UK", "libvirt CA 6", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE, ++ false, false, NULL, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercert6req, cacert6req, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + + /* Technically a CA cert with basic constraints + * key purpose == key signing + non-critical should + * be rejected. GNUTLS < 3 does not reject it and + * we don't anticipate them changing this behaviour + */ +- DO_CTX_TEST(true, cacert4req, servercertreq, GNUTLS_VERSION_MAJOR >= 3); +- DO_CTX_TEST(true, cacert5req, servercertreq, true); +- DO_CTX_TEST(true, cacert6req, servercertreq, true); ++ DO_CTX_TEST(true, cacert4req, servercert4req, GNUTLS_VERSION_MAJOR >= 3); ++ DO_CTX_TEST(true, cacert5req, servercert5req, true); ++ DO_CTX_TEST(true, cacert6req, servercert6req, true); + + + /* Various good servers */ + /* no usage or purpose */ +- static struct testTLSCertReq servercert1req = { +- NULL, NULL, "servercert1.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert7req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ false, false, NULL, NULL, ++ 0, 0); + /* usage:cert-sign+dig-sig+encipher:critical */ +- static struct testTLSCertReq servercert2req = { +- NULL, NULL, "servercert2.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert8req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); + /* usage:cert-sign:not-critical */ +- static struct testTLSCertReq servercert3req = { +- NULL, NULL, "servercert3.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, false, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert9req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, false, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); + /* purpose:server:critical */ +- static struct testTLSCertReq servercert4req = { +- NULL, NULL, "servercert4.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert10req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + /* purpose:server:not-critical */ +- static struct testTLSCertReq servercert5req = { +- NULL, NULL, "servercert5.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, false, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert11req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, false, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + /* purpose:client+server:critical */ +- static struct testTLSCertReq servercert6req = { +- NULL, NULL, "servercert6.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert12req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, ++ 0, 0); + /* purpose:client+server:not-critical */ +- static struct testTLSCertReq servercert7req = { +- NULL, NULL, "servercert7.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, +- 0, 0, +- }; +- +- DO_CTX_TEST(true, cacertreq, servercert1req, false); +- DO_CTX_TEST(true, cacertreq, servercert2req, false); +- DO_CTX_TEST(true, cacertreq, servercert3req, false); +- DO_CTX_TEST(true, cacertreq, servercert4req, false); +- DO_CTX_TEST(true, cacertreq, servercert5req, false); +- DO_CTX_TEST(true, cacertreq, servercert6req, false); ++ TLS_CERT_REQ(servercert13req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, ++ 0, 0); ++ + DO_CTX_TEST(true, cacertreq, servercert7req, false); ++ DO_CTX_TEST(true, cacertreq, servercert8req, false); ++ DO_CTX_TEST(true, cacertreq, servercert9req, false); ++ DO_CTX_TEST(true, cacertreq, servercert10req, false); ++ DO_CTX_TEST(true, cacertreq, servercert11req, false); ++ DO_CTX_TEST(true, cacertreq, servercert12req, false); ++ DO_CTX_TEST(true, cacertreq, servercert13req, false); + /* Bad servers */ + + /* usage:cert-sign:critical */ +- static struct testTLSCertReq servercert8req = { +- NULL, NULL, "servercert8.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert14req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); + /* purpose:client:critical */ +- static struct testTLSCertReq servercert9req = { +- NULL, NULL, "servercert9.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert15req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, 0); + /* usage: none:critical */ +- static struct testTLSCertReq servercert10req = { +- NULL, NULL, "servercert10.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercert16req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, 0, ++ false, false, NULL, NULL, ++ 0, 0); + +- DO_CTX_TEST(true, cacertreq, servercert8req, true); +- DO_CTX_TEST(true, cacertreq, servercert9req, true); +- DO_CTX_TEST(true, cacertreq, servercert10req, true); ++ DO_CTX_TEST(true, cacertreq, servercert14req, true); ++ DO_CTX_TEST(true, cacertreq, servercert15req, true); ++ DO_CTX_TEST(true, cacertreq, servercert16req, true); + + + + /* Various good clients */ + /* no usage or purpose */ +- static struct testTLSCertReq clientcert1req = { +- NULL, NULL, "clientcert1.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert1req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ false, false, NULL, NULL, ++ 0, 0); + /* usage:cert-sign+dig-sig+encipher:critical */ +- static struct testTLSCertReq clientcert2req = { +- NULL, NULL, "clientcert2.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert2req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); + /* usage:cert-sign:not-critical */ +- static struct testTLSCertReq clientcert3req = { +- NULL, NULL, "clientcert3.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, false, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert3req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, false, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); + /* purpose:client:critical */ +- static struct testTLSCertReq clientcert4req = { +- NULL, NULL, "clientcert4.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert4req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, 0); + /* purpose:client:not-critical */ +- static struct testTLSCertReq clientcert5req = { +- NULL, NULL, "clientcert5.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, false, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert5req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, false, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, 0); + /* purpose:client+client:critical */ +- static struct testTLSCertReq clientcert6req = { +- NULL, NULL, "clientcert6.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert6req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, ++ 0, 0); + /* purpose:client+client:not-critical */ +- static struct testTLSCertReq clientcert7req = { +- NULL, NULL, "clientcert7.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert7req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, ++ 0, 0); + + DO_CTX_TEST(false, cacertreq, clientcert1req, false); + DO_CTX_TEST(false, cacertreq, clientcert2req, false); +@@ -418,32 +420,26 @@ mymain(void) + /* Bad clients */ + + /* usage:cert-sign:critical */ +- static struct testTLSCertReq clientcert8req = { +- NULL, NULL, "clientcert8.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert8req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); + /* purpose:client:critical */ +- static struct testTLSCertReq clientcert9req = { +- NULL, NULL, "clientcert9.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- false, false, 0, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert9req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ false, false, 0, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + /* usage: none:critical */ +- static struct testTLSCertReq clientcert10req = { +- NULL, NULL, "clientcert10.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(clientcert10req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, 0, ++ false, false, NULL, NULL, ++ 0, 0); + + DO_CTX_TEST(false, cacertreq, clientcert8req, true); + DO_CTX_TEST(false, cacertreq, clientcert9req, true); +@@ -453,66 +449,114 @@ mymain(void) + + /* Expired stuff */ + +- static struct testTLSCertReq cacertexpreq = { +- NULL, NULL, "cacert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, true, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, -1, +- }; +- static struct testTLSCertReq servercertexpreq = { +- NULL, NULL, "servercert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, -1, +- }; +- static struct testTLSCertReq clientcertexpreq = { +- NULL, NULL, "clientcert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 0, -1, +- }; +- +- DO_CTX_TEST(true, cacertexpreq, servercertreq, true); +- DO_CTX_TEST(true, cacertreq, servercertexpreq, true); +- DO_CTX_TEST(false, cacertreq, clientcertexpreq, true); ++ TLS_ROOT_REQ(cacertexpreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, -1); ++ TLS_CERT_REQ(servercertexpreq, cacertexpreq, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercertexp1req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, -1); ++ TLS_CERT_REQ(clientcertexp1req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, -1); ++ ++ DO_CTX_TEST(true, cacertexpreq, servercertexpreq, true); ++ DO_CTX_TEST(true, cacertreq, servercertexp1req, true); ++ DO_CTX_TEST(false, cacertreq, clientcertexp1req, true); + + + /* Not activated stuff */ + +- static struct testTLSCertReq cacertnewreq = { +- NULL, NULL, "cacert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, true, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 1, 2, +- }; +- static struct testTLSCertReq servercertnewreq = { +- NULL, NULL, "servercert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 1, 2, +- }; +- static struct testTLSCertReq clientcertnewreq = { +- NULL, NULL, "clientcert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 1, 2, +- }; +- +- DO_CTX_TEST(true, cacertnewreq, servercertreq, true); +- DO_CTX_TEST(true, cacertreq, servercertnewreq, true); +- DO_CTX_TEST(false, cacertreq, clientcertnewreq, true); ++ TLS_ROOT_REQ(cacertnewreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 1, 2); ++ TLS_CERT_REQ(servercertnewreq, cacertnewreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ TLS_CERT_REQ(servercertnew1req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 1, 2); ++ TLS_CERT_REQ(clientcertnew1req, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 1, 2); ++ ++ DO_CTX_TEST(true, cacertnewreq, servercertnewreq, true); ++ DO_CTX_TEST(true, cacertreq, servercertnew1req, true); ++ DO_CTX_TEST(false, cacertreq, clientcertnew1req, true); ++ ++ testTLSDiscardCert(&cacertreq); ++ testTLSDiscardCert(&cacert1req); ++ testTLSDiscardCert(&cacert2req); ++ testTLSDiscardCert(&cacert3req); ++ testTLSDiscardCert(&cacert4req); ++ testTLSDiscardCert(&cacert5req); ++ testTLSDiscardCert(&cacert6req); ++ ++ testTLSDiscardCert(&servercertreq); ++ testTLSDiscardCert(&servercert1req); ++ testTLSDiscardCert(&servercert2req); ++ testTLSDiscardCert(&servercert3req); ++ testTLSDiscardCert(&servercert4req); ++ testTLSDiscardCert(&servercert5req); ++ testTLSDiscardCert(&servercert6req); ++ testTLSDiscardCert(&servercert7req); ++ testTLSDiscardCert(&servercert8req); ++ testTLSDiscardCert(&servercert9req); ++ testTLSDiscardCert(&servercert10req); ++ testTLSDiscardCert(&servercert11req); ++ testTLSDiscardCert(&servercert12req); ++ testTLSDiscardCert(&servercert13req); ++ testTLSDiscardCert(&servercert14req); ++ testTLSDiscardCert(&servercert15req); ++ testTLSDiscardCert(&servercert16req); ++ ++ testTLSDiscardCert(&clientcertreq); ++ testTLSDiscardCert(&clientcert1req); ++ testTLSDiscardCert(&clientcert2req); ++ testTLSDiscardCert(&clientcert3req); ++ testTLSDiscardCert(&clientcert4req); ++ testTLSDiscardCert(&clientcert5req); ++ testTLSDiscardCert(&clientcert6req); ++ testTLSDiscardCert(&clientcert7req); ++ testTLSDiscardCert(&clientcert8req); ++ testTLSDiscardCert(&clientcert9req); ++ testTLSDiscardCert(&clientcert10req); ++ ++ testTLSDiscardCert(&cacertexpreq); ++ testTLSDiscardCert(&servercertexpreq); ++ testTLSDiscardCert(&servercertexp1req); ++ testTLSDiscardCert(&clientcertexp1req); ++ ++ testTLSDiscardCert(&cacertnewreq); ++ testTLSDiscardCert(&servercertnewreq); ++ testTLSDiscardCert(&servercertnew1req); ++ testTLSDiscardCert(&clientcertnew1req); + + testTLSCleanup(); + +diff --git a/tests/virnettlshelpers.c b/tests/virnettlshelpers.c +index 96b2f6e..8236e82 100644 +--- a/tests/virnettlshelpers.c ++++ b/tests/virnettlshelpers.c +@@ -152,7 +152,8 @@ static void testTLSDerEncode(ASN1_TYPE src, + * TLS certificate code + */ + void +-testTLSGenerateCert(struct testTLSCertReq *req) ++testTLSGenerateCert(struct testTLSCertReq *req, ++ gnutls_x509_crt_t ca) + { + gnutls_x509_crt_t crt; + int err; +@@ -379,10 +380,10 @@ testTLSGenerateCert(struct testTLSCertReq *req) + + + /* +- * If no 'cart' is set then we are self signing +- * the cert. This is done for CA certs ++ * If no 'ca' is set then we are self signing ++ * the cert. This is done for the root CA certs + */ +- if ((err = gnutls_x509_crt_sign(crt, req->cacrt ? req->cacrt : crt, privkey) < 0)) { ++ if ((err = gnutls_x509_crt_sign(crt, ca ? ca : crt, privkey) < 0)) { + VIR_WARN("Failed to sign certificate %s", gnutls_strerror(err)); + abort(); + } +diff --git a/tests/virnettlshelpers.h b/tests/virnettlshelpers.h +index 3ea9978..50a4ba1 100644 +--- a/tests/virnettlshelpers.h ++++ b/tests/virnettlshelpers.h +@@ -36,7 +36,6 @@ extern const char *keyfile; + */ + struct testTLSCertReq { + gnutls_x509_crt_t crt; +- gnutls_x509_crt_t cacrt; /* If not set, then the cert will be self-signed */ + + const char *filename; + +@@ -70,7 +69,8 @@ struct testTLSCertReq { + int expire_offset; + }; + +-void testTLSGenerateCert(struct testTLSCertReq *req); ++void testTLSGenerateCert(struct testTLSCertReq *req, ++ gnutls_x509_crt_t ca); + void testTLSDiscardCert(struct testTLSCertReq *req); + + void testTLSInit(void); +diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c +index 9c5b3ca..370ba52 100644 +--- a/tests/virnettlssessiontest.c ++++ b/tests/virnettlssessiontest.c +@@ -100,20 +100,6 @@ static int testTLSSessionInit(const void *opaque) + ignore_value(virSetNonBlock(channel[1])); + + +- /* Generate all the certs we need for this test */ +- testTLSGenerateCert(&data->careq); +- data->serverreq.cacrt = data->careq.crt; +- testTLSGenerateCert(&data->serverreq); +- +- if (data->othercareq.filename) { +- testTLSGenerateCert(&data->othercareq); +- data->clientreq.cacrt = data->othercareq.crt; +- } else { +- data->clientreq.cacrt = data->careq.crt; +- } +- testTLSGenerateCert(&data->clientreq); +- +- + /* We skip initial sanity checks here because we + * want to make sure that problems are being + * detected at the TLS session validation stage +@@ -243,12 +229,6 @@ cleanup: + virObjectUnref(serverSess); + virObjectUnref(clientSess); + +- testTLSDiscardCert(&data->careq); +- if (data->othercareq.filename) +- testTLSDiscardCert(&data->othercareq); +- testTLSDiscardCert(&data->clientreq); +- testTLSDiscardCert(&data->serverreq); +- + VIR_FORCE_CLOSE(channel[0]); + VIR_FORCE_CLOSE(channel[1]); + return ret; +@@ -275,7 +255,8 @@ mymain(void) + data.expectClientFail = _expectClientFail; \ + data.hostname = _hostname; \ + data.wildcards = _wildcards; \ +- if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \ ++ if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \ ++ 1, testTLSSessionInit, &data) < 0) \ + ret = -1; \ + } while (0) + +@@ -292,68 +273,87 @@ mymain(void) + data.expectClientFail = _expectClientFail; \ + data.hostname = _hostname; \ + data.wildcards = _wildcards; \ +- if (virtTestRun("TLS Session", 1, testTLSSessionInit, &data) < 0) \ ++ if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \ ++ 1, testTLSSessionInit, &data) < 0) \ + ret = -1; \ + } while (0) + ++# define TLS_CERT_REQ(varname, cavarname, \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ ++ static struct testTLSCertReq varname = { \ ++ NULL, #varname ".pem", \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \ ++ }; \ ++ testTLSGenerateCert(&varname, cavarname.crt) ++ ++# define TLS_ROOT_REQ(varname, \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ ++ static struct testTLSCertReq varname = { \ ++ NULL, #varname ".pem", \ ++ co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ ++ kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \ ++ }; \ ++ testTLSGenerateCert(&varname, NULL) ++ + /* A perfect CA, perfect client & perfect server */ + + /* Basic:CA:critical */ +- static struct testTLSCertReq cacertreq = { +- NULL, NULL, "cacert.pem", "UK", +- "libvirt CA", NULL, NULL, NULL, NULL, +- true, true, true, +- true, true, GNUTLS_KEY_KEY_CERT_SIGN, +- false, false, NULL, NULL, +- 0, 0, +- }; +- static struct testTLSCertReq cacert1req = { +- NULL, NULL, "cacert1.pem", "UK", +- "libvirt CA 1", NULL, NULL, NULL, NULL, +- true, true, true, +- false, false, 0, +- false, false, NULL, NULL, +- 0, 0, +- }; +- static struct testTLSCertReq servercertreq = { +- NULL, NULL, "servercert.pem", "UK", +- "libvirt.org", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; +- static struct testTLSCertReq clientcertreq = { +- NULL, NULL, "clientcert.pem", "UK", +- "libvirt", NULL, NULL, NULL, NULL, +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, +- 0, 0, +- }; ++ TLS_ROOT_REQ(cacertreq, ++ "UK", "libvirt CA", NULL, NULL, NULL, NULL, ++ true, true, true, ++ true, true, GNUTLS_KEY_KEY_CERT_SIGN, ++ false, false, NULL, NULL, ++ 0, 0); ++ ++ TLS_ROOT_REQ(altcacertreq, ++ "UK", "libvirt CA 1", NULL, NULL, NULL, NULL, ++ true, true, true, ++ false, false, 0, ++ false, false, NULL, NULL, ++ 0, 0); ++ ++ TLS_CERT_REQ(servercertreq, cacertreq, ++ "UK", "libvirt.org", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); ++ TLS_CERT_REQ(clientcertreq, cacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, 0); ++ ++ TLS_CERT_REQ(clientcertaltreq, altcacertreq, ++ "UK", "libvirt", NULL, NULL, NULL, NULL, ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, ++ 0, 0); + + DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL); +- DO_SESS_TEST_EXT(cacertreq, cacert1req, servercertreq, clientcertreq, true, true, "libvirt.org", NULL); ++ DO_SESS_TEST_EXT(cacertreq, altcacertreq, servercertreq, clientcertaltreq, true, true, "libvirt.org", NULL); ++ + + /* When an altname is set, the CN is ignored, so it must be duplicated + * as an altname for it to match */ +- static struct testTLSCertReq servercertalt1req = { +- NULL, NULL, "servercert.pem", "UK", +- "libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf", +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercertalt1req, cacertreq, ++ "UK", "libvirt.org", "www.libvirt.org", "libvirt.org", "192.168.122.1", "fec0::dead:beaf", ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + /* This intentionally doesn't replicate */ +- static struct testTLSCertReq servercertalt2req = { +- NULL, NULL, "servercert.pem", "UK", +- "libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf", +- true, true, false, +- true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, +- true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, +- 0, 0, +- }; ++ TLS_CERT_REQ(servercertalt2req, cacertreq, ++ "UK", "libvirt.org", "www.libvirt.org", "wiki.libvirt.org", "192.168.122.1", "fec0::dead:beaf", ++ true, true, false, ++ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, ++ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, ++ 0, 0); + + DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL); + DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL); +@@ -396,6 +396,16 @@ mymain(void) + DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5); + DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6); + ++ testTLSDiscardCert(&clientcertreq); ++ testTLSDiscardCert(&clientcertaltreq); ++ ++ testTLSDiscardCert(&servercertreq); ++ testTLSDiscardCert(&servercertalt1req); ++ testTLSDiscardCert(&servercertalt2req); ++ ++ testTLSDiscardCert(&cacertreq); ++ testTLSDiscardCert(&altcacertreq); ++ + testTLSCleanup(); + + return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Avoid-reporting-an-error-if-veth-device-is-already-deleted.patch b/SOURCES/libvirt-Avoid-reporting-an-error-if-veth-device-is-already-deleted.patch new file mode 100644 index 0000000..e808b32 --- /dev/null +++ b/SOURCES/libvirt-Avoid-reporting-an-error-if-veth-device-is-already-deleted.patch @@ -0,0 +1,68 @@ +From 97edaf4f3dc5af717f88e41577a1cda77982f4c1 Mon Sep 17 00:00:00 2001 +Message-Id: <97edaf4f3dc5af717f88e41577a1cda77982f4c1.1381871411.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Mon, 7 Oct 2013 17:17:28 +0100 +Subject: [PATCH] Avoid reporting an error if veth device is already deleted + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1014604 + +The kernel automatically destroys veth devices when cleaning +up the container network namespace. During normal shutdown, it +is thus likely that the attempt to run 'ip link del vethN' +will fail. If it fails, check if the device exists, and avoid +reporting an error if it has gone. This switches to use the +virCommand APIs instead of virRun too. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 10caf94ddc568d36561d89ca28fe0c58154a50f9) +Signed-off-by: Jiri Denemark +--- + po/POTFILES.in | 1 + + src/util/virnetdevveth.c | 17 ++++++++++++++--- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 884b70a..8afd015 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -168,6 +168,7 @@ src/util/virnetdevbridge.c + src/util/virnetdevmacvlan.c + src/util/virnetdevopenvswitch.c + src/util/virnetdevtap.c ++src/util/virnetdevveth.c + src/util/virnetdevvportprofile.c + src/util/virnetlink.c + src/util/virnodesuspend.c +diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c +index 039767f..c0d32c4 100644 +--- a/src/util/virnetdevveth.c ++++ b/src/util/virnetdevveth.c +@@ -161,9 +161,20 @@ cleanup: + */ + int virNetDevVethDelete(const char *veth) + { +- const char *argv[] = {"ip", "link", "del", veth, NULL}; ++ virCommandPtr cmd = virCommandNewArgList("ip", "link", "del", veth, NULL); ++ int status; + +- VIR_DEBUG("veth: %s", veth); ++ if (virCommandRun(cmd, &status) < 0) ++ return -1; + +- return virRun(argv, NULL); ++ if (status != 0) { ++ if (!virNetDevExists(veth)) { ++ VIR_DEBUG("Device %s already deleted (by kernel namespace cleanup)", veth); ++ return 0; ++ } ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Failed to delete veth device %s"), veth); ++ return -1; ++ } ++ return 0; + } +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Block-all-use-of-getenv-with-syntax-check.patch b/SOURCES/libvirt-Block-all-use-of-getenv-with-syntax-check.patch new file mode 100644 index 0000000..9895c94 --- /dev/null +++ b/SOURCES/libvirt-Block-all-use-of-getenv-with-syntax-check.patch @@ -0,0 +1,70 @@ +From a8692d25ea7457443ad49dc9187ca54d7a8faa55 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Wed, 30 Oct 2013 17:01:52 +0000 +Subject: [PATCH] Block all use of getenv with syntax-check + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1015247 + +The use of getenv is typically insecure, and we want people +to use our wrappers, to force them to think about setuid +needs. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 71b21f12bece1127b28b404f11f57b4c2d48983a) +Signed-off-by: Jiri Denemark +--- + cfg.mk | 8 ++++++++ + src/util/virutil.c | 4 ++-- + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/cfg.mk b/cfg.mk +index aa2e1a1..f2cd411 100644 +--- a/cfg.mk ++++ b/cfg.mk +@@ -836,6 +836,11 @@ sc_prohibit_unbounded_arrays_in_rpc: + halt='Arrays in XDR must have a upper limit set for ' \ + $(_sc_search_regexp) + ++sc_prohibit_getenv: ++ @prohibit='\b(secure_)?getenv *\(' \ ++ exclude='exempt from syntax-check' \ ++ halt='Use virGetEnv{Allow,Block}SUID instead of getenv' \ ++ $(_sc_search_regexp) + + # We don't use this feature of maint.mk. + prev_version_file = /dev/null +@@ -1005,3 +1010,6 @@ exclude_file_name_regexp--sc_prohibit_include_public_headers_brackets = \ + + exclude_file_name_regexp--sc_prohibit_int_ijk = \ + ^(src/remote_protocol-structs|src/remote/remote_protocol.x|cfg.mk|include/)$ ++ ++exclude_file_name_regexp--sc_prohibit_getenv = \ ++ ^tests/.*\.[ch]$$ +diff --git a/src/util/virutil.c b/src/util/virutil.c +index 2b3cbeb..21827f2 100644 +--- a/src/util/virutil.c ++++ b/src/util/virutil.c +@@ -2108,7 +2108,7 @@ cleanup: + */ + const char *virGetEnvBlockSUID(const char *name) + { +- return secure_getenv(name); ++ return secure_getenv(name); /* exempt from syntax-check-rules */ + } + + +@@ -2122,7 +2122,7 @@ const char *virGetEnvBlockSUID(const char *name) + */ + const char *virGetEnvAllowSUID(const char *name) + { +- return getenv(name); ++ return getenv(name); /* exempt from syntax-check-rules */ + } + + +-- +1.8.4.2 + diff --git a/SOURCES/libvirt-Block-all-use-of-libvirt.so-in-setuid-programs.patch b/SOURCES/libvirt-Block-all-use-of-libvirt.so-in-setuid-programs.patch new file mode 100644 index 0000000..e6b1071 --- /dev/null +++ b/SOURCES/libvirt-Block-all-use-of-libvirt.so-in-setuid-programs.patch @@ -0,0 +1,43 @@ +From b019d146357887bcf45b85b251f568d54e1bafb1 Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Wed, 30 Oct 2013 17:01:57 +0000 +Subject: [PATCH] Block all use of libvirt.so in setuid programs + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1015247 + +Avoid people introducing security flaws in their apps by +forbidding the use of libvirt.so in setuid programs, with +a check in virInitialize. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 9cd6a57db6ea6762fbf85c59c379a27fa6e7fd2e) +Signed-off-by: Jiri Denemark +--- + src/libvirt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/libvirt.c b/src/libvirt.c +index 54c90ec..e008368 100644 +--- a/src/libvirt.c ++++ b/src/libvirt.c +@@ -409,6 +409,14 @@ virGlobalInit(void) + virErrorInitialize() < 0) + goto error; + ++#ifndef IN_VIRT_LOGIN_SHELL ++ if (virIsSUID()) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("libvirt.so is not safe to use from setuid programs")); ++ goto error; ++ } ++#endif ++ + #ifdef WITH_GNUTLS_GCRYPT + /* + * This sequence of API calls it copied exactly from +-- +1.8.4.2 + diff --git a/SOURCES/libvirt-Change-data-passed-into-TLS-test-cases.patch b/SOURCES/libvirt-Change-data-passed-into-TLS-test-cases.patch new file mode 100644 index 0000000..bf0cd79 --- /dev/null +++ b/SOURCES/libvirt-Change-data-passed-into-TLS-test-cases.patch @@ -0,0 +1,453 @@ +From 252f0445c26644a711dc2c41ee2fcebe42eac742 Mon Sep 17 00:00:00 2001 +Message-Id: <252f0445c26644a711dc2c41ee2fcebe42eac742.1377873637.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Tue, 13 Aug 2013 11:32:47 +0100 +Subject: [PATCH] Change data passed into TLS test cases + +For https://bugzilla.redhat.com/show_bug.cgi?id=994158 + +Currently a 'struct testTLSCertReq' instance is passed into +the TLS test cases. This is not flexible enough to cope with +certificate chains, where one file now corresponds to multiple +certificates. Change the test cases so that we pass in filenames +instead. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit b93bd78ed36570c1afe594182df927d94ea6ebaa) +--- + tests/virnettlscontexttest.c | 96 +++++++++++++++++++++--------------------- + tests/virnettlssessiontest.c | 99 ++++++++++++++++++++++++-------------------- + 2 files changed, 102 insertions(+), 93 deletions(-) + +diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c +index 4211a74..3012c4a 100644 +--- a/tests/virnettlscontexttest.c ++++ b/tests/virnettlscontexttest.c +@@ -42,8 +42,8 @@ + + struct testTLSContextData { + bool isServer; +- struct testTLSCertReq careq; +- struct testTLSCertReq certreq; ++ const char *cacrt; ++ const char *crt; + bool expectFail; + }; + +@@ -63,17 +63,17 @@ static int testTLSContextInit(const void *opaque) + int ret = -1; + + if (data->isServer) { +- ctxt = virNetTLSContextNewServer(data->careq.filename, ++ ctxt = virNetTLSContextNewServer(data->cacrt, + NULL, +- data->certreq.filename, ++ data->crt, + keyfile, + NULL, + true, + true); + } else { +- ctxt = virNetTLSContextNewClient(data->careq.filename, ++ ctxt = virNetTLSContextNewClient(data->cacrt, + NULL, +- data->certreq.filename, ++ data->crt, + keyfile, + true, + true); +@@ -82,14 +82,14 @@ static int testTLSContextInit(const void *opaque) + if (ctxt) { + if (data->expectFail) { + VIR_WARN("Expected failure %s against %s", +- data->careq.filename, data->certreq.filename); ++ data->cacrt, data->crt); + goto cleanup; + } + } else { + virErrorPtr err = virGetLastError(); + if (!data->expectFail) { + VIR_WARN("Unexpected failure %s against %s", +- data->careq.filename, data->certreq.filename); ++ data->cacrt, data->crt); + goto cleanup; + } + VIR_DEBUG("Got error %s", err ? err->message : ""); +@@ -111,14 +111,14 @@ mymain(void) + + testTLSInit(); + +-# define DO_CTX_TEST(_isServer, _caReq, _certReq, _expectFail) \ ++# define DO_CTX_TEST(_isServer, _caCrt, _crt, _expectFail) \ + do { \ + static struct testTLSContextData data; \ + data.isServer = _isServer; \ +- data.careq = _caReq; \ +- data.certreq = _certReq; \ ++ data.cacrt = _caCrt; \ ++ data.crt = _crt; \ + data.expectFail = _expectFail; \ +- if (virtTestRun("TLS Context " #_caReq " + " #_certReq, 1, \ ++ if (virtTestRun("TLS Context " #_caCrt " + " #_crt, 1, \ + testTLSContextInit, &data) < 0) \ + ret = -1; \ + } while (0) +@@ -127,7 +127,7 @@ mymain(void) + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ + static struct testTLSCertReq varname = { \ +- NULL, #varname ".pem", \ ++ NULL, #varname "-ctx.pem", \ + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \ + }; \ +@@ -137,7 +137,7 @@ mymain(void) + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ + static struct testTLSCertReq varname = { \ +- NULL, #varname ".pem", \ ++ NULL, #varname "-ctx.pem", \ + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo \ + }; \ +@@ -167,8 +167,8 @@ mymain(void) + true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, + 0, 0); + +- DO_CTX_TEST(true, cacertreq, servercertreq, false); +- DO_CTX_TEST(false, cacertreq, clientcertreq, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercertreq.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcertreq.filename, false); + + + /* Some other CAs which are good */ +@@ -215,9 +215,9 @@ mymain(void) + true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, + 0, 0); + +- DO_CTX_TEST(true, cacert1req, servercert1req, false); +- DO_CTX_TEST(true, cacert2req, servercert2req, false); +- DO_CTX_TEST(true, cacert3req, servercert3req, false); ++ DO_CTX_TEST(true, cacert1req.filename, servercert1req.filename, false); ++ DO_CTX_TEST(true, cacert2req.filename, servercert2req.filename, false); ++ DO_CTX_TEST(true, cacert3req.filename, servercert3req.filename, false); + + /* Now some bad certs */ + +@@ -266,9 +266,9 @@ mymain(void) + * be rejected. GNUTLS < 3 does not reject it and + * we don't anticipate them changing this behaviour + */ +- DO_CTX_TEST(true, cacert4req, servercert4req, GNUTLS_VERSION_MAJOR >= 3); +- DO_CTX_TEST(true, cacert5req, servercert5req, true); +- DO_CTX_TEST(true, cacert6req, servercert6req, true); ++ DO_CTX_TEST(true, cacert4req.filename, servercert4req.filename, GNUTLS_VERSION_MAJOR >= 3); ++ DO_CTX_TEST(true, cacert5req.filename, servercert5req.filename, true); ++ DO_CTX_TEST(true, cacert6req.filename, servercert6req.filename, true); + + + /* Various good servers */ +@@ -322,13 +322,13 @@ mymain(void) + true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, + 0, 0); + +- DO_CTX_TEST(true, cacertreq, servercert7req, false); +- DO_CTX_TEST(true, cacertreq, servercert8req, false); +- DO_CTX_TEST(true, cacertreq, servercert9req, false); +- DO_CTX_TEST(true, cacertreq, servercert10req, false); +- DO_CTX_TEST(true, cacertreq, servercert11req, false); +- DO_CTX_TEST(true, cacertreq, servercert12req, false); +- DO_CTX_TEST(true, cacertreq, servercert13req, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert7req.filename, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert8req.filename, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert9req.filename, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert10req.filename, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert11req.filename, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert12req.filename, false); ++ DO_CTX_TEST(true, cacertreq.filename, servercert13req.filename, false); + /* Bad servers */ + + /* usage:cert-sign:critical */ +@@ -353,9 +353,9 @@ mymain(void) + false, false, NULL, NULL, + 0, 0); + +- DO_CTX_TEST(true, cacertreq, servercert14req, true); +- DO_CTX_TEST(true, cacertreq, servercert15req, true); +- DO_CTX_TEST(true, cacertreq, servercert16req, true); ++ DO_CTX_TEST(true, cacertreq.filename, servercert14req.filename, true); ++ DO_CTX_TEST(true, cacertreq.filename, servercert15req.filename, true); ++ DO_CTX_TEST(true, cacertreq.filename, servercert16req.filename, true); + + + +@@ -410,13 +410,13 @@ mymain(void) + true, false, GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER, + 0, 0); + +- DO_CTX_TEST(false, cacertreq, clientcert1req, false); +- DO_CTX_TEST(false, cacertreq, clientcert2req, false); +- DO_CTX_TEST(false, cacertreq, clientcert3req, false); +- DO_CTX_TEST(false, cacertreq, clientcert4req, false); +- DO_CTX_TEST(false, cacertreq, clientcert5req, false); +- DO_CTX_TEST(false, cacertreq, clientcert6req, false); +- DO_CTX_TEST(false, cacertreq, clientcert7req, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert1req.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert2req.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert3req.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert4req.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert5req.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert6req.filename, false); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert7req.filename, false); + /* Bad clients */ + + /* usage:cert-sign:critical */ +@@ -441,9 +441,9 @@ mymain(void) + false, false, NULL, NULL, + 0, 0); + +- DO_CTX_TEST(false, cacertreq, clientcert8req, true); +- DO_CTX_TEST(false, cacertreq, clientcert9req, true); +- DO_CTX_TEST(false, cacertreq, clientcert10req, true); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert8req.filename, true); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert9req.filename, true); ++ DO_CTX_TEST(false, cacertreq.filename, clientcert10req.filename, true); + + + +@@ -474,9 +474,9 @@ mymain(void) + true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, + 0, -1); + +- DO_CTX_TEST(true, cacertexpreq, servercertexpreq, true); +- DO_CTX_TEST(true, cacertreq, servercertexp1req, true); +- DO_CTX_TEST(false, cacertreq, clientcertexp1req, true); ++ DO_CTX_TEST(true, cacertexpreq.filename, servercertexpreq.filename, true); ++ DO_CTX_TEST(true, cacertreq.filename, servercertexp1req.filename, true); ++ DO_CTX_TEST(false, cacertreq.filename, clientcertexp1req.filename, true); + + + /* Not activated stuff */ +@@ -506,9 +506,9 @@ mymain(void) + true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, + 1, 2); + +- DO_CTX_TEST(true, cacertnewreq, servercertnewreq, true); +- DO_CTX_TEST(true, cacertreq, servercertnew1req, true); +- DO_CTX_TEST(false, cacertreq, clientcertnew1req, true); ++ DO_CTX_TEST(true, cacertnewreq.filename, servercertnewreq.filename, true); ++ DO_CTX_TEST(true, cacertreq.filename, servercertnew1req.filename, true); ++ DO_CTX_TEST(false, cacertreq.filename, clientcertnew1req.filename, true); + + testTLSDiscardCert(&cacertreq); + testTLSDiscardCert(&cacert1req); +diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c +index 370ba52..8636fc8 100644 +--- a/tests/virnettlssessiontest.c ++++ b/tests/virnettlssessiontest.c +@@ -39,10 +39,10 @@ + # define VIR_FROM_THIS VIR_FROM_RPC + + struct testTLSSessionData { +- struct testTLSCertReq careq; +- struct testTLSCertReq othercareq; +- struct testTLSCertReq serverreq; +- struct testTLSCertReq clientreq; ++ const char *servercacrt; ++ const char *clientcacrt; ++ const char *servercrt; ++ const char *clientcrt; + bool expectServerFail; + bool expectClientFail; + const char *hostname; +@@ -104,32 +104,29 @@ static int testTLSSessionInit(const void *opaque) + * want to make sure that problems are being + * detected at the TLS session validation stage + */ +- serverCtxt = virNetTLSContextNewServer(data->careq.filename, ++ serverCtxt = virNetTLSContextNewServer(data->servercacrt, + NULL, +- data->serverreq.filename, ++ data->servercrt, + keyfile, + data->wildcards, + false, + true); + +- clientCtxt = virNetTLSContextNewClient(data->othercareq.filename ? +- data->othercareq.filename : +- data->careq.filename, ++ clientCtxt = virNetTLSContextNewClient(data->clientcacrt, + NULL, +- data->clientreq.filename, ++ data->clientcrt, + keyfile, + false, + true); + + if (!serverCtxt) { + VIR_WARN("Unexpected failure loading %s against %s", +- data->careq.filename, data->serverreq.filename); ++ data->servercacrt, data->servercrt); + goto cleanup; + } + if (!clientCtxt) { + VIR_WARN("Unexpected failure loading %s against %s", +- data->othercareq.filename ? data->othercareq.filename : +- data->careq.filename, data->clientreq.filename); ++ data->clientcacrt, data->clientcrt); + goto cleanup; + } + +@@ -140,13 +137,12 @@ static int testTLSSessionInit(const void *opaque) + + if (!serverSess) { + VIR_WARN("Unexpected failure using %s against %s", +- data->careq.filename, data->serverreq.filename); ++ data->servercacrt, data->servercrt); + goto cleanup; + } + if (!clientSess) { + VIR_WARN("Unexpected failure using %s against %s", +- data->othercareq.filename ? data->othercareq.filename : +- data->careq.filename, data->clientreq.filename); ++ data->clientcacrt, data->clientcrt); + goto cleanup; + } + +@@ -242,38 +238,37 @@ mymain(void) + + testTLSInit(); + +-# define DO_SESS_TEST(_caReq, _serverReq, _clientReq, _expectServerFail,\ ++# define DO_SESS_TEST(_caCrt, _serverCrt, _clientCrt, _expectServerFail, \ + _expectClientFail, _hostname, _wildcards) \ + do { \ + static struct testTLSSessionData data; \ +- static struct testTLSCertReq other; \ +- data.careq = _caReq; \ +- data.othercareq = other; \ +- data.serverreq = _serverReq; \ +- data.clientreq = _clientReq; \ ++ data.servercacrt = _caCrt; \ ++ data.clientcacrt = _caCrt; \ ++ data.servercrt = _serverCrt; \ ++ data.clientcrt = _clientCrt; \ + data.expectServerFail = _expectServerFail; \ + data.expectClientFail = _expectClientFail; \ + data.hostname = _hostname; \ + data.wildcards = _wildcards; \ +- if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \ ++ if (virtTestRun("TLS Session " #_serverCrt " + " #_clientCrt, \ + 1, testTLSSessionInit, &data) < 0) \ + ret = -1; \ + } while (0) + +-# define DO_SESS_TEST_EXT(_caReq, _othercaReq, _serverReq, _clientReq, \ ++# define DO_SESS_TEST_EXT(_serverCaCrt, _clientCaCrt, _serverCrt, _clientCrt, \ + _expectServerFail, _expectClientFail, \ + _hostname, _wildcards) \ + do { \ + static struct testTLSSessionData data; \ +- data.careq = _caReq; \ +- data.othercareq = _othercaReq; \ +- data.serverreq = _serverReq; \ +- data.clientreq = _clientReq; \ ++ data.servercacrt = _serverCaCrt; \ ++ data.clientcacrt = _clientCaCrt; \ ++ data.servercrt = _serverCrt; \ ++ data.clientcrt = _clientCrt; \ + data.expectServerFail = _expectServerFail; \ + data.expectClientFail = _expectClientFail; \ + data.hostname = _hostname; \ + data.wildcards = _wildcards; \ +- if (virtTestRun("TLS Session " #_serverReq " + " #_clientReq, \ ++ if (virtTestRun("TLS Session " #_serverCrt " + " #_clientCrt, \ + 1, testTLSSessionInit, &data) < 0) \ + ret = -1; \ + } while (0) +@@ -282,7 +277,7 @@ mymain(void) + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ + static struct testTLSCertReq varname = { \ +- NULL, #varname ".pem", \ ++ NULL, #varname "-sess.pem", \ + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \ + }; \ +@@ -292,7 +287,7 @@ mymain(void) + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, eo) \ + static struct testTLSCertReq varname = { \ +- NULL, #varname ".pem", \ ++ NULL, #varname "-sess.pem", \ + co, cn, an1, an2, ia1, ia2, bce, bcc, bci, \ + kue, kuc, kuv, kpe, kpc, kpo1, kpo2, so, so \ + }; \ +@@ -335,8 +330,10 @@ mymain(void) + true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL, + 0, 0); + +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", NULL); +- DO_SESS_TEST_EXT(cacertreq, altcacertreq, servercertreq, clientcertaltreq, true, true, "libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ false, false, "libvirt.org", NULL); ++ DO_SESS_TEST_EXT(cacertreq.filename, altcacertreq.filename, servercertreq.filename, ++ clientcertaltreq.filename, true, true, "libvirt.org", NULL); + + + /* When an altname is set, the CN is ignored, so it must be duplicated +@@ -355,13 +352,19 @@ mymain(void) + true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL, + 0, 0); + +- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "libvirt.org", NULL); +- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, false, "www.libvirt.org", NULL); +- DO_SESS_TEST(cacertreq, servercertalt1req, clientcertreq, false, true, "wiki.libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertalt1req.filename, clientcertreq.filename, ++ false, false, "libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertalt1req.filename, clientcertreq.filename, ++ false, false, "www.libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertalt1req.filename, clientcertreq.filename, ++ false, true, "wiki.libvirt.org", NULL); + +- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, true, "libvirt.org", NULL); +- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "www.libvirt.org", NULL); +- DO_SESS_TEST(cacertreq, servercertalt2req, clientcertreq, false, false, "wiki.libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertalt2req.filename, clientcertreq.filename, ++ false, true, "libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertalt2req.filename, clientcertreq.filename, ++ false, false, "www.libvirt.org", NULL); ++ DO_SESS_TEST(cacertreq.filename, servercertalt2req.filename, clientcertreq.filename, ++ false, false, "wiki.libvirt.org", NULL); + + const char *const wildcards1[] = { + "C=UK,CN=dogfood", +@@ -389,12 +392,18 @@ mymain(void) + NULL, + }; + +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards1); +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards2); +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards3); +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, true, false, "libvirt.org", wildcards4); +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards5); +- DO_SESS_TEST(cacertreq, servercertreq, clientcertreq, false, false, "libvirt.org", wildcards6); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ true, false, "libvirt.org", wildcards1); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ false, false, "libvirt.org", wildcards2); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ false, false, "libvirt.org", wildcards3); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ true, false, "libvirt.org", wildcards4); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ false, false, "libvirt.org", wildcards5); ++ DO_SESS_TEST(cacertreq.filename, servercertreq.filename, clientcertreq.filename, ++ false, false, "libvirt.org", wildcards6); + + testTLSDiscardCert(&clientcertreq); + testTLSDiscardCert(&clientcertaltreq); +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Change-way-we-fake-dbus-method-calls.patch b/SOURCES/libvirt-Change-way-we-fake-dbus-method-calls.patch new file mode 100644 index 0000000..75631e5 --- /dev/null +++ b/SOURCES/libvirt-Change-way-we-fake-dbus-method-calls.patch @@ -0,0 +1,70 @@ +From 47e18ab1d1b8a343e7d29f1f3884a040a18147c6 Mon Sep 17 00:00:00 2001 +Message-Id: <47e18ab1d1b8a343e7d29f1f3884a040a18147c6.1381871412.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Mon, 14 Oct 2013 16:45:14 +0100 +Subject: [PATCH] Change way we fake dbus method calls + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1018730 + +Ubuntu libdbus.so links with -Bsymbolic-functions, which means +that we can only LD_PRELOAD functions that we directly call. +Functions which libdbus.so calls internally can not be replaced. +Thus we cannot use dbus_message_new_error or dbus_message_new_method_return + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit dbd2bc8c8bdd927f3e9132afc8579dbaa1de91de) +Signed-off-by: Jiri Denemark +--- + tests/virsystemdmock.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +diff --git a/tests/virsystemdmock.c b/tests/virsystemdmock.c +index ded52d2..5dbd33f 100644 +--- a/tests/virsystemdmock.c ++++ b/tests/virsystemdmock.c +@@ -65,22 +65,32 @@ dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message ATTRIBUTE_UNUSED, + } + + DBusMessage *dbus_connection_send_with_reply_and_block(DBusConnection *connection ATTRIBUTE_UNUSED, +- DBusMessage *message, ++ DBusMessage *message ATTRIBUTE_UNUSED, + int timeout_milliseconds ATTRIBUTE_UNUSED, + DBusError *error) + { + DBusMessage *reply = NULL; + +- if (getenv("FAIL_BAD_SERVICE")) +- reply = dbus_message_new_error(message, +- "org.freedesktop.systemd.badthing", +- "Something went wrong creating the machine"); +- else if (getenv("FAIL_NO_SERVICE")) ++ if (getenv("FAIL_BAD_SERVICE")) { ++ DBusMessageIter iter; ++ const char *error_message = "Something went wrong creating the machine"; ++ if (!(reply = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR))) ++ return NULL; ++ dbus_message_set_error_name(reply, "org.freedesktop.systemd.badthing"); ++ dbus_message_iter_init_append(reply, &iter); ++ if (!dbus_message_iter_append_basic(&iter, ++ DBUS_TYPE_STRING, ++ &error_message)) { ++ dbus_message_unref(reply); ++ return NULL; ++ } ++ } else if (getenv("FAIL_NO_SERVICE")) { + dbus_set_error(error, + "org.freedesktop.DBus.Error.ServiceUnknown", + "%s", "The name org.freedesktop.machine1 was not provided by any .service files"); +- else +- reply = dbus_message_new_method_return(message); ++ } else { ++ reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); ++ } + + return reply; + } +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Close-all-non-stdio-FDs-in-virt-login-shell.patch b/SOURCES/libvirt-Close-all-non-stdio-FDs-in-virt-login-shell.patch new file mode 100644 index 0000000..45fea01 --- /dev/null +++ b/SOURCES/libvirt-Close-all-non-stdio-FDs-in-virt-login-shell.patch @@ -0,0 +1,46 @@ +From e93e8db21dfe3d62aa3f4684c3729de51b729feb Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Daniel P. Berrange" +Date: Wed, 30 Oct 2013 17:01:43 +0000 +Subject: [PATCH] Close all non-stdio FDs in virt-login-shell + +CVE-2013-4400 + +We don't want to inherit any FDs in the new namespace +except for the stdio FDs. Explicitly close them all, +just in case some do not have the close-on-exec flag +set. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit b7fcc799ad5d8f3e55b89b94e599903e3c092467) +Signed-off-by: Jiri Denemark +--- + tools/virt-login-shell.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c +index 1157cd0..c2c9947 100644 +--- a/tools/virt-login-shell.c ++++ b/tools/virt-login-shell.c +@@ -308,6 +308,18 @@ main(int argc, char **argv) + if (cpid == 0) { + pid_t ccpid; + ++ int openmax = sysconf(_SC_OPEN_MAX); ++ int fd; ++ if (openmax < 0) { ++ virReportSystemError(errno, "%s", ++ _("sysconf(_SC_OPEN_MAX) failed")); ++ return EXIT_FAILURE; ++ } ++ for (fd = 3; fd < openmax; fd++) { ++ int tmpfd = fd; ++ VIR_MASS_CLOSE(tmpfd); ++ } ++ + /* Fork once because we don't want to affect + * virt-login-shell's namespace itself + */ +-- +1.8.4.2 + diff --git a/SOURCES/libvirt-Convert-uuid-to-a-string-before-printing-it.patch b/SOURCES/libvirt-Convert-uuid-to-a-string-before-printing-it.patch new file mode 100644 index 0000000..e5a8a2b --- /dev/null +++ b/SOURCES/libvirt-Convert-uuid-to-a-string-before-printing-it.patch @@ -0,0 +1,124 @@ +From 8604ebe89c5267f34ee414fa62b69c5a5af3f62d Mon Sep 17 00:00:00 2001 +Message-Id: <8604ebe89c5267f34ee414fa62b69c5a5af3f62d.1381871413.git.jdenemar@redhat.com> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Tue, 15 Oct 2013 12:36:38 +0200 +Subject: [PATCH] Convert uuid to a string before printing it + +Introduced by 1fa7946. + +https://bugzilla.redhat.com/show_bug.cgi?id=1019023 +(cherry picked from commit 15fac93b951eb67553ca64443c740c1b975696a9) + +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_command.c | 6 ++++-- + src/storage/storage_backend_iscsi.c | 8 ++++++-- + src/storage/storage_backend_rbd.c | 4 ++-- + 3 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index dcce432..d455847 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -3113,11 +3113,13 @@ qemuGetSecretString(virConnectPtr conn, + size_t secret_size; + virSecretPtr sec = NULL; + char *secret = NULL; ++ char uuidStr[VIR_UUID_STRING_BUFLEN]; + + /* look up secret */ + switch (diskSecretType) { + case VIR_DOMAIN_DISK_SECRET_TYPE_UUID: + sec = virSecretLookupByUUID(conn, uuid); ++ virUUIDFormat(uuid, uuidStr); + break; + case VIR_DOMAIN_DISK_SECRET_TYPE_USAGE: + sec = virSecretLookupByUsage(conn, secretUsageType, usage); +@@ -3128,7 +3130,7 @@ qemuGetSecretString(virConnectPtr conn, + if (diskSecretType == VIR_DOMAIN_DISK_SECRET_TYPE_UUID) { + virReportError(VIR_ERR_NO_SECRET, + _("%s no secret matches uuid '%s'"), +- scheme, uuid); ++ scheme, uuidStr); + } else { + virReportError(VIR_ERR_NO_SECRET, + _("%s no secret matches usage value '%s'"), +@@ -3144,7 +3146,7 @@ qemuGetSecretString(virConnectPtr conn, + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get value of the secret for " + "username '%s' using uuid '%s'"), +- username, uuid); ++ username, uuidStr); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get value of the secret for " +diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c +index e71ea46..556c2cc 100644 +--- a/src/storage/storage_backend_iscsi.c ++++ b/src/storage/storage_backend_iscsi.c +@@ -44,6 +44,7 @@ + #include "virobject.h" + #include "virrandom.h" + #include "virstring.h" ++#include "viruuid.h" + + #define VIR_FROM_THIS VIR_FROM_STORAGE + +@@ -702,6 +703,7 @@ virStorageBackendISCSISetAuth(const char *portal, + unsigned char *secret_value = NULL; + virStoragePoolAuthChap chap; + int ret = -1; ++ char uuidStr[VIR_UUID_STRING_BUFLEN]; + + if (def->source.authType == VIR_STORAGE_POOL_AUTH_NONE) + return 0; +@@ -733,10 +735,11 @@ virStorageBackendISCSISetAuth(const char *portal, + VIR_SECRET_GET_VALUE_INTERNAL_CALL); + if (!secret_value) { + if (chap.secret.uuidUsable) { ++ virUUIDFormat(chap.secret.uuid, uuidStr); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get the value of the secret " + "for username %s using uuid '%s'"), +- chap.username, chap.secret.uuid); ++ chap.username, uuidStr); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get the value of the secret " +@@ -747,9 +750,10 @@ virStorageBackendISCSISetAuth(const char *portal, + } + } else { + if (chap.secret.uuidUsable) { ++ virUUIDFormat(chap.secret.uuid, uuidStr); + virReportError(VIR_ERR_NO_SECRET, + _("no secret matches uuid '%s'"), +- chap.secret.uuid); ++ uuidStr); + } else { + virReportError(VIR_ERR_NO_SECRET, + _("no secret matches usage value '%s'"), +diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c +index d9e1789..60b48c2 100644 +--- a/src/storage/storage_backend_rbd.c ++++ b/src/storage/storage_backend_rbd.c +@@ -94,7 +94,7 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr, + if (pool->def->source.auth.cephx.secret.uuidUsable) { + virReportError(VIR_ERR_NO_SECRET, + _("no secret matches uuid '%s'"), +- pool->def->source.auth.cephx.secret.uuid); ++ secretUuid); + } else { + virReportError(VIR_ERR_NO_SECRET, + _("no secret matches usage value '%s'"), +@@ -112,7 +112,7 @@ static int virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr *ptr, + _("could not get the value of the secret " + "for username '%s' using uuid '%s'"), + pool->def->source.auth.cephx.username, +- pool->def->source.auth.cephx.secret.uuid); ++ secretUuid); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get the value of the secret " +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Cope-with-races-while-killing-processes.patch b/SOURCES/libvirt-Cope-with-races-while-killing-processes.patch new file mode 100644 index 0000000..d837aae --- /dev/null +++ b/SOURCES/libvirt-Cope-with-races-while-killing-processes.patch @@ -0,0 +1,72 @@ +From 1e84e3165f8d37f8eebf862c6811f346cd8dbcca Mon Sep 17 00:00:00 2001 +Message-Id: <1e84e3165f8d37f8eebf862c6811f346cd8dbcca.1375465853.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Wed, 31 Jul 2013 19:48:19 +0100 +Subject: [PATCH] Cope with races while killing processes + +https://bugzilla.redhat.com/show_bug.cgi?id=980929 + +When systemd is involved in managing processes, it may start +killing off & tearing down croups associated with the process +while we're still doing virCgroupKillPainfully. We must +explicitly check for ENOENT and treat it as if we had finished +killing processes + +Signed-off-by: Daniel P. Berrange + +(cherry picked from commit 75304eaa1a08b23e5206b352403de7d296fc069e) +--- + src/util/vircgroup.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c +index 0e8bb79..a70bb98 100644 +--- a/src/util/vircgroup.c ++++ b/src/util/vircgroup.c +@@ -2550,6 +2550,12 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr + while (!done) { + done = true; + if (!(fp = fopen(keypath, "r"))) { ++ if (errno == ENOENT) { ++ VIR_DEBUG("No file %s, assuming done", keypath); ++ killedAny = false; ++ goto done; ++ } ++ + virReportSystemError(errno, + _("Failed to read %s"), + keypath); +@@ -2589,6 +2595,7 @@ static int virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr + } + } + ++ done: + ret = killedAny ? 1 : 0; + + cleanup: +@@ -2658,8 +2665,13 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas + if (rc == 1) + killedAny = true; + +- VIR_DEBUG("Iterate over children of %s", keypath); ++ VIR_DEBUG("Iterate over children of %s (killedAny=%d)", keypath, killedAny); + if (!(dp = opendir(keypath))) { ++ if (errno == ENOENT) { ++ VIR_DEBUG("Path %s does not exist, assuming done", keypath); ++ killedAny = false; ++ goto done; ++ } + virReportSystemError(errno, + _("Cannot open %s"), keypath); + return -1; +@@ -2689,6 +2701,7 @@ static int virCgroupKillRecursiveInternal(virCgroupPtr group, int signum, virHas + virCgroupFree(&subgroup); + } + ++ done: + ret = killedAny ? 1 : 0; + + cleanup: +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-DBus-introduce-virDBusIsServiceEnabled.patch b/SOURCES/libvirt-DBus-introduce-virDBusIsServiceEnabled.patch new file mode 100644 index 0000000..5a0fc73 --- /dev/null +++ b/SOURCES/libvirt-DBus-introduce-virDBusIsServiceEnabled.patch @@ -0,0 +1,160 @@ +From 351d57a6576d6026ac0e3807030b07e877e5de07 Mon Sep 17 00:00:00 2001 +Message-Id: <351d57a6576d6026ac0e3807030b07e877e5de07.1381871412.git.jdenemar@redhat.com> +From: Gao feng +Date: Mon, 14 Oct 2013 16:45:13 +0100 +Subject: [PATCH] DBus: introduce virDBusIsServiceEnabled + +For + + https://bugzilla.redhat.com/show_bug.cgi?id=1018730 + +This patch introduces virDBusIsServiceEnabled, we can use +this method to get if the service is supported. + +In one case, if org.freedesktop.machine1 is unavailable on +host, we should skip creating machine through systemd. + +Signed-off-by: Gao feng +(cherry picked from commit 7ada155cdf2bbfac16ce08f64abb455a940e2cf7) +Signed-off-by: Jiri Denemark +--- + src/util/virdbus.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/util/virdbus.h | 1 + + src/util/virsystemd.c | 17 +++++--------- + 3 files changed, 68 insertions(+), 11 deletions(-) + +diff --git a/src/util/virdbus.c b/src/util/virdbus.c +index 62c31be..a2c4b4e 100644 +--- a/src/util/virdbus.c ++++ b/src/util/virdbus.c +@@ -1207,6 +1207,61 @@ int virDBusMessageRead(DBusMessage *msg, + return ret; + } + ++/** ++ * virDBusIsServiceEnabled: ++ * @name: service name ++ * ++ * Retruns 0 if service is available, -1 on fatal error, or -2 if service is not available ++ */ ++int virDBusIsServiceEnabled(const char *name) ++{ ++ DBusConnection *conn; ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter, sub; ++ int ret = -1; ++ ++ if (!virDBusHasSystemBus()) ++ return -2; ++ ++ conn = virDBusGetSystemBus(); ++ ++ if (virDBusCallMethod(conn, ++ &reply, ++ "org.freedesktop.DBus", ++ "/org/freedesktop/DBus", ++ "org.freedesktop.DBus", ++ "ListActivatableNames", ++ DBUS_TYPE_INVALID) < 0) ++ return ret; ++ ++ if (!dbus_message_iter_init(reply, &iter) || ++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("Reply message incorrect")); ++ goto cleanup; ++ } ++ ++ ret = -2; ++ dbus_message_iter_recurse(&iter, &sub); ++ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) { ++ const char *service = NULL; ++ ++ dbus_message_iter_get_basic(&sub, &service); ++ dbus_message_iter_next(&sub); ++ ++ if (STREQ(service, name)) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ VIR_DEBUG("Service %s is %s", name, ret ? "unavailable" : "available"); ++ ++ cleanup: ++ dbus_message_unref(reply); ++ return ret; ++} ++ + + #else /* ! WITH_DBUS */ + DBusConnection *virDBusGetSystemBus(void) +@@ -1271,4 +1326,10 @@ int virDBusMessageDecode(DBusMessage* msg ATTRIBUTE_UNUSED, + return -1; + } + ++int virDBusIsServiceEnabled(const char *name ATTRIBUTE_UNUSED) ++{ ++ VIR_DEBUG("DBus support not compiled into this binary"); ++ return -2; ++} ++ + #endif /* ! WITH_DBUS */ +diff --git a/src/util/virdbus.h b/src/util/virdbus.h +index a5aab56..194a01a 100644 +--- a/src/util/virdbus.h ++++ b/src/util/virdbus.h +@@ -45,4 +45,5 @@ int virDBusCallMethod(DBusConnection *conn, + int virDBusMessageRead(DBusMessage *msg, + const char *types, ...); + ++int virDBusIsServiceEnabled(const char *name); + #endif /* __VIR_DBUS_H__ */ +diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c +index 13370b5..e72b7f0 100644 +--- a/src/util/virsystemd.c ++++ b/src/util/virsystemd.c +@@ -138,18 +138,20 @@ int virSystemdCreateMachine(const char *name, + bool iscontainer, + const char *partition) + { +- int ret = -1; ++ int ret; + DBusConnection *conn; + char *machinename = NULL; + char *creatorname = NULL; + char *username = NULL; + char *slicename = NULL; + +- if (!virDBusHasSystemBus()) +- return -2; ++ ret = virDBusIsServiceEnabled("org.freedesktop.machine1"); ++ if (ret < 0) ++ return ret; + + conn = virDBusGetSystemBus(); + ++ ret = -1; + if (privileged) { + if (virAsprintf(&machinename, "%s-%s", drivername, name) < 0) + goto cleanup; +@@ -228,15 +230,8 @@ int virSystemdCreateMachine(const char *name, + (unsigned int)pidleader, + rootdir ? rootdir : "", + 1, "Slice", "s", +- slicename) < 0) { +- virErrorPtr err = virGetLastError(); +- if (err->code == VIR_ERR_DBUS_SERVICE && +- STREQ(err->str2, "org.freedesktop.DBus.Error.ServiceUnknown")) { +- virResetLastError(); +- ret = -2; +- } ++ slicename) < 0) + goto cleanup; +- } + + ret = 0; + +-- +1.8.3.2 + diff --git a/SOURCES/libvirt-Delete-obsolete-unused-python-test-files.patch b/SOURCES/libvirt-Delete-obsolete-unused-python-test-files.patch new file mode 100644 index 0000000..5ad8ea7 --- /dev/null +++ b/SOURCES/libvirt-Delete-obsolete-unused-python-test-files.patch @@ -0,0 +1,451 @@ +From 79ca3c66fb28886ecaaf38220023d02efdddf66f Mon Sep 17 00:00:00 2001 +Message-Id: <79ca3c66fb28886ecaaf38220023d02efdddf66f.1375465853.git.jdenemar@redhat.com> +From: "Daniel P. Berrange" +Date: Tue, 30 Jul 2013 11:24:22 +0100 +Subject: [PATCH] Delete obsolete / unused python test files + +https://bugzilla.redhat.com/show_bug.cgi?id=884103 + +The python/tests directory contains a number of so called +"tests" for the python API. These are all hardcoded to +look for Xen and cannot be run in any automated fashion, +and no one is ever manually running them. Given that they +don't meaningully contribute to the test coverage, delete +them. + +For some reason these tests were also copied into the +filesystem as part of 'make install'. The change to the +RPM in commit 3347a4203278ec93d7b0ceb88b5ed10e4f14765c +caused a build failure, since it removed the code which +deleted these installed tests. + +Signed-off-by: Daniel P. Berrange +(cherry picked from commit 5bb2a245abbde4c0a407f631660e2f2c81bc4c02) +--- + configure.ac | 2 +- + python/Makefile.am | 2 - + python/tests/Makefile.am | 52 ----------------- + python/tests/basic.py | 31 ---------- + python/tests/create.py | 146 ----------------------------------------------- + python/tests/error.py | 42 -------------- + python/tests/node.py | 34 ----------- + python/tests/uuid.py | 41 ------------- + 8 files changed, 1 insertion(+), 349 deletions(-) + delete mode 100644 python/tests/Makefile.am + delete mode 100755 python/tests/basic.py + delete mode 100755 python/tests/create.py + delete mode 100755 python/tests/error.py + delete mode 100755 python/tests/node.py + delete mode 100755 python/tests/uuid.py + +diff --git a/configure.ac b/configure.ac +index 35a5d76..084d864 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2447,7 +2447,7 @@ AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile \ + libvirt.pc libvirt.spec mingw-libvirt.spec \ + po/Makefile.in \ + include/libvirt/Makefile include/libvirt/libvirt.h \ +- python/Makefile python/tests/Makefile \ ++ python/Makefile \ + daemon/Makefile \ + tools/Makefile \ + tests/Makefile \ +diff --git a/python/Makefile.am b/python/Makefile.am +index 7eb42c6..925e1f4 100644 +--- a/python/Makefile.am ++++ b/python/Makefile.am +@@ -16,8 +16,6 @@ + ## License along with this library. If not, see + ## . + +-SUBDIRS= . tests +- + INCLUDES = \ + $(PYTHON_INCLUDES) \ + -I$(top_builddir)/gnulib/lib \ +diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am +deleted file mode 100644 +index 0fd3c78..0000000 +--- a/python/tests/Makefile.am ++++ /dev/null +@@ -1,52 +0,0 @@ +-## Copyright (C) 2005-2011, 2013 Red Hat, Inc. +-## +-## This library is free software; you can redistribute it and/or +-## modify it under the terms of the GNU Lesser General Public +-## License as published by the Free Software Foundation; either +-## version 2.1 of the License, or (at your option) any later version. +-## +-## This library is distributed in the hope that it will be useful, +-## but WITHOUT ANY WARRANTY; without even the implied warranty of +-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-## Lesser General Public License for more details. +-## +-## You should have received a copy of the GNU Lesser General Public +-## License along with this library. If not, see +-## . +- +-EXAMPLE_DIR = $(datadir)/doc/libvirt-python-$(VERSION)/examples +- +-PYTESTS= \ +- basic.py \ +- create.py \ +- uuid.py \ +- error.py \ +- node.py +- +-EXTRA_DIST = $(PYTESTS) +- +-if WITH_PYTHON +-tests: $(PYTESTS) +- @echo "## running Python regression tests" +- -@(PYTHONPATH="..:../.libs:../src/.libs:$(srcdir)/../src:$$PYTHONPATH";\ +- export PYTHONPATH; \ +- LD_LIBRARY_PATH="$(top_builddir)/src/.libs:$$LD_LIBRARY_PATH" ; \ +- export LD_LIBRARY_PATH; \ +- for test in $(PYTESTS) ; \ +- do log=`$(PYTHON) $(srcdir)/$$test` ; \ +- if [ "`echo $$log | grep OK`" = "" ] ; then \ +- echo "-- $$test" ; echo "$$log" ; fi ; done) +-else +-tests: +-endif +- +-clean: +- rm -f *.pyc core +- +-install-data-local: +- $(mkinstalldirs) $(DESTDIR)$(EXAMPLE_DIR) +- -(for test in $(PYTESTS); \ +- do $(INSTALL) -m 0644 $(srcdir)/$$test $(DESTDIR)$(EXAMPLE_DIR) ; done) +- +-uninstall-local: +- for test in $(PYTESTS); do rm -f $(DESTDIR)$(EXAMPLE_DIR)/$$test; done +diff --git a/python/tests/basic.py b/python/tests/basic.py +deleted file mode 100755 +index c6dec81..0000000 +--- a/python/tests/basic.py ++++ /dev/null +@@ -1,31 +0,0 @@ +-#!/usr/bin/python -u +-import libvirt +-import sys +-import os +- +-if not os.access("/proc/xen", os.R_OK): +- print 'System is not running a Xen kernel' +- sys.exit(1) +- +-conn = libvirt.openReadOnly(None) +-if conn == None: +- print 'Failed to open connection to the hypervisor' +- sys.exit(1) +- +-# print conn +- +-try: +- dom0 = conn.lookupByName("Domain-0") +-except: +- print 'Failed to find the main domain' +- sys.exit(1) +- +-# print dom0 +- +-print "Domain 0: id %d running %s" % (dom0.ID(), dom0.OSType()) +-print dom0.info() +-del dom0 +-del conn +-print "OK" +- +-sys.exit(0) +diff --git a/python/tests/create.py b/python/tests/create.py +deleted file mode 100755 +index 815ccc4..0000000 +--- a/python/tests/create.py ++++ /dev/null +@@ -1,146 +0,0 @@ +-#!/usr/bin/python -u +-import libvirt +-import sys +-import os +-import time +- +-if not os.access("/proc/xen", os.R_OK): +- print 'System is not running a Xen kernel' +- sys.exit(1) +- +-# +-# Try to provide default OS images paths here, of course non standard +-# +-osroots = [ +- "/u/fc4-2.img", +- "/u/fc4.img", +- "/xen/fc4.img", +-] +- +-okay = 1 +- +-osroot = None +-for root in osroots: +- if os.access(root, os.R_OK): +- osroot = root +- break +- +-if osroot == None: +- print "Could not find a guest OS root, edit to add the path in osroots" +- sys.exit(1) +- +-kernel=open("/proc/version").read().split() +-kernelOv = kernel[2] +- +-if kernelOv.find('hypervisor'): +- kernelU = "/boot/vmlinuz-" + kernelOv.replace('hypervisor', 'guest') +- initrdU = "/boot/initrd-" + kernelOv.replace('hypervisor', 'guest') + ".img" +-elif kernelOv.find('xen0'): +- kernelU = "/boot/vmlinuz-" + kernelOv.replace('xen0', 'xenU') +- initrdU = "/boot/initrd-" + kernelOv.replace('xen0', 'xenU') + ".img" +- +-if not os.access(kernelU, os.R_OK): +- print "Did not find the guest kernel %s" % (kernelU) +- sys.exit(1) +- +-kernelU = "" + kernelU + "" +- +-if not os.access(initrdU, os.R_OK): +- print "Did not find the guest initrd %s" % (initrdU) +- initrdU = "" +-else: +- initrdU = "" + initrdU + "" +- +- +-conn = libvirt.open(None) +-if conn == None: +- print 'Failed to open connection to the hypervisor' +- sys.exit(1) +- +-xmldesc=""" +- test +- +- linux +-""" + kernelU + initrdU + """ +- root=/dev/sda1 ro selinux=0 3 +- +- 131072 +- 1 +- +- +- +- +- +- +- +- +-