summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonardo Arena <rnalrd@alpinelinux.org>2017-04-27 15:01:03 +0000
committerLeonardo Arena <rnalrd@alpinelinux.org>2017-04-28 06:11:48 +0000
commit5a58568f86fb352acf6c7598f8c7fdf05749676a (patch)
tree1a9a08ab78384708ed6a28da54ec833c73e9be34
parentc008230bf2ef319a8e6b5f39b245c1319a30e268 (diff)
main/xen: security fixes #7115 (CVE-2016-9603, CVE-2017-7228)
-rw-r--r--main/xen/APKBUILD17
-rw-r--r--main/xen/xsa211-qemut.patch225
-rw-r--r--main/xen/xsa211-qemuu-4.6.patch260
-rw-r--r--main/xen/xsa212.patch87
4 files changed, 588 insertions, 1 deletions
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD
index dfeec648a53..87a3d98a4a1 100644
--- a/main/xen/APKBUILD
+++ b/main/xen/APKBUILD
@@ -4,7 +4,7 @@
# Maintainer: William Pitcock <nenolod@dereferenced.org>
pkgname=xen
pkgver=4.6.3
-pkgrel=5
+pkgrel=6
pkgdesc="Xen hypervisor"
url="http://www.xen.org/"
arch="x86_64"
@@ -82,6 +82,9 @@ source="http://bits.xensource.com/oss-xen/release/$pkgver/$pkgname-$pkgver.tar.g
xsa202-4.6.patch
xsa203-4.7.patch
xsa204-4.7.patch
+ xsa211-qemut.patch
+ xsa211-qemuu-4.6.patch
+ xsa212.patch
qemu-coroutine-gthread.patch
qemu-xen_paths.patch
@@ -125,6 +128,9 @@ _seabios=/usr/share/seabios/bios-256k.bin
# - CVE-2016-7092
# - CVE-2016-7093
# - CVE-2016-7094
+# 4.6.3-r5:
+# - CVE-2016-9603
+# - CVE-2017-7228
prepare() {
local i _failed=
@@ -317,6 +323,9 @@ add3ad7828d582fc272073e906ce17a1 xsa200-4.6.patch
a5a39c6354c952095e1d78a582385933 xsa202-4.6.patch
da401ec1a25668a2dabc666f6687409b xsa203-4.7.patch
dc4ad05682ce371e1755817b22229601 xsa204-4.7.patch
+08722b90a7d33850ea67dfc90d04f6d8 xsa211-qemut.patch
+a300eae67ae77cf4d2e0741dad01ee29 xsa211-qemuu-4.6.patch
+8d3c76a3954dfa359d2f9fe9b59c1828 xsa212.patch
de1a3db370b87cfb0bddb51796b50315 qemu-coroutine-gthread.patch
08bfdf8caff5d631f53660bf3fd4edaf qemu-xen_paths.patch
e449bb3359b490804ffc7b0ae08d62a0 hotplug-vif-vtrill.patch
@@ -375,6 +384,9 @@ a9cf56564d020675c0f2f1ea15009a712f172be3d53ea8ddf2f48adaac392e76 xsa201-3-4.7.p
e007187639f5392a9256979504d50eff0ae38309a61524ea42c4150fab38b6f4 xsa202-4.6.patch
7cc04278778fe885e4c3ae3f846d099075a38bccfafe6dff018ba525499b4e46 xsa203-4.7.patch
d0359f26e9be783672896200e14d85a3111c29d7da580313b593fca04688fef2 xsa204-4.7.patch
+6d583b255db09a8ed34545a8b290d40c2f51f293de6ebb5abef57945c274ecb0 xsa211-qemut.patch
+be0049f39b306a3dfb703b73eb60ecf35b9cc7a3d4e9481fd8314fd7e3704573 xsa211-qemuu-4.6.patch
+be1255bcda06158cdb86eb5297e8a271e05318e88cd21035c58a67f9ada6ccba xsa212.patch
3941f99b49c7e8dafc9fae8aad2136a14c6d84533cd542cc5f1040a41ef7c6fe qemu-coroutine-gthread.patch
e4e5e838e259a3116978aabbcebc1865a895179a7fcbf4bad195c83e9b4c0f98 qemu-xen_paths.patch
dd1e784bc455eb62cb85b3fa24bfc34f575ceaab9597ef6a2f1ee7ff7b3cae0a hotplug-vif-vtrill.patch
@@ -433,6 +445,9 @@ ad0f4217ef8218dac6997385690981e7a88d05b735e04779f582ad4a0307d8e7804c015971403133
dee7a595324ea5de3754c9aad2422fc2021bcb53999e344dbe6e4edfd4772a5ed20e8ebfb40750b81287a2a022037d49cbe4f0f7ba481ae0ac79a4249ef630bf xsa202-4.6.patch
b86ef48db23dacb51fbbdd55041bf08fac8aa0db76a272bb2f9d9be7195cd9a359a30fbbb61e040c66f23358f12ae102a92a30296fb18e4feb1023b58ffad4ff xsa203-4.7.patch
a2a091cd51ed54f5b5ba4131efc1c9cc0a69a647cea46415f73c29e5764efb00025e2e65bd5d24cf26f903263fce150b2b1c52ca5d61fd81dea7efe16abf57be xsa204-4.7.patch
+42d3350eda9dafeb52748d5ba5f3edf8dea106a1fd2bce8d00bdee4ca1f49be1fd5d7b0bec427e147b856efd91517ce5f069796a1172504317986c34d652180d xsa211-qemut.patch
+a21ae520900f31b77a50cb9956499d884d93802962e0f10503c61b8962ad76a38655a17bc9ef03057b5c23d4f4c5b6a951fd3ad6aa5bbd5ad7e939b29706b7c6 xsa211-qemuu-4.6.patch
+d012556c6b439629c5e4284a0de2f5ae70cda3db4f6f42373b8719509fec3bb0bb667a50484fd1e6c1129dcd2bff550a3eb9ead0f676fb626e6263ac98023e06 xsa212.patch
c3c46f232f0bd9f767b232af7e8ce910a6166b126bd5427bb8dc325aeb2c634b956de3fc225cab5af72649070c8205cc8e1cab7689fc266c204f525086f1a562 qemu-coroutine-gthread.patch
1936ab39a1867957fa640eb81c4070214ca4856a2743ba7e49c0cd017917071a9680d015f002c57fa7b9600dbadd29dcea5887f50e6c133305df2669a7a933f3 qemu-xen_paths.patch
f095ea373f36381491ad36f0662fb4f53665031973721256b23166e596318581da7cbb0146d0beb2446729adfdb321e01468e377793f6563a67d68b8b0f7ffe3 hotplug-vif-vtrill.patch
diff --git a/main/xen/xsa211-qemut.patch b/main/xen/xsa211-qemut.patch
new file mode 100644
index 00000000000..ecfc58a17a1
--- /dev/null
+++ b/main/xen/xsa211-qemut.patch
@@ -0,0 +1,225 @@
+From 29e67cfd46b4d06ca1bb75558e227ec34a6af35f Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson@eu.citrix.com>
+Date: Thu, 9 Mar 2017 11:14:55 +0000
+Subject: [PATCH] cirrus/vnc: zap drop bitblit support from console code.
+
+From: Gerd Hoffmann <kraxel@redhat.com>
+
+There is a special code path (dpy_gfx_copy) to allow graphic emulation
+notify user interface code about bitblit operations carryed out by
+guests. It is supported by cirrus and vnc server. The intended purpose
+is to optimize display scrolls and just send over the scroll op instead
+of a full display update.
+
+This is rarely used these days though because modern guests simply don't
+use the cirrus blitter any more. Any linux guest using the cirrus drm
+driver doesn't. Any windows guest newer than winxp doesn't ship with a
+cirrus driver any more and thus uses the cirrus as simple framebuffer.
+
+So this code tends to bitrot and bugs can go unnoticed for a long time.
+See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV"
+which fixes a bug lingering in the code for almost a year, added by
+commit "c7628bf vnc: only alloc server surface with clients connected".
+
+Also the vnc server will throttle the frame rate in case it figures the
+network can't keep up (send buffers are full). This doesn't work with
+dpy_gfx_copy, for any copy operation sent to the vnc client we have to
+send all outstanding updates beforehand, otherwise the vnc client might
+run the client side blit on outdated data and thereby corrupt the
+display. So this dpy_gfx_copy "optimization" might even make things
+worse on slow network links.
+
+Lets kill it once for all.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+These changes (dropping dpy_copy and all its references and
+implementations) reimplemented for qemu-xen-traditional.
+
+This is XSA-211.
+
+Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
+---
+ console.c | 8 --------
+ tools/qemu-xen-traditional/console.h | 16 ----------------
+ hw/cirrus_vga.c | 15 +++++----------
+ hw/vmware_vga.c | 1 +
+ vnc.c | 35 -----------------------------------
+ 5 files changed, 6 insertions(+), 69 deletions(-)
+
+diff --git a/tools/qemu-xen-traditional/console.c b/tools/qemu-xen-traditional/console.c
+index d4f1ad0..e61b53b 100644
+--- a/tools/qemu-xen-traditional/console.c
++++ b/tools/qemu-xen-traditional/console.c
+@@ -1399,14 +1399,6 @@ void qemu_console_resize(DisplayState *ds, int width, int height)
+ }
+ }
+
+-void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- if (is_graphic_console()) {
+- dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
+- }
+-}
+-
+ PixelFormat qemu_different_endianness_pixelformat(int bpp)
+ {
+ PixelFormat pf;
+diff --git a/tools/qemu-xen-traditional/console.h b/tools/qemu-xen-traditional/console.h
+index 14b42f3..8306cc4 100644
+--- a/tools/qemu-xen-traditional/console.h
++++ b/tools/qemu-xen-traditional/console.h
+@@ -98,8 +98,6 @@ struct DisplayChangeListener {
+ void (*dpy_resize)(struct DisplayState *s);
+ void (*dpy_setdata)(struct DisplayState *s);
+ void (*dpy_refresh)(struct DisplayState *s);
+- void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+ void (*dpy_fill)(struct DisplayState *s, int x, int y,
+ int w, int h, uint32_t c);
+ void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
+@@ -211,18 +209,6 @@ static inline void dpy_refresh(DisplayState *s)
+ }
+ }
+
+-static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h) {
+- struct DisplayChangeListener *dcl = s->listeners;
+- while (dcl != NULL) {
+- if (dcl->dpy_copy)
+- dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
+- else /* TODO */
+- dcl->dpy_update(s, dst_x, dst_y, w, h);
+- dcl = dcl->next;
+- }
+-}
+-
+ static inline void dpy_fill(struct DisplayState *s, int x, int y,
+ int w, int h, uint32_t c) {
+ struct DisplayChangeListener *dcl = s->listeners;
+@@ -297,8 +283,6 @@ void text_consoles_set_display(DisplayState *ds);
+ void console_select(unsigned int index);
+ void console_color_init(DisplayState *ds);
+ void qemu_console_resize(DisplayState *ds, int width, int height);
+-void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+
+ /* sdl.c */
+ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame, int opengl_enabled);
+diff --git a/tools/qemu-xen-traditional/hw/cirrus_vga.c b/tools/qemu-xen-traditional/hw/cirrus_vga.c
+index 06b4a3b..4e85b90 100644
+--- a/tools/qemu-xen-traditional/hw/cirrus_vga.c
++++ b/tools/qemu-xen-traditional/hw/cirrus_vga.c
+@@ -793,11 +793,6 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ }
+ }
+
+- /* we have to flush all pending changes so that the copy
+- is generated at the appropriate moment in time */
+- if (notify)
+- vga_hw_update();
+-
+ (*s->cirrus_rop) (s, s->vram_ptr +
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->vram_ptr +
+@@ -806,13 +801,13 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ s->cirrus_blt_width, s->cirrus_blt_height);
+
+ if (notify)
+- qemu_console_copy(s->ds,
+- sx, sy, dx, dy,
+- s->cirrus_blt_width / depth,
+- s->cirrus_blt_height);
++ dpy_update(s->ds,
++ dx, dy,
++ s->cirrus_blt_width / depth,
++ s->cirrus_blt_height);
+
+ /* we don't have to notify the display that this portion has
+- changed since qemu_console_copy implies this */
++ changed since dpy_update implies this */
+
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+diff --git a/tools/qemu-xen-traditional/hw/vmware_vga.c b/tools/qemu-xen-traditional/hw/vmware_vga.c
+index d1cba28..c38e43c 100644
+--- a/tools/qemu-xen-traditional/hw/vmware_vga.c
++++ b/tools/qemu-xen-traditional/hw/vmware_vga.c
+@@ -383,6 +383,7 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
+
+ # ifdef DIRECT_VRAM
+ if (s->ds->dpy_copy)
++# error This configuration is not supported. See XSA-211.
+ qemu_console_copy(s->ds, x0, y0, x1, y1, w, h);
+ else
+ # endif
+diff --git a/tools/qemu-xen-traditional/vnc.c b/tools/qemu-xen-traditional/vnc.c
+index 61d1555..0e61197 100644
+--- a/tools/qemu-xen-traditional/vnc.c
++++ b/tools/qemu-xen-traditional/vnc.c
+@@ -572,36 +572,6 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+ send_framebuffer_update_raw(vs, x, y, w, h);
+ }
+
+-static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
+-{
+- VncState *vs = ds->opaque;
+- int updating_client = 1;
+-
+- if (!vs->update_requested ||
+- src_x < vs->visible_x || src_y < vs->visible_y ||
+- dst_x < vs->visible_x || dst_y < vs->visible_y ||
+- (src_x + w) > (vs->visible_x + vs->visible_w) ||
+- (src_y + h) > (vs->visible_y + vs->visible_h) ||
+- (dst_x + w) > (vs->visible_x + vs->visible_w) ||
+- (dst_y + h) > (vs->visible_y + vs->visible_h))
+- updating_client = 0;
+-
+- if (updating_client)
+- _vnc_update_client(vs);
+-
+- if (updating_client && vs->csock != -1 && !vs->has_update) {
+- vnc_write_u8(vs, 0); /* msg id */
+- vnc_write_u8(vs, 0);
+- vnc_write_u16(vs, 1); /* number of rects */
+- vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
+- vnc_write_u16(vs, src_x);
+- vnc_write_u16(vs, src_y);
+- vnc_flush(vs);
+- vs->update_requested--;
+- } else
+- framebuffer_set_updated(vs, dst_x, dst_y, w, h);
+-}
+-
+ static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x)
+ {
+ int h;
+@@ -1543,16 +1513,12 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
+ vs->has_pointer_type_change = 0;
+ vs->has_WMVi = 0;
+ vs->absolute = -1;
+- dcl->dpy_copy = NULL;
+
+ for (i = n_encodings - 1; i >= 0; i--) {
+ switch (encodings[i]) {
+ case 0: /* Raw */
+ vs->has_hextile = 0;
+ break;
+- case 1: /* CopyRect */
+- dcl->dpy_copy = vnc_copy;
+- break;
+ case 5: /* Hextile */
+ vs->has_hextile = 1;
+ break;
+@@ -2459,7 +2425,6 @@ static void vnc_listen_read(void *opaque)
+ vs->has_resize = 0;
+ vs->has_hextile = 0;
+ vs->update_requested = 0;
+- dcl->dpy_copy = NULL;
+ vnc_timer_init(vs);
+ }
+ }
+--
+2.1.4
+
diff --git a/main/xen/xsa211-qemuu-4.6.patch b/main/xen/xsa211-qemuu-4.6.patch
new file mode 100644
index 00000000000..b61cca93e23
--- /dev/null
+++ b/main/xen/xsa211-qemuu-4.6.patch
@@ -0,0 +1,260 @@
+From c85f4df08b17f5808eda2b8afea1e4db7016cdc8 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 14 Feb 2017 19:09:59 +0100
+Subject: [PATCH] cirrus/vnc: zap bitblit support from console code.
+
+There is a special code path (dpy_gfx_copy) to allow graphic emulation
+notify user interface code about bitblit operations carryed out by
+guests. It is supported by cirrus and vnc server. The intended purpose
+is to optimize display scrolls and just send over the scroll op instead
+of a full display update.
+
+This is rarely used these days though because modern guests simply don't
+use the cirrus blitter any more. Any linux guest using the cirrus drm
+driver doesn't. Any windows guest newer than winxp doesn't ship with a
+cirrus driver any more and thus uses the cirrus as simple framebuffer.
+
+So this code tends to bitrot and bugs can go unnoticed for a long time.
+See for example commit "3e10c3e vnc: fix qemu crash because of SIGSEGV"
+which fixes a bug lingering in the code for almost a year, added by
+commit "c7628bf vnc: only alloc server surface with clients connected".
+
+Also the vnc server will throttle the frame rate in case it figures the
+network can't keep up (send buffers are full). This doesn't work with
+dpy_gfx_copy, for any copy operation sent to the vnc client we have to
+send all outstanding updates beforehand, otherwise the vnc client might
+run the client side blit on outdated data and thereby corrupt the
+display. So this dpy_gfx_copy "optimization" might even make things
+worse on slow network links.
+
+Lets kill it once for all.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/display/cirrus_vga.c | 12 ++-----
+ include/ui/console.h | 8 -----
+ ui/console.c | 28 ---------------
+ ui/vnc.c | 91 -------------------------------------------------
+ 4 files changed, 3 insertions(+), 136 deletions(-)
+
+diff --git a/tools/qemu-xen/hw/display/cirrus_vga.c b/tools/qemu-xen/hw/display/cirrus_vga.c
+index d643a0d..2e38c86 100644
+--- a/tools/qemu-xen/hw/display/cirrus_vga.c
++++ b/tools/qemu-xen/hw/display/cirrus_vga.c
+@@ -756,11 +756,6 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ }
+ }
+
+- /* we have to flush all pending changes so that the copy
+- is generated at the appropriate moment in time */
+- if (notify)
+- graphic_hw_update(s->vga.con);
+-
+ (*s->cirrus_rop) (s, s->vga.vram_ptr +
+ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->vga.vram_ptr +
+@@ -769,10 +764,9 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ s->cirrus_blt_width, s->cirrus_blt_height);
+
+ if (notify) {
+- qemu_console_copy(s->vga.con,
+- sx, sy, dx, dy,
+- s->cirrus_blt_width / depth,
+- s->cirrus_blt_height);
++ dpy_gfx_update(s->vga.con, dx, dy,
++ s->cirrus_blt_width / depth,
++ s->cirrus_blt_height);
+ }
+
+ /* we don't have to notify the display that this portion has
+diff --git a/tools/qemu-xen/include/ui/console.h b/tools/qemu-xen/include/ui/console.h
+index 22ef8ca..331c07a 100644
+--- a/tools/qemu-xen/include/ui/console.h
++++ b/tools/qemu-xen/include/ui/console.h
+@@ -158,10 +158,6 @@ typedef struct DisplayChangeListenerOps {
+ int x, int y, int w, int h);
+ void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
+ struct DisplaySurface *new_surface);
+- void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
+- int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+-
+ void (*dpy_text_cursor)(DisplayChangeListener *dcl,
+ int x, int y);
+ void (*dpy_text_resize)(DisplayChangeListener *dcl,
+@@ -223,8 +219,6 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info);
+ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
+ void dpy_gfx_replace_surface(QemuConsole *con,
+ DisplaySurface *surface);
+-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+ void dpy_text_cursor(QemuConsole *con, int x, int y);
+ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
+ void dpy_text_resize(QemuConsole *con, int w, int h);
+@@ -315,8 +309,6 @@ void text_consoles_set_display(DisplayState *ds);
+ void console_select(unsigned int index);
+ void console_color_init(DisplayState *ds);
+ void qemu_console_resize(QemuConsole *con, int width, int height);
+-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h);
+ DisplaySurface *qemu_console_surface(QemuConsole *con);
+ DisplayState *qemu_console_displaystate(QemuConsole *console);
+
+diff --git a/tools/qemu-xen/ui/console.c b/tools/qemu-xen/ui/console.c
+index 258af5d..cc1aa20 100644
+--- a/tools/qemu-xen/ui/console.c
++++ b/tools/qemu-xen/ui/console.c
+@@ -1450,27 +1450,6 @@ static void dpy_refresh(DisplayState *s)
+ }
+ }
+
+-void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- DisplayState *s = con->ds;
+- DisplayChangeListener *dcl;
+-
+- if (!qemu_console_is_visible(con)) {
+- return;
+- }
+- QLIST_FOREACH(dcl, &s->listeners, next) {
+- if (con != (dcl->con ? dcl->con : active_console)) {
+- continue;
+- }
+- if (dcl->ops->dpy_gfx_copy) {
+- dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
+- } else { /* TODO */
+- dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
+- }
+- }
+-}
+-
+ void dpy_text_cursor(QemuConsole *con, int x, int y)
+ {
+ DisplayState *s = con->ds;
+@@ -1968,13 +1947,6 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
+ dpy_gfx_replace_surface(s, surface);
+ }
+
+-void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- assert(con->console_type == GRAPHIC_CONSOLE);
+- dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
+-}
+-
+ DisplaySurface *qemu_console_surface(QemuConsole *console)
+ {
+ return console->surface;
+diff --git a/tools/qemu-xen/ui/vnc.c b/tools/qemu-xen/ui/vnc.c
+index 76caa897..c3c2625 100644
+--- a/tools/qemu-xen/ui/vnc.c
++++ b/tools/qemu-xen/ui/vnc.c
+@@ -733,96 +733,6 @@ int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+ return n;
+ }
+
+-static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
+-{
+- /* send bitblit op to the vnc client */
+- vnc_lock_output(vs);
+- vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+- vnc_write_u8(vs, 0);
+- vnc_write_u16(vs, 1); /* number of rects */
+- vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
+- vnc_write_u16(vs, src_x);
+- vnc_write_u16(vs, src_y);
+- vnc_unlock_output(vs);
+- vnc_flush(vs);
+-}
+-
+-static void vnc_dpy_copy(DisplayChangeListener *dcl,
+- int src_x, int src_y,
+- int dst_x, int dst_y, int w, int h)
+-{
+- VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
+- VncState *vs, *vn;
+- uint8_t *src_row;
+- uint8_t *dst_row;
+- int i, x, y, pitch, inc, w_lim, s;
+- int cmp_bytes;
+-
+- vnc_refresh_server_surface(vd);
+- QTAILQ_FOREACH_SAFE(vs, &vd->clients, next, vn) {
+- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+- vs->force_update = 1;
+- vnc_update_client(vs, 1, true);
+- /* vs might be free()ed here */
+- }
+- }
+-
+- /* do bitblit op on the local surface too */
+- pitch = vnc_server_fb_stride(vd);
+- src_row = vnc_server_fb_ptr(vd, src_x, src_y);
+- dst_row = vnc_server_fb_ptr(vd, dst_x, dst_y);
+- y = dst_y;
+- inc = 1;
+- if (dst_y > src_y) {
+- /* copy backwards */
+- src_row += pitch * (h-1);
+- dst_row += pitch * (h-1);
+- pitch = -pitch;
+- y = dst_y + h - 1;
+- inc = -1;
+- }
+- w_lim = w - (VNC_DIRTY_PIXELS_PER_BIT - (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
+- if (w_lim < 0) {
+- w_lim = w;
+- } else {
+- w_lim = w - (w_lim % VNC_DIRTY_PIXELS_PER_BIT);
+- }
+- for (i = 0; i < h; i++) {
+- for (x = 0; x <= w_lim;
+- x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
+- if (x == w_lim) {
+- if ((s = w - w_lim) == 0)
+- break;
+- } else if (!x) {
+- s = (VNC_DIRTY_PIXELS_PER_BIT -
+- (dst_x % VNC_DIRTY_PIXELS_PER_BIT));
+- s = MIN(s, w_lim);
+- } else {
+- s = VNC_DIRTY_PIXELS_PER_BIT;
+- }
+- cmp_bytes = s * VNC_SERVER_FB_BYTES;
+- if (memcmp(src_row, dst_row, cmp_bytes) == 0)
+- continue;
+- memmove(dst_row, src_row, cmp_bytes);
+- QTAILQ_FOREACH(vs, &vd->clients, next) {
+- if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+- set_bit(((x + dst_x) / VNC_DIRTY_PIXELS_PER_BIT),
+- vs->dirty[y]);
+- }
+- }
+- }
+- src_row += pitch - w * VNC_SERVER_FB_BYTES;
+- dst_row += pitch - w * VNC_SERVER_FB_BYTES;
+- y += inc;
+- }
+-
+- QTAILQ_FOREACH(vs, &vd->clients, next) {
+- if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
+- vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
+- }
+- }
+-}
+-
+ static void vnc_mouse_set(DisplayChangeListener *dcl,
+ int x, int y, int visible)
+ {
+@@ -2949,7 +2859,6 @@ static void vnc_listen_websocket_read(void *opaque)
+ static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "vnc",
+ .dpy_refresh = vnc_refresh,
+- .dpy_gfx_copy = vnc_dpy_copy,
+ .dpy_gfx_update = vnc_dpy_update,
+ .dpy_gfx_switch = vnc_dpy_switch,
+ .dpy_mouse_set = vnc_mouse_set,
+--
+2.1.4
+
diff --git a/main/xen/xsa212.patch b/main/xen/xsa212.patch
new file mode 100644
index 00000000000..2c435c41364
--- /dev/null
+++ b/main/xen/xsa212.patch
@@ -0,0 +1,87 @@
+memory: properly check guest memory ranges in XENMEM_exchange handling
+
+The use of guest_handle_okay() here (as introduced by the XSA-29 fix)
+is insufficient here, guest_handle_subrange_okay() needs to be used
+instead.
+
+Note that the uses are okay in
+- XENMEM_add_to_physmap_batch handling due to the size field being only
+ 16 bits wide,
+- livepatch_list() due to the limit of 1024 enforced on the
+ number-of-entries input (leaving aside the fact that this can be
+ called by a privileged domain only anyway),
+- compat mode handling due to counts there being limited to 32 bits,
+- everywhere else due to guest arrays being accessed sequentially from
+ index zero.
+
+This is XSA-212.
+
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+@@ -436,8 +436,8 @@ static long memory_exchange(XEN_GUEST_HA
+ goto fail_early;
+ }
+
+- if ( !guest_handle_okay(exch.in.extent_start, exch.in.nr_extents) ||
+- !guest_handle_okay(exch.out.extent_start, exch.out.nr_extents) )
++ if ( !guest_handle_subrange_okay(exch.in.extent_start, exch.nr_exchanged,
++ exch.in.nr_extents - 1) )
+ {
+ rc = -EFAULT;
+ goto fail_early;
+@@ -447,11 +447,27 @@ static long memory_exchange(XEN_GUEST_HA
+ {
+ in_chunk_order = exch.out.extent_order - exch.in.extent_order;
+ out_chunk_order = 0;
++
++ if ( !guest_handle_subrange_okay(exch.out.extent_start,
++ exch.nr_exchanged >> in_chunk_order,
++ exch.out.nr_extents - 1) )
++ {
++ rc = -EFAULT;
++ goto fail_early;
++ }
+ }
+ else
+ {
+ in_chunk_order = 0;
+ out_chunk_order = exch.in.extent_order - exch.out.extent_order;
++
++ if ( !guest_handle_subrange_okay(exch.out.extent_start,
++ exch.nr_exchanged << out_chunk_order,
++ exch.out.nr_extents - 1) )
++ {
++ rc = -EFAULT;
++ goto fail_early;
++ }
+ }
+
+ d = rcu_lock_domain_by_any_id(exch.in.domid);
+--- a/xen/include/asm-x86/x86_64/uaccess.h
++++ b/xen/include/asm-x86/x86_64/uaccess.h
+@@ -29,8 +29,9 @@ extern void *xlat_malloc(unsigned long *
+ /*
+ * Valid if in +ve half of 48-bit address space, or above Xen-reserved area.
+ * This is also valid for range checks (addr, addr+size). As long as the
+- * start address is outside the Xen-reserved area then we will access a
+- * non-canonical address (and thus fault) before ever reaching VIRT_START.
++ * start address is outside the Xen-reserved area, sequential accesses
++ * (starting at addr) will hit a non-canonical address (and thus fault)
++ * before ever reaching VIRT_START.
+ */
+ #define __addr_ok(addr) \
+ (((unsigned long)(addr) < (1UL<<47)) || \
+@@ -40,7 +41,8 @@ extern void *xlat_malloc(unsigned long *
+ (__addr_ok(addr) || is_compat_arg_xlat_range(addr, size))
+
+ #define array_access_ok(addr, count, size) \
+- (access_ok(addr, (count)*(size)))
++ (likely(((count) ?: 0UL) < (~0UL / (size))) && \
++ access_ok(addr, (count) * (size)))
+
+ #define __compat_addr_ok(d, addr) \
+ ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START(d))