[xen] Excessive checking in compatibility mode hypercall argument translation, Insufficient bounding of "R
myoung
myoung at fedoraproject.org
Thu Nov 27 21:51:19 UTC 2014
commit 1a774a79bed04025d5d85a13b7e18d825fe19410
Author: Michael Young <m.a.young at durham.ac.uk>
Date: Thu Nov 27 21:49:50 2014 +0000
Excessive checking in compatibility mode hypercall argument translation,
Insufficient bounding of "REP MOVS" to MMIO emulated inside the hypervisor,
fix segfaults and failures in xl migrate --debug
...-3460eeb3fc2811efcf2e8ac13a0882ab72ef92bc.patch | 31 ++
xen.spec | 19 +-
xl.migrate.debug.crash.patch | 11 +
xl.migrate.debug.fail.patch | 408 ++++++++++++++++++++
xsa111.patch | 122 ++++++
xsa112.patch | 88 +++++
6 files changed, 678 insertions(+), 1 deletions(-)
---
diff --git a/xen.git-3460eeb3fc2811efcf2e8ac13a0882ab72ef92bc.patch b/xen.git-3460eeb3fc2811efcf2e8ac13a0882ab72ef92bc.patch
new file mode 100644
index 0000000..c85dd76
--- /dev/null
+++ b/xen.git-3460eeb3fc2811efcf2e8ac13a0882ab72ef92bc.patch
@@ -0,0 +1,31 @@
+From 3460eeb3fc2811efcf2e8ac13a0882ab72ef92bc Mon Sep 17 00:00:00 2001
+From: Wen Congyang <wency at cn.fujitsu.com>
+Date: Mon, 22 Sep 2014 13:59:14 +0800
+Subject: [PATCH] tools: libxc: restore: csum the correct page
+
+In verify mode, we map the guest memory, and the guest page is
+region_base + i * PAGE_SIZE. So we should csum page (region_base
++ i * PAGE_SIZE), not (region_base + (i+curbatch) * PAGE_SIZE)
+
+Signed-off-by: Wen Congyang <wency at cn.fujitsu.com>
+Acked-by: Ian Campbell <ian.campbell at citrix.com>
+---
+ tools/libxc/xc_domain_restore.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
+index bec716c..fb4ddfc 100644
+--- a/tools/libxc/xc_domain_restore.c
++++ b/tools/libxc/xc_domain_restore.c
+@@ -1405,7 +1405,7 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
+
+ DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
+ "actualcs=%08lx\n", pfn, pagebuf->pfn_types[pfn],
+- csum_page(region_base + (i + curbatch)*PAGE_SIZE),
++ csum_page(region_base + i * PAGE_SIZE),
+ csum_page(buf));
+
+ for ( v = 0; v < 4; v++ )
+--
+1.7.2.5
+
diff --git a/xen.spec b/xen.spec
index 7c76747..a6bda79 100644
--- a/xen.spec
+++ b/xen.spec
@@ -53,7 +53,7 @@
Summary: Xen is a virtual machine monitor
Name: xen
Version: 4.4.1
-Release: 8%{?dist}
+Release: 9%{?dist}
Group: Development/Libraries
License: GPLv2+ and LGPLv2+ and BSD
URL: http://xen.org/
@@ -110,6 +110,11 @@ Patch29: xsa109.patch
Patch30: xsa110.patch
Patch31: CVE-2014-0150.patch
Patch32: xsa113.patch
+Patch33: xsa111.patch
+Patch34: xsa112.patch
+Patch35: xen.git-3460eeb3fc2811efcf2e8ac13a0882ab72ef92bc.patch
+Patch36: xl.migrate.debug.crash.patch
+Patch37: xl.migrate.debug.fail.patch
Patch99: xen.figs.disable.patch
Patch100: xen-configure-xend.patch
@@ -305,6 +310,11 @@ manage Xen virtual machines.
%patch30 -p1
%patch31 -p1
%patch32 -p1
+%patch33 -p1
+%patch34 -p1
+%patch35 -p1
+%patch36 -p1
+%patch37 -p1
%patch99 -p1
%patch100 -p1
@@ -907,6 +917,13 @@ rm -rf %{buildroot}
%endif
%changelog
+* Thu Nov 27 2014 Michael Young <m.a.young at durham.ac.uk> - 4.4.1-9
+- Excessive checking in compatibility mode hypercall argument translation
+ [XSA-111, CVE-2014-8866]
+- Insufficient bounding of "REP MOVS" to MMIO emulated inside the hypervisor
+ [XSA-112, CVE-2014-8867]
+- fix segfaults and failures in xl migrate --debug (#1166461)
+
* Thu Nov 20 2014 Michael Young <m.a.young at durham.ac.uk> - 4.4.1-8
- Guest effectable page reference leak in MMU_MACHPHYS_UPDATE handling
[XSA-113, CVE-2014-9030] (#1166914)
diff --git a/xl.migrate.debug.crash.patch b/xl.migrate.debug.crash.patch
new file mode 100644
index 0000000..4b3d822
--- /dev/null
+++ b/xl.migrate.debug.crash.patch
@@ -0,0 +1,11 @@
+--- xen-4.5.0-rc1/tools/libxc/xc_domain_restore.c.orig 2014-10-24 15:22:40.000000000 +0100
++++ xen-4.5.0-rc1/tools/libxc/xc_domain_restore.c 2014-11-25 21:01:16.604081467 +0000
+@@ -1404,7 +1404,7 @@
+ int v;
+
+ DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
+- "actualcs=%08lx\n", pfn, pagebuf->pfn_types[pfn],
++ "actualcs=%08lx\n", pfn, pfn_type[pfn],
+ csum_page(region_base + i * PAGE_SIZE),
+ csum_page(buf));
+
diff --git a/xl.migrate.debug.fail.patch b/xl.migrate.debug.fail.patch
new file mode 100644
index 0000000..9b70763
--- /dev/null
+++ b/xl.migrate.debug.fail.patch
@@ -0,0 +1,408 @@
+--- xen-4.5.0-rc1/tools/libxl/xl_cmdimpl.c.orig 2014-10-24 15:22:40.000000000 +0100
++++ xen-4.5.0-rc1/tools/libxl/xl_cmdimpl.c 2014-11-26 22:41:41.697043321 +0000
+@@ -380,10 +380,10 @@
+ }
+ static void printf_info(enum output_format output_format,
+ int domid,
+- libxl_domain_config *d_config)
++ libxl_domain_config *d_config, FILE *fh)
+ {
+ if (output_format == OUTPUT_FORMAT_SXP)
+- return printf_info_sexp(domid, d_config);
++ return printf_info_sexp(domid, d_config, fh);
+
+ const char *buf;
+ libxl_yajl_length len = 0;
+@@ -404,7 +404,7 @@
+ if (s != yajl_gen_status_ok)
+ goto out;
+
+- puts(buf);
++ fputs(buf, fh);
+
+ out:
+ yajl_gen_free(hand);
+@@ -413,7 +413,13 @@
+ fprintf(stderr,
+ "unable to format domain config as JSON (YAJL:%d)\n", s);
+
+- if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
++ if (ferror(fh) || fflush(fh)) {
++ if (fh == stdout)
++ perror("stdout");
++ else
++ perror("stderr");
++ exit(-1);
++ }
+ }
+
+ static int do_daemonize(char *name)
+@@ -2423,7 +2429,7 @@
+ }
+
+ if (!dom_info->quiet)
+- printf("Parsing config from %s\n", config_source);
++ fprintf(stderr, "Parsing config from %s\n", config_source);
+
+ parse_config_data(config_source, config_data, config_len, &d_config, dom_info);
+
+@@ -2451,7 +2457,7 @@
+ }
+
+ if (debug || dom_info->dryrun)
+- printf_info(default_output_format, -1, &d_config);
++ printf_info(default_output_format, -1, &d_config, stderr);
+
+ ret = 0;
+ if (dom_info->dryrun)
+@@ -3403,7 +3409,7 @@
+ if (default_output_format == OUTPUT_FORMAT_JSON)
+ s = printf_info_one_json(hand, info[i].domid, &d_config);
+ else
+- printf_info_sexp(info[i].domid, &d_config);
++ printf_info_sexp(info[i].domid, &d_config, stdout);
+ libxl_domain_config_dispose(&d_config);
+ free(data);
+ free(config_source);
+@@ -4725,7 +4731,7 @@
+ parse_config_data(filename, config_data, config_len, &d_config, NULL);
+
+ if (debug || dryrun_only)
+- printf_info(default_output_format, -1, &d_config);
++ printf_info(default_output_format, -1, &d_config, stdout);
+
+ if (!dryrun_only) {
+ fprintf(stderr, "setting dom%d configuration\n", domid);
+--- xen-4.5.0-rc1/tools/libxl/xl_sxp.c.orig 2014-10-24 15:22:40.000000000 +0100
++++ xen-4.5.0-rc1/tools/libxl/xl_sxp.c 2014-11-26 22:30:58.416394082 +0000
+@@ -30,7 +30,7 @@
+ /* In general you should not add new output to this function since it
+ * is intended only for legacy use.
+ */
+-void printf_info_sexp(int domid, libxl_domain_config *d_config)
++void printf_info_sexp(int domid, libxl_domain_config *d_config, FILE *fh)
+ {
+ int i;
+ libxl_dominfo info;
+@@ -39,197 +39,197 @@
+ libxl_domain_build_info *b_info = &d_config->b_info;
+ char *pool;
+
+- printf("(domain\n\t(domid %d)\n", domid);
+- printf("\t(create_info)\n");
+- printf("\t(hvm %d)\n", c_info->type == LIBXL_DOMAIN_TYPE_HVM);
+- printf("\t(hap %s)\n", libxl_defbool_to_string(c_info->hap));
+- printf("\t(oos %s)\n", libxl_defbool_to_string(c_info->oos));
+- printf("\t(ssidref %d)\n", c_info->ssidref);
+- printf("\t(name %s)\n", c_info->name);
++ fprintf(fh, "(domain\n\t(domid %d)\n", domid);
++ fprintf(fh, "\t(create_info)\n");
++ fprintf(fh, "\t(hvm %d)\n", c_info->type == LIBXL_DOMAIN_TYPE_HVM);
++ fprintf(fh, "\t(hap %s)\n", libxl_defbool_to_string(c_info->hap));
++ fprintf(fh, "\t(oos %s)\n", libxl_defbool_to_string(c_info->oos));
++ fprintf(fh, "\t(ssidref %d)\n", c_info->ssidref);
++ fprintf(fh, "\t(name %s)\n", c_info->name);
+
+ /* retrieve the UUID from dominfo, since it is probably generated
+ * during parsing and thus does not match the real one
+ */
+ if (libxl_domain_info(ctx, &info, domid) == 0) {
+- printf("\t(uuid " LIBXL_UUID_FMT ")\n", LIBXL_UUID_BYTES(info.uuid));
++ fprintf(fh, "\t(uuid " LIBXL_UUID_FMT ")\n", LIBXL_UUID_BYTES(info.uuid));
+ } else {
+- printf("\t(uuid <unknown>)\n");
++ fprintf(fh, "\t(uuid <unknown>)\n");
+ }
+ pool = libxl_cpupoolid_to_name(ctx, c_info->poolid);
+ if (pool)
+- printf("\t(cpupool %s)\n", pool);
++ fprintf(fh, "\t(cpupool %s)\n", pool);
+ free(pool);
+ if (c_info->xsdata)
+- printf("\t(xsdata contains data)\n");
++ fprintf(fh, "\t(xsdata contains data)\n");
+ else
+- printf("\t(xsdata (null))\n");
++ fprintf(fh, "\t(xsdata (null))\n");
+ if (c_info->platformdata)
+- printf("\t(platformdata contains data)\n");
++ fprintf(fh, "\t(platformdata contains data)\n");
+ else
+- printf("\t(platformdata (null))\n");
++ fprintf(fh, "\t(platformdata (null))\n");
+
+
+- printf("\t(build_info)\n");
+- printf("\t(max_vcpus %d)\n", b_info->max_vcpus);
+- printf("\t(tsc_mode %s)\n", libxl_tsc_mode_to_string(b_info->tsc_mode));
+- printf("\t(max_memkb %"PRId64")\n", b_info->max_memkb);
+- printf("\t(target_memkb %"PRId64")\n", b_info->target_memkb);
+- printf("\t(nomigrate %s)\n",
++ fprintf(fh, "\t(build_info)\n");
++ fprintf(fh, "\t(max_vcpus %d)\n", b_info->max_vcpus);
++ fprintf(fh, "\t(tsc_mode %s)\n", libxl_tsc_mode_to_string(b_info->tsc_mode));
++ fprintf(fh, "\t(max_memkb %"PRId64")\n", b_info->max_memkb);
++ fprintf(fh, "\t(target_memkb %"PRId64")\n", b_info->target_memkb);
++ fprintf(fh, "\t(nomigrate %s)\n",
+ libxl_defbool_to_string(b_info->disable_migrate));
+
+ if (c_info->type == LIBXL_DOMAIN_TYPE_PV && b_info->u.pv.bootloader) {
+- printf("\t(bootloader %s)\n", b_info->u.pv.bootloader);
++ fprintf(fh, "\t(bootloader %s)\n", b_info->u.pv.bootloader);
+ if (b_info->u.pv.bootloader_args) {
+- printf("\t(bootloader_args");
++ fprintf(fh, "\t(bootloader_args");
+ for (i=0; b_info->u.pv.bootloader_args[i]; i++)
+- printf(" %s", b_info->u.pv.bootloader_args[i]);
+- printf(")\n");
++ fprintf(fh, " %s", b_info->u.pv.bootloader_args[i]);
++ fprintf(fh, ")\n");
+ }
+ }
+
+- printf("\t(image\n");
++ fprintf(fh, "\t(image\n");
+ switch (c_info->type) {
+ case LIBXL_DOMAIN_TYPE_HVM:
+- printf("\t\t(hvm\n");
+- printf("\t\t\t(firmware %s)\n", b_info->u.hvm.firmware);
+- printf("\t\t\t(video_memkb %"PRId64")\n", b_info->video_memkb);
+- printf("\t\t\t(shadow_memkb %"PRId64")\n", b_info->shadow_memkb);
+- printf("\t\t\t(pae %s)\n", libxl_defbool_to_string(b_info->u.hvm.pae));
+- printf("\t\t\t(apic %s)\n",
++ fprintf(fh, "\t\t(hvm\n");
++ fprintf(fh, "\t\t\t(firmware %s)\n", b_info->u.hvm.firmware);
++ fprintf(fh, "\t\t\t(video_memkb %"PRId64")\n", b_info->video_memkb);
++ fprintf(fh, "\t\t\t(shadow_memkb %"PRId64")\n", b_info->shadow_memkb);
++ fprintf(fh, "\t\t\t(pae %s)\n", libxl_defbool_to_string(b_info->u.hvm.pae));
++ fprintf(fh, "\t\t\t(apic %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.apic));
+- printf("\t\t\t(acpi %s)\n",
++ fprintf(fh, "\t\t\t(acpi %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.acpi));
+- printf("\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
+- printf("\t\t\t(viridian %s)\n",
++ fprintf(fh, "\t\t\t(nx %s)\n", libxl_defbool_to_string(b_info->u.hvm.nx));
++ fprintf(fh, "\t\t\t(viridian %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.viridian));
+- printf("\t\t\t(hpet %s)\n",
++ fprintf(fh, "\t\t\t(hpet %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.hpet));
+- printf("\t\t\t(vpt_align %s)\n",
++ fprintf(fh, "\t\t\t(vpt_align %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.vpt_align));
+- printf("\t\t\t(timer_mode %s)\n",
++ fprintf(fh, "\t\t\t(timer_mode %s)\n",
+ libxl_timer_mode_to_string(b_info->u.hvm.timer_mode));
+- printf("\t\t\t(nestedhvm %s)\n",
++ fprintf(fh, "\t\t\t(nestedhvm %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.nested_hvm));
+- printf("\t\t\t(stdvga %s)\n", b_info->u.hvm.vga.kind ==
++ fprintf(fh, "\t\t\t(stdvga %s)\n", b_info->u.hvm.vga.kind ==
+ LIBXL_VGA_INTERFACE_TYPE_STD ?
+ "True" : "False");
+- printf("\t\t\t(vnc %s)\n",
++ fprintf(fh, "\t\t\t(vnc %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.vnc.enable));
+- printf("\t\t\t(vnclisten %s)\n", b_info->u.hvm.vnc.listen);
+- printf("\t\t\t(vncdisplay %d)\n", b_info->u.hvm.vnc.display);
+- printf("\t\t\t(vncunused %s)\n",
++ fprintf(fh, "\t\t\t(vnclisten %s)\n", b_info->u.hvm.vnc.listen);
++ fprintf(fh, "\t\t\t(vncdisplay %d)\n", b_info->u.hvm.vnc.display);
++ fprintf(fh, "\t\t\t(vncunused %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.vnc.findunused));
+- printf("\t\t\t(keymap %s)\n", b_info->u.hvm.keymap);
+- printf("\t\t\t(sdl %s)\n",
++ fprintf(fh, "\t\t\t(keymap %s)\n", b_info->u.hvm.keymap);
++ fprintf(fh, "\t\t\t(sdl %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.sdl.enable));
+- printf("\t\t\t(opengl %s)\n",
++ fprintf(fh, "\t\t\t(opengl %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.sdl.opengl));
+- printf("\t\t\t(nographic %s)\n",
++ fprintf(fh, "\t\t\t(nographic %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.nographic));
+- printf("\t\t\t(spice %s)\n",
++ fprintf(fh, "\t\t\t(spice %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.spice.enable));
+- printf("\t\t\t(spiceport %d)\n", b_info->u.hvm.spice.port);
+- printf("\t\t\t(spicetls_port %d)\n", b_info->u.hvm.spice.tls_port);
+- printf("\t\t\t(spicehost %s)\n", b_info->u.hvm.spice.host);
+- printf("\t\t\t(spicedisable_ticketing %s)\n",
++ fprintf(fh, "\t\t\t(spiceport %d)\n", b_info->u.hvm.spice.port);
++ fprintf(fh, "\t\t\t(spicetls_port %d)\n", b_info->u.hvm.spice.tls_port);
++ fprintf(fh, "\t\t\t(spicehost %s)\n", b_info->u.hvm.spice.host);
++ fprintf(fh, "\t\t\t(spicedisable_ticketing %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.spice.disable_ticketing));
+- printf("\t\t\t(spiceagent_mouse %s)\n",
++ fprintf(fh, "\t\t\t(spiceagent_mouse %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.spice.agent_mouse));
+
+- printf("\t\t\t(device_model %s)\n", b_info->device_model ? : "default");
+- printf("\t\t\t(gfx_passthru %s)\n",
++ fprintf(fh, "\t\t\t(device_model %s)\n", b_info->device_model ? : "default");
++ fprintf(fh, "\t\t\t(gfx_passthru %s)\n",
+ libxl_defbool_to_string(b_info->u.hvm.gfx_passthru));
+- printf("\t\t\t(serial %s)\n", b_info->u.hvm.serial);
+- printf("\t\t\t(boot %s)\n", b_info->u.hvm.boot);
+- printf("\t\t\t(usb %s)\n", libxl_defbool_to_string(b_info->u.hvm.usb));
+- printf("\t\t\t(usbdevice %s)\n", b_info->u.hvm.usbdevice);
+- printf("\t\t)\n");
++ fprintf(fh, "\t\t\t(serial %s)\n", b_info->u.hvm.serial);
++ fprintf(fh, "\t\t\t(boot %s)\n", b_info->u.hvm.boot);
++ fprintf(fh, "\t\t\t(usb %s)\n", libxl_defbool_to_string(b_info->u.hvm.usb));
++ fprintf(fh, "\t\t\t(usbdevice %s)\n", b_info->u.hvm.usbdevice);
++ fprintf(fh, "\t\t)\n");
+ break;
+ case LIBXL_DOMAIN_TYPE_PV:
+- printf("\t\t(linux %d)\n", 0);
+- printf("\t\t\t(kernel %s)\n", b_info->u.pv.kernel);
+- printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
+- printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk);
+- printf("\t\t\t(e820_host %s)\n",
++ fprintf(fh, "\t\t(linux %d)\n", 0);
++ fprintf(fh, "\t\t\t(kernel %s)\n", b_info->u.pv.kernel);
++ fprintf(fh, "\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
++ fprintf(fh, "\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk);
++ fprintf(fh, "\t\t\t(e820_host %s)\n",
+ libxl_defbool_to_string(b_info->u.pv.e820_host));
+- printf("\t\t)\n");
++ fprintf(fh, "\t\t)\n");
+ break;
+ default:
+ fprintf(stderr, "Unknown domain type %d\n", c_info->type);
+ exit(1);
+ }
+- printf("\t)\n");
++ fprintf(fh, "\t)\n");
+
+ for (i = 0; i < d_config->num_disks; i++) {
+- printf("\t(device\n");
+- printf("\t\t(tap\n");
+- printf("\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
+- printf("\t\t\t(frontend_domid %d)\n", domid);
+- printf("\t\t\t(physpath %s)\n", d_config->disks[i].pdev_path);
+- printf("\t\t\t(phystype %d)\n", d_config->disks[i].backend);
+- printf("\t\t\t(virtpath %s)\n", d_config->disks[i].vdev);
+- printf("\t\t\t(unpluggable %d)\n", d_config->disks[i].removable);
+- printf("\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
+- printf("\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
+- printf("\t\t)\n");
+- printf("\t)\n");
++ fprintf(fh, "\t(device\n");
++ fprintf(fh, "\t\t(tap\n");
++ fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->disks[i].backend_domid);
++ fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
++ fprintf(fh, "\t\t\t(physpath %s)\n", d_config->disks[i].pdev_path);
++ fprintf(fh, "\t\t\t(phystype %d)\n", d_config->disks[i].backend);
++ fprintf(fh, "\t\t\t(virtpath %s)\n", d_config->disks[i].vdev);
++ fprintf(fh, "\t\t\t(unpluggable %d)\n", d_config->disks[i].removable);
++ fprintf(fh, "\t\t\t(readwrite %d)\n", d_config->disks[i].readwrite);
++ fprintf(fh, "\t\t\t(is_cdrom %d)\n", d_config->disks[i].is_cdrom);
++ fprintf(fh, "\t\t)\n");
++ fprintf(fh, "\t)\n");
+ }
+
+ for (i = 0; i < d_config->num_nics; i++) {
+- printf("\t(device\n");
+- printf("\t\t(vif\n");
++ fprintf(fh, "\t(device\n");
++ fprintf(fh, "\t\t(vif\n");
+ if (d_config->nics[i].ifname)
+- printf("\t\t\t(vifname %s)\n", d_config->nics[i].ifname);
+- printf("\t\t\t(backend_domid %d)\n", d_config->nics[i].backend_domid);
+- printf("\t\t\t(frontend_domid %d)\n", domid);
+- printf("\t\t\t(devid %d)\n", d_config->nics[i].devid);
+- printf("\t\t\t(mtu %d)\n", d_config->nics[i].mtu);
+- printf("\t\t\t(model %s)\n", d_config->nics[i].model);
+- printf("\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
++ fprintf(fh, "\t\t\t(vifname %s)\n", d_config->nics[i].ifname);
++ fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->nics[i].backend_domid);
++ fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
++ fprintf(fh, "\t\t\t(devid %d)\n", d_config->nics[i].devid);
++ fprintf(fh, "\t\t\t(mtu %d)\n", d_config->nics[i].mtu);
++ fprintf(fh, "\t\t\t(model %s)\n", d_config->nics[i].model);
++ fprintf(fh, "\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
+ d_config->nics[i].mac[0], d_config->nics[i].mac[1],
+ d_config->nics[i].mac[2], d_config->nics[i].mac[3],
+ d_config->nics[i].mac[4], d_config->nics[i].mac[5]);
+- printf("\t\t)\n");
+- printf("\t)\n");
++ fprintf(fh, "\t\t)\n");
++ fprintf(fh, "\t)\n");
+ }
+
+ for (i = 0; i < d_config->num_pcidevs; i++) {
+- printf("\t(device\n");
+- printf("\t\t(pci\n");
+- printf("\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
++ fprintf(fh, "\t(device\n");
++ fprintf(fh, "\t\t(pci\n");
++ fprintf(fh, "\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
+ d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
+ d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
+ d_config->pcidevs[i].vdevfn);
+- printf("\t\t\t(opts msitranslate %d power_mgmt %d)\n",
++ fprintf(fh, "\t\t\t(opts msitranslate %d power_mgmt %d)\n",
+ d_config->pcidevs[i].msitranslate,
+ d_config->pcidevs[i].power_mgmt);
+- printf("\t\t)\n");
+- printf("\t)\n");
++ fprintf(fh, "\t\t)\n");
++ fprintf(fh, "\t)\n");
+ }
+
+ for (i = 0; i < d_config->num_vfbs; i++) {
+- printf("\t(device\n");
+- printf("\t\t(vfb\n");
+- printf("\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
+- printf("\t\t\t(frontend_domid %d)\n", domid);
+- printf("\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
+- printf("\t\t\t(vnc %s)\n",
++ fprintf(fh, "\t(device\n");
++ fprintf(fh, "\t\t(vfb\n");
++ fprintf(fh, "\t\t\t(backend_domid %d)\n", d_config->vfbs[i].backend_domid);
++ fprintf(fh, "\t\t\t(frontend_domid %d)\n", domid);
++ fprintf(fh, "\t\t\t(devid %d)\n", d_config->vfbs[i].devid);
++ fprintf(fh, "\t\t\t(vnc %s)\n",
+ libxl_defbool_to_string(d_config->vfbs[i].vnc.enable));
+- printf("\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnc.listen);
+- printf("\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vnc.display);
+- printf("\t\t\t(vncunused %s)\n",
++ fprintf(fh, "\t\t\t(vnclisten %s)\n", d_config->vfbs[i].vnc.listen);
++ fprintf(fh, "\t\t\t(vncdisplay %d)\n", d_config->vfbs[i].vnc.display);
++ fprintf(fh, "\t\t\t(vncunused %s)\n",
+ libxl_defbool_to_string(d_config->vfbs[i].vnc.findunused));
+- printf("\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
+- printf("\t\t\t(sdl %s)\n",
++ fprintf(fh, "\t\t\t(keymap %s)\n", d_config->vfbs[i].keymap);
++ fprintf(fh, "\t\t\t(sdl %s)\n",
+ libxl_defbool_to_string(d_config->vfbs[i].sdl.enable));
+- printf("\t\t\t(opengl %s)\n",
++ fprintf(fh, "\t\t\t(opengl %s)\n",
+ libxl_defbool_to_string(d_config->vfbs[i].sdl.opengl));
+- printf("\t\t\t(display %s)\n", d_config->vfbs[i].sdl.display);
+- printf("\t\t\t(xauthority %s)\n", d_config->vfbs[i].sdl.xauthority);
+- printf("\t\t)\n");
+- printf("\t)\n");
++ fprintf(fh, "\t\t\t(display %s)\n", d_config->vfbs[i].sdl.display);
++ fprintf(fh, "\t\t\t(xauthority %s)\n", d_config->vfbs[i].sdl.xauthority);
++ fprintf(fh, "\t\t)\n");
++ fprintf(fh, "\t)\n");
+ }
+- printf(")\n");
++ fprintf(fh, ")\n");
+ }
+
+
+--- xen-4.5.0-rc1/tools/libxl/xl.h.orig 2014-10-24 15:22:40.000000000 +0100
++++ xen-4.5.0-rc1/tools/libxl/xl.h 2014-11-26 22:30:58.416394082 +0000
+@@ -186,7 +186,7 @@
+ };
+ extern enum output_format default_output_format;
+
+-extern void printf_info_sexp(int domid, libxl_domain_config *d_config);
++extern void printf_info_sexp(int domid, libxl_domain_config *d_config, FILE *fh);
+
+ #define XL_GLOBAL_CONFIG XEN_CONFIG_DIR "/xl.conf"
+ #define XL_LOCK_FILE XEN_LOCK_DIR "/xl"
diff --git a/xsa111.patch b/xsa111.patch
new file mode 100644
index 0000000..1761316
--- /dev/null
+++ b/xsa111.patch
@@ -0,0 +1,122 @@
+x86: limit checks in hypercall_xlat_continuation() to actual arguments
+
+HVM/PVH guests can otherwise trigger the final BUG_ON() in that
+function by entering 64-bit mode, setting the high halves of affected
+registers to non-zero values, leaving 64-bit mode, and issuing a
+hypercall that might get preempted and hence become subject to
+continuation argument translation (HYPERVISOR_memory_op being the only
+one possible for HVM, PVH also having the option of using
+HYPERVISOR_mmuext_op). This issue got introduced when HVM code was
+switched to use compat_memory_op() - neither that nor
+hypercall_xlat_continuation() were originally intended to be used by
+other than PV guests (which can't enter 64-bit mode and hence have no
+way to alter the high halves of 64-bit registers).
+
+This is XSA-111.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+Reviewed-by: Tim Deegan <tim at xen.org>
+
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -1750,7 +1750,8 @@ unsigned long hypercall_create_continuat
+ return op;
+ }
+
+-int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
++int hypercall_xlat_continuation(unsigned int *id, unsigned int nr,
++ unsigned int mask, ...)
+ {
+ int rc = 0;
+ struct mc_state *mcs = ¤t->mc_state;
+@@ -1759,7 +1760,10 @@ int hypercall_xlat_continuation(unsigned
+ unsigned long nval = 0;
+ va_list args;
+
+- BUG_ON(id && *id > 5);
++ ASSERT(nr <= ARRAY_SIZE(mcs->call.args));
++ ASSERT(!(mask >> nr));
++
++ BUG_ON(id && *id >= nr);
+ BUG_ON(id && (mask & (1U << *id)));
+
+ va_start(args, mask);
+@@ -1772,7 +1776,7 @@ int hypercall_xlat_continuation(unsigned
+ return 0;
+ }
+
+- for ( i = 0; i < 6; ++i, mask >>= 1 )
++ for ( i = 0; i < nr; ++i, mask >>= 1 )
+ {
+ if ( mask & 1 )
+ {
+@@ -1800,7 +1804,7 @@ int hypercall_xlat_continuation(unsigned
+ else
+ {
+ regs = guest_cpu_user_regs();
+- for ( i = 0; i < 6; ++i, mask >>= 1 )
++ for ( i = 0; i < nr; ++i, mask >>= 1 )
+ {
+ unsigned long *reg;
+
+--- a/xen/arch/x86/x86_64/compat/mm.c
++++ b/xen/arch/x86/x86_64/compat/mm.c
+@@ -118,7 +118,7 @@ int compat_arch_memory_op(unsigned long
+ break;
+
+ if ( rc == __HYPERVISOR_memory_op )
+- hypercall_xlat_continuation(NULL, 0x2, nat, arg);
++ hypercall_xlat_continuation(NULL, 2, 0x2, nat, arg);
+
+ XLAT_pod_target(&cmp, nat);
+
+@@ -354,7 +354,7 @@ int compat_mmuext_op(XEN_GUEST_HANDLE_PA
+ left = 1;
+ if ( arg1 != MMU_UPDATE_PREEMPTED )
+ {
+- BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops,
++ BUG_ON(!hypercall_xlat_continuation(&left, 4, 0x01, nat_ops,
+ cmp_uops));
+ if ( !test_bit(_MCSF_in_multicall, &mcs->flags) )
+ regs->_ecx += count - i;
+@@ -362,7 +362,7 @@ int compat_mmuext_op(XEN_GUEST_HANDLE_PA
+ mcs->compat_call.args[1] += count - i;
+ }
+ else
+- BUG_ON(hypercall_xlat_continuation(&left, 0));
++ BUG_ON(hypercall_xlat_continuation(&left, 4, 0));
+ BUG_ON(left != arg1);
+ }
+ else
+--- a/xen/common/compat/memory.c
++++ b/xen/common/compat/memory.c
+@@ -282,7 +282,7 @@ int compat_memory_op(unsigned int cmd, X
+ break;
+
+ cmd = 0;
+- if ( hypercall_xlat_continuation(&cmd, 0x02, nat.hnd, compat) )
++ if ( hypercall_xlat_continuation(&cmd, 2, 0x02, nat.hnd, compat) )
+ {
+ BUG_ON(rc != __HYPERVISOR_memory_op);
+ BUG_ON((cmd & MEMOP_CMD_MASK) != op);
+--- a/xen/include/xen/compat.h
++++ b/xen/include/xen/compat.h
+@@ -195,6 +195,8 @@ static inline int name(k xen_ ## n *x, k
+ * This option is useful for extracting the "op" argument or similar from the
+ * hypercall to enable further xlat processing.
+ *
++ * nr: Total number of arguments the hypercall has.
++ *
+ * mask: Specifies which of the hypercall arguments require compat translation.
+ * bit 0 indicates that the 0'th argument requires translation, bit 1 indicates
+ * that the first argument requires translation and so on. Native and compat
+@@ -214,7 +216,8 @@ static inline int name(k xen_ ## n *x, k
+ *
+ * Return: Number of arguments which were actually translated.
+ */
+-int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...);
++int hypercall_xlat_continuation(unsigned int *id, unsigned int nr,
++ unsigned int mask, ...);
+
+ /* In-place translation functons: */
+ struct start_info;
diff --git a/xsa112.patch b/xsa112.patch
new file mode 100644
index 0000000..a3da626
--- /dev/null
+++ b/xsa112.patch
@@ -0,0 +1,88 @@
+x86/HVM: confine internally handled MMIO to solitary regions
+
+While it is generally wrong to cross region boundaries when dealing
+with MMIO accesses of repeated string instructions (currently only
+MOVS) as that would do things a guest doesn't expect (leaving aside
+that none of these regions would normally be accessed with repeated
+string instructions in the first place), this is even more of a problem
+for all virtual MSI-X page accesses (both msixtbl_{read,write}() can be
+made dereference NULL "entry" pointers this way) as well as undersized
+(1- or 2-byte) LAPIC writes (causing vlapic_read_aligned() to access
+space beyond the one memory page set up for holding LAPIC register
+values).
+
+Since those functions validly assume to be called only with addresses
+their respective checking functions indicated to be okay, it is generic
+code that needs to be fixed to clip the repetition count.
+
+To be on the safe side (and consistent), also do the same for buffered
+I/O intercepts, even if their only client (stdvga) doesn't put the
+hypervisor at risk (i.e. "only" guest misbehavior would result).
+
+This is CVE-2014-8867 / XSA-112.
+
+Signed-off-by: Jan Beulich <jbeulich at suse.com>
+Reviewed-by: Tim Deegan <tim at xen.org>
+
+--- a/xen/arch/x86/hvm/intercept.c
++++ b/xen/arch/x86/hvm/intercept.c
+@@ -181,11 +181,24 @@ int hvm_mmio_intercept(ioreq_t *p)
+ int i;
+
+ for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ )
+- if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) )
++ {
++ hvm_mmio_check_t check_handler =
++ hvm_mmio_handlers[i]->check_handler;
++
++ if ( check_handler(v, p->addr) )
++ {
++ if ( unlikely(p->count > 1) &&
++ !check_handler(v, unlikely(p->df)
++ ? p->addr - (p->count - 1L) * p->size
++ : p->addr + (p->count - 1L) * p->size) )
++ p->count = 1;
++
+ return hvm_mmio_access(
+ v, p,
+ hvm_mmio_handlers[i]->read_handler,
+ hvm_mmio_handlers[i]->write_handler);
++ }
++ }
+
+ return X86EMUL_UNHANDLEABLE;
+ }
+@@ -342,6 +355,13 @@ int hvm_io_intercept(ioreq_t *p, int typ
+ if ( type == HVM_PORTIO )
+ return process_portio_intercept(
+ handler->hdl_list[i].action.portio, p);
++
++ if ( unlikely(p->count > 1) &&
++ (unlikely(p->df)
++ ? p->addr - (p->count - 1L) * p->size < addr
++ : p->addr + p->count * 1L * p->size - 1 >= addr + size) )
++ p->count = 1;
++
+ return handler->hdl_list[i].action.mmio(p);
+ }
+ }
+--- a/xen/arch/x86/hvm/vmsi.c
++++ b/xen/arch/x86/hvm/vmsi.c
+@@ -226,6 +226,8 @@ static int msixtbl_read(
+ rcu_read_lock(&msixtbl_rcu_lock);
+
+ entry = msixtbl_find_entry(v, address);
++ if ( !entry )
++ goto out;
+ offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
+
+ if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
+@@ -268,6 +270,8 @@ static int msixtbl_write(struct vcpu *v,
+ rcu_read_lock(&msixtbl_rcu_lock);
+
+ entry = msixtbl_find_entry(v, address);
++ if ( !entry )
++ goto out;
+ nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
+
+ offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
More information about the scm-commits
mailing list