[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 = &current->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