aboutsummaryrefslogtreecommitdiffstats
path: root/main/xen
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2015-07-31 06:56:14 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2015-07-31 06:57:57 +0000
commit2da905892881b50d9bfe43beb3e6cd993a4eb0af (patch)
tree3b0be849f5050e6b4d25fe1fef1797fba640a151 /main/xen
parentb014d839c940b3591e749be4fc2ef7a3f6d73f24 (diff)
downloadaports-2da905892881b50d9bfe43beb3e6cd993a4eb0af.tar.bz2
aports-2da905892881b50d9bfe43beb3e6cd993a4eb0af.tar.xz
main/xen: security fixes (CVE-2015-3259,CVE-2015-5154)
ref #4493
Diffstat (limited to 'main/xen')
-rw-r--r--main/xen/APKBUILD26
-rw-r--r--main/xen/xsa137.patch231
-rw-r--r--main/xen/xsa138-qemut-1.patch77
-rw-r--r--main/xen/xsa138-qemut-2.patch71
-rw-r--r--main/xen/xsa138-qemuu-1.patch76
-rw-r--r--main/xen/xsa138-qemuu-2.patch28
-rw-r--r--main/xen/xsa138-qemuu-3.patch71
7 files changed, 579 insertions, 1 deletions
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD
index d14f3f8066..4ab51cb73b 100644
--- a/main/xen/APKBUILD
+++ b/main/xen/APKBUILD
@@ -3,7 +3,7 @@
# Maintainer: William Pitcock <nenolod@dereferenced.org>
pkgname=xen
pkgver=4.5.1
-pkgrel=1
+pkgrel=2
pkgdesc="Xen hypervisor"
url="http://www.xen.org/"
arch="x86_64"
@@ -29,6 +29,12 @@ source="http://bits.xensource.com/oss-xen/release/$pkgver/$pkgname-$pkgver.tar.g
xsa135-qemut-1.patch
xsa135-qemut-2.patch
+ xsa137.patch
+ xsa138-qemut-1.patch
+ xsa138-qemut-2.patch
+ xsa138-qemuu-1.patch
+ xsa138-qemuu-2.patch
+ xsa138-qemuu-3.patch
qemu-coroutine-gthread.patch
qemu-xen-musl-openpty.patch
@@ -221,6 +227,12 @@ e26becb8a6a2b6695f6b3e8097593db8 tpm_emulator-0.7.4.tar.gz
debc62758716a169df9f62e6ab2bc634 zlib-1.2.3.tar.gz
8035908817374d2d32aaadf942e3391d xsa135-qemut-1.patch
462f5d784493119bdfa6e7b5a628a88d xsa135-qemut-2.patch
+b15a4247812342c2febb26e43be01dc0 xsa137.patch
+80133dcbd2d2d0dcfcfc82b2172daec4 xsa138-qemut-1.patch
+bbe64473d94e5e059edfaac114067cc4 xsa138-qemut-2.patch
+c58f36d469d98f40eab478635b214a5d xsa138-qemuu-1.patch
+d0365ffb471ba1acb7227c07d15f5e3a xsa138-qemuu-2.patch
+86cc3fcc24da1b46473dae6a04f1af2e xsa138-qemuu-3.patch
de1a3db370b87cfb0bddb51796b50315 qemu-coroutine-gthread.patch
dd8603eaab5857816843bfc37647d569 qemu-xen-musl-openpty.patch
08bfdf8caff5d631f53660bf3fd4edaf qemu-xen_paths.patch
@@ -257,6 +269,12 @@ f60ae61cfbd5da1d849d0beaa21f593c38dac9359f0b3ddc612f447408265b24 pciutils-2.2.9
1795c7d067a43174113fdf03447532f373e1c6c57c08d61d9e4e9be5e244b05e zlib-1.2.3.tar.gz
b4b66d772e52ec35f7256b168ac68f5cf0901590112b3b4db860d1b9c2f513f6 xsa135-qemut-1.patch
0d98a8c4498390a93665872dea9b4b00781578e95e6c78a49632bacb5f70edb8 xsa135-qemut-2.patch
+0272c443575c88b53445c89ef84f0cd98a03944d3303f06c66c33ef0037d97b9 xsa137.patch
+134b697539eb0c68326cdeec9672dbed93bc81b7e31301993599ac9311b7c6a4 xsa138-qemut-1.patch
+53c05aee8d819507e6ca5b7ea7dd929f9afcfcd29068ae5228b2ef00828045bf xsa138-qemut-2.patch
+855199d5cfd6bbc171129ef864cf8c6f7c4f6a0ac5159275154b6477f9b77727 xsa138-qemuu-1.patch
+9f67687e09b6d62772c430f57db56caec061f592a24e937c6954a6a73afaed22 xsa138-qemuu-2.patch
+e4d4691d4bf00d6a5175cc6c75346a7d4663bec0af54fd6b67c78a2278daa5ef xsa138-qemuu-3.patch
3941f99b49c7e8dafc9fae8aad2136a14c6d84533cd542cc5f1040a41ef7c6fe qemu-coroutine-gthread.patch
fe76c7c8faf686060b20491bfed4a13ce37b1bc3dcdbf33d242e388cee14c7c1 qemu-xen-musl-openpty.patch
e4e5e838e259a3116978aabbcebc1865a895179a7fcbf4bad195c83e9b4c0f98 qemu-xen_paths.patch
@@ -293,6 +311,12 @@ c5cb1cdff40d2d71fd3e692a9d0efadf2aa17290daf5195391a1c81ddd9dfc913a8e44d5be2b12be
021b958fcd0d346c4ba761bcf0cc40f3522de6186cf5a0a6ea34a70504ce9622b1c2626fce40675bc8282cf5f5ade18473656abc38050f72f5d6480507a2106e zlib-1.2.3.tar.gz
68824ec4d8a201c9687bd2de82489730908a70914243067f9e76a2584ce73212fd55ec00d6cf1301f7d1c73e32c9e46a93d3da4a6a61781ddec4f863190fb02b xsa135-qemut-1.patch
c29683569affcef4d45ec510b0b8b6d7c4466fc3026005b0612876ce1b7dc52ead77880a3204b5df78d836bdf197b872780c67afd49a895f9f7a47aabf3d9064 xsa135-qemut-2.patch
+00a45a430467b708c04d0ee9a25decbdf542eb6d8b6623bb71c87ad6c22880aa12cbf4d070a958e40c9901a99262459e6913b89f192eb31e1addecc2a4fa387d xsa137.patch
+6f648cd7447e82163b9b920473a6605c4879a656886ead395130022df8f89c630c5311f6eb66d12d9fdeaead36f25c02b4b401ae6432fe6ba1e7ae91da8b0a1d xsa138-qemut-1.patch
+64c3435d96b78fd677214508fb811c6de2b5df3b66e824c48010f2f7e6c644fa423a4a45a7135bf1538f3701e744ec9080922218ae73135ef52387d92e1b2468 xsa138-qemut-2.patch
+68d72eb311deab03cb2816b508148169bc5fae712ca98ea5959738c056ae2440a11534d4eb455f5db0fe79c3f1c3881a2449a5c91064e35dbc84a87c2b0ac43c xsa138-qemuu-1.patch
+cb307f4191c96bd61a565f248517d5905243e8888bc2999e677e4f2bdb48994153e4319021b0a9d27ef08038d4e6e8b993dfac021a8e1e4a1134604b7d8b8f4c xsa138-qemuu-2.patch
+8e1dc230a6ae8a22913a68dfce67af9115859e71ac0440c0078c1bd8a0995b0abbbf1379aba60b786732c1e00af4b75e1231c520bf50cd88ea6848f4dabad013 xsa138-qemuu-3.patch
c3c46f232f0bd9f767b232af7e8ce910a6166b126bd5427bb8dc325aeb2c634b956de3fc225cab5af72649070c8205cc8e1cab7689fc266c204f525086f1a562 qemu-coroutine-gthread.patch
a8b7378516172389450834985e8558d7a86d7cd808154bdc846bb98325e40fc4e87b1fc6d725297f4bef6eb54ebcbcbfa4d9d0363d83f635755795fb0726e006 qemu-xen-musl-openpty.patch
1936ab39a1867957fa640eb81c4070214ca4856a2743ba7e49c0cd017917071a9680d015f002c57fa7b9600dbadd29dcea5887f50e6c133305df2669a7a933f3 qemu-xen_paths.patch
diff --git a/main/xen/xsa137.patch b/main/xen/xsa137.patch
new file mode 100644
index 0000000000..ffc7fa7d49
--- /dev/null
+++ b/main/xen/xsa137.patch
@@ -0,0 +1,231 @@
+From 593fe52faa1b85567a7ec20c69d8cfbc7368ae5b Mon Sep 17 00:00:00 2001
+From: Ian Jackson <ian.jackson@eu.citrix.com>
+Date: Mon, 15 Jun 2015 14:50:42 +0100
+Subject: [PATCH] xl: Sane handling of extra config file arguments
+
+Various xl sub-commands take additional parameters containing = as
+additional config fragments.
+
+The handling of these config fragments has a number of bugs:
+
+ 1. Use of a static 1024-byte buffer. (If truncation would occur,
+ with semi-trusted input, a security risk arises due to quotes
+ being lost.)
+
+ 2. Mishandling of the return value from snprintf, so that if
+ truncation occurs, the to-write pointer is updated with the
+ wanted-to-write length, resulting in stack corruption. (This is
+ XSA-137.)
+
+ 3. Clone-and-hack of the code for constructing the appended
+ config file.
+
+These are fixed here, by introducing a new function
+`string_realloc_append' and using it everywhere. The `extra_info'
+buffers are replaced by pointers, which start off NULL and are
+explicitly freed on all return paths.
+
+The separate variable which will become dom_info.extra_config is
+abolished (which involves moving the clearing of dom_info).
+
+Additional bugs I observe, not fixed here:
+
+ 4. The functions which now call string_realloc_append use ad-hoc
+ error returns, with multiple calls to `return'. This currently
+ necessitates multiple new calls to `free'.
+
+ 5. Many of the paths in xl call exit(-rc) where rc is a libxl status
+ code. This is a ridiculous exit status `convention'.
+
+ 6. The loops for handling extra config data are clone-and-hacks.
+
+ 7. Once the extra config buffer is accumulated, it must be combined
+ with the appropriate main config file. The code to do this
+ combining is clone-and-hacked too.
+
+Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
+Tested-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
+Acked-by: Ian Campbell <ian,campbell@citrix.com>
+---
+v2: Use SSIZE_MAX, not INT_MAX.
+ Check *accumulate for NULL, not accumulate.
+ Move memset of dom_info.
+---
+ tools/libxl/xl_cmdimpl.c | 64 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 40 insertions(+), 24 deletions(-)
+
+diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
+index c858068..c01a851 100644
+--- a/tools/libxl/xl_cmdimpl.c
++++ b/tools/libxl/xl_cmdimpl.c
+@@ -151,7 +151,7 @@ struct domain_create {
+ int console_autoconnect;
+ int checkpointed_stream;
+ const char *config_file;
+- const char *extra_config; /* extra config string */
++ char *extra_config; /* extra config string */
+ const char *restore_file;
+ int migrate_fd; /* -1 means none */
+ char **migration_domname_r; /* from malloc */
+@@ -4805,11 +4805,25 @@ int main_vm_list(int argc, char **argv)
+ return 0;
+ }
+
++static void string_realloc_append(char **accumulate, const char *more)
++{
++ /* Appends more to accumulate. Accumulate is either NULL, or
++ * points (always) to a malloc'd nul-terminated string. */
++
++ size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
++ size_t morelen = strlen(more) + 1/*nul*/;
++ if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
++ fprintf(stderr,"Additional config data far too large\n");
++ exit(-ERROR_FAIL);
++ }
++
++ *accumulate = xrealloc(*accumulate, oldlen + morelen);
++ memcpy(*accumulate + oldlen, more, morelen);
++}
++
+ int main_create(int argc, char **argv)
+ {
+ const char *filename = NULL;
+- char *p;
+- char extra_config[1024];
+ struct domain_create dom_info;
+ int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0,
+ quiet = 0, monitor = 1, vnc = 0, vncautopass = 0;
+@@ -4824,6 +4838,8 @@ int main_create(int argc, char **argv)
+ {0, 0, 0, 0}
+ };
+
++ dom_info.extra_config = NULL;
++
+ if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
+ filename = argv[1];
+ argc--; argv++;
+@@ -4863,20 +4879,21 @@ int main_create(int argc, char **argv)
+ break;
+ }
+
+- extra_config[0] = '\0';
+- for (p = extra_config; optind < argc; optind++) {
++ memset(&dom_info, 0, sizeof(dom_info));
++
++ for (; optind < argc; optind++) {
+ if (strchr(argv[optind], '=') != NULL) {
+- p += snprintf(p, sizeof(extra_config) - (p - extra_config),
+- "%s\n", argv[optind]);
++ string_realloc_append(&dom_info.extra_config, argv[optind]);
++ string_realloc_append(&dom_info.extra_config, "\n");
+ } else if (!filename) {
+ filename = argv[optind];
+ } else {
+ help("create");
++ free(dom_info.extra_config);
+ return 2;
+ }
+ }
+
+- memset(&dom_info, 0, sizeof(dom_info));
+ dom_info.debug = debug;
+ dom_info.daemonize = daemonize;
+ dom_info.monitor = monitor;
+@@ -4884,16 +4901,18 @@ int main_create(int argc, char **argv)
+ dom_info.dryrun = dryrun_only;
+ dom_info.quiet = quiet;
+ dom_info.config_file = filename;
+- dom_info.extra_config = extra_config;
+ dom_info.migrate_fd = -1;
+ dom_info.vnc = vnc;
+ dom_info.vncautopass = vncautopass;
+ dom_info.console_autoconnect = console_autoconnect;
+
+ rc = create_domain(&dom_info);
+- if (rc < 0)
++ if (rc < 0) {
++ free(dom_info.extra_config);
+ return -rc;
++ }
+
++ free(dom_info.extra_config);
+ return 0;
+ }
+
+@@ -4901,8 +4920,7 @@ int main_config_update(int argc, char **argv)
+ {
+ uint32_t domid;
+ const char *filename = NULL;
+- char *p;
+- char extra_config[1024];
++ char *extra_config = NULL;
+ void *config_data = 0;
+ int config_len = 0;
+ libxl_domain_config d_config;
+@@ -4940,15 +4958,15 @@ int main_config_update(int argc, char **argv)
+ break;
+ }
+
+- extra_config[0] = '\0';
+- for (p = extra_config; optind < argc; optind++) {
++ for (; optind < argc; optind++) {
+ if (strchr(argv[optind], '=') != NULL) {
+- p += snprintf(p, sizeof(extra_config) - (p - extra_config),
+- "%s\n", argv[optind]);
++ string_realloc_append(&extra_config, argv[optind]);
++ string_realloc_append(&extra_config, "\n");
+ } else if (!filename) {
+ filename = argv[optind];
+ } else {
+ help("create");
++ free(extra_config);
+ return 2;
+ }
+ }
+@@ -4957,7 +4975,8 @@ int main_config_update(int argc, char **argv)
+ rc = libxl_read_file_contents(ctx, filename,
+ &config_data, &config_len);
+ if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n",
+- filename, strerror(errno)); return ERROR_FAIL; }
++ filename, strerror(errno));
++ free(extra_config); return ERROR_FAIL; }
+ if (strlen(extra_config)) {
+ if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) {
+ fprintf(stderr, "Failed to attach extra configration\n");
+@@ -4998,7 +5017,7 @@ int main_config_update(int argc, char **argv)
+ libxl_domain_config_dispose(&d_config);
+
+ free(config_data);
+-
++ free(extra_config);
+ return 0;
+ }
+
+@@ -7255,7 +7274,7 @@ int main_cpupoolcreate(int argc, char **argv)
+ {
+ const char *filename = NULL, *config_src=NULL;
+ const char *p;
+- char extra_config[1024];
++ char *extra_config = NULL;
+ int opt;
+ static struct option opts[] = {
+ {"defconfig", 1, 0, 'f'},
+@@ -7289,13 +7308,10 @@ int main_cpupoolcreate(int argc, char **argv)
+ break;
+ }
+
+- memset(extra_config, 0, sizeof(extra_config));
+ while (optind < argc) {
+ if ((p = strchr(argv[optind], '='))) {
+- if (strlen(extra_config) + 1 + strlen(argv[optind]) < sizeof(extra_config)) {
+- strcat(extra_config, "\n");
+- strcat(extra_config, argv[optind]);
+- }
++ string_realloc_append(&extra_config, "\n");
++ string_realloc_append(&extra_config, argv[optind]);
+ } else if (!filename) {
+ filename = argv[optind];
+ } else {
+--
+1.7.10.4
+
diff --git a/main/xen/xsa138-qemut-1.patch b/main/xen/xsa138-qemut-1.patch
new file mode 100644
index 0000000000..cfbeb1d26d
--- /dev/null
+++ b/main/xen/xsa138-qemut-1.patch
@@ -0,0 +1,77 @@
+From 510952d4c33ee69574167ce30829b21c815a165b Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Wed, 3 Jun 2015 14:13:31 +0200
+Subject: [PATCH 1/2] ide: Check array bounds before writing to io_buffer
+ (CVE-2015-5154)
+
+If the end_transfer_func of a command is called because enough data has
+been read or written for the current PIO transfer, and it fails to
+correctly call the command completion functions, the DRQ bit in the
+status register and s->end_transfer_func may remain set. This allows the
+guest to access further bytes in s->io_buffer beyond s->data_end, and
+eventually overflowing the io_buffer.
+
+One case where this currently happens is emulation of the ATAPI command
+START STOP UNIT.
+
+This patch fixes the problem by adding explicit array bounds checks
+before accessing the buffer instead of relying on end_transfer_func to
+function correctly.
+
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ hw/ide.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/hw/ide.c b/hw/ide.c
+index 791666b..211ec88 100644
+--- a/tools/qemu-xen-traditional/hw/ide.c
++++ b/tools/qemu-xen-traditional/hw/ide.c
+@@ -3002,6 +3002,10 @@ static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
+ buffered_pio_write(s, addr, 2);
+
+ p = s->data_ptr;
++ if (p + 2 > s->data_end) {
++ return;
++ }
++
+ *(uint16_t *)p = le16_to_cpu(val);
+ p += 2;
+ s->data_ptr = p;
+@@ -3021,6 +3025,10 @@ static uint32_t ide_data_readw(void *opaque, uint32_t addr)
+ buffered_pio_read(s, addr, 2);
+
+ p = s->data_ptr;
++ if (p + 2 > s->data_end) {
++ return 0;
++ }
++
+ ret = cpu_to_le16(*(uint16_t *)p);
+ p += 2;
+ s->data_ptr = p;
+@@ -3040,6 +3048,10 @@ static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
+ buffered_pio_write(s, addr, 4);
+
+ p = s->data_ptr;
++ if (p + 4 > s->data_end) {
++ return;
++ }
++
+ *(uint32_t *)p = le32_to_cpu(val);
+ p += 4;
+ s->data_ptr = p;
+@@ -3059,6 +3071,10 @@ static uint32_t ide_data_readl(void *opaque, uint32_t addr)
+ buffered_pio_read(s, addr, 4);
+
+ p = s->data_ptr;
++ if (p + 4 > s->data_end) {
++ return 0;
++ }
++
+ ret = cpu_to_le32(*(uint32_t *)p);
+ p += 4;
+ s->data_ptr = p;
+--
+2.1.4
+
diff --git a/main/xen/xsa138-qemut-2.patch b/main/xen/xsa138-qemut-2.patch
new file mode 100644
index 0000000000..1389ced4c3
--- /dev/null
+++ b/main/xen/xsa138-qemut-2.patch
@@ -0,0 +1,71 @@
+From 1ac0f60d558b7fca55c69a61ab4c4538af1f02f9 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Wed, 3 Jun 2015 14:41:27 +0200
+Subject: [PATCH 2/2] ide: Clear DRQ after handling all expected accesses
+
+This is additional hardening against an end_transfer_func that fails to
+clear the DRQ status bit. The bit must be unset as soon as the PIO
+transfer has completed, so it's better to do this in a central place
+instead of duplicating the code in all commands (and forgetting it in
+some).
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ hw/ide.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/hw/ide.c b/hw/ide.c
+index 211ec88..7b84d1b 100644
+--- a/tools/qemu-xen-traditional/hw/ide.c
++++ b/tools/qemu-xen-traditional/hw/ide.c
+@@ -3009,8 +3009,10 @@ static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
+ *(uint16_t *)p = le16_to_cpu(val);
+ p += 2;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ }
+
+ static uint32_t ide_data_readw(void *opaque, uint32_t addr)
+@@ -3032,8 +3034,10 @@ static uint32_t ide_data_readw(void *opaque, uint32_t addr)
+ ret = cpu_to_le16(*(uint16_t *)p);
+ p += 2;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ return ret;
+ }
+
+@@ -3055,8 +3059,10 @@ static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
+ *(uint32_t *)p = le32_to_cpu(val);
+ p += 4;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ }
+
+ static uint32_t ide_data_readl(void *opaque, uint32_t addr)
+@@ -3078,8 +3084,10 @@ static uint32_t ide_data_readl(void *opaque, uint32_t addr)
+ ret = cpu_to_le32(*(uint32_t *)p);
+ p += 4;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ return ret;
+ }
+
+--
+2.1.4
+
diff --git a/main/xen/xsa138-qemuu-1.patch b/main/xen/xsa138-qemuu-1.patch
new file mode 100644
index 0000000000..333d064750
--- /dev/null
+++ b/main/xen/xsa138-qemuu-1.patch
@@ -0,0 +1,76 @@
+From a9de14175548c04e0f8be7fae219246509ba46a9 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Wed, 3 Jun 2015 14:13:31 +0200
+Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer
+ (CVE-2015-5154)
+
+If the end_transfer_func of a command is called because enough data has
+been read or written for the current PIO transfer, and it fails to
+correctly call the command completion functions, the DRQ bit in the
+status register and s->end_transfer_func may remain set. This allows the
+guest to access further bytes in s->io_buffer beyond s->data_end, and
+eventually overflowing the io_buffer.
+
+One case where this currently happens is emulation of the ATAPI command
+START STOP UNIT.
+
+This patch fixes the problem by adding explicit array bounds checks
+before accessing the buffer instead of relying on end_transfer_func to
+function correctly.
+
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ hw/ide/core.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 122e955..44fcc23 100644
+--- a/tools/qemu-xen/hw/ide/core.c
++++ b/tools/qemu-xen/hw/ide/core.c
+@@ -2021,6 +2021,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
+ }
+
+ p = s->data_ptr;
++ if (p + 2 > s->data_end) {
++ return;
++ }
++
+ *(uint16_t *)p = le16_to_cpu(val);
+ p += 2;
+ s->data_ptr = p;
+@@ -2042,6 +2046,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
+ }
+
+ p = s->data_ptr;
++ if (p + 2 > s->data_end) {
++ return 0;
++ }
++
+ ret = cpu_to_le16(*(uint16_t *)p);
+ p += 2;
+ s->data_ptr = p;
+@@ -2063,6 +2071,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
+ }
+
+ p = s->data_ptr;
++ if (p + 4 > s->data_end) {
++ return;
++ }
++
+ *(uint32_t *)p = le32_to_cpu(val);
+ p += 4;
+ s->data_ptr = p;
+@@ -2084,6 +2096,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
+ }
+
+ p = s->data_ptr;
++ if (p + 4 > s->data_end) {
++ return 0;
++ }
++
+ ret = cpu_to_le32(*(uint32_t *)p);
+ p += 4;
+ s->data_ptr = p;
+--
+1.8.3.1
diff --git a/main/xen/xsa138-qemuu-2.patch b/main/xen/xsa138-qemuu-2.patch
new file mode 100644
index 0000000000..ab0ce5f323
--- /dev/null
+++ b/main/xen/xsa138-qemuu-2.patch
@@ -0,0 +1,28 @@
+From aa851d30acfbb9580098ac1dc82885530cb8b3c1 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Wed, 3 Jun 2015 14:17:46 +0200
+Subject: [PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion
+
+The command must be completed on all code paths. START STOP UNIT with
+pwrcnd set should succeed without doing anything.
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ hw/ide/atapi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
+index 950e311..79dd167 100644
+--- a/tools/qemu-xen/hw/ide/atapi.c
++++ b/tools/qemu-xen/hw/ide/atapi.c
+@@ -983,6 +983,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
+
+ if (pwrcnd) {
+ /* eject/load only happens for power condition == 0 */
++ ide_atapi_cmd_ok(s);
+ return;
+ }
+
+--
+1.8.3.1
+
diff --git a/main/xen/xsa138-qemuu-3.patch b/main/xen/xsa138-qemuu-3.patch
new file mode 100644
index 0000000000..0322866fe3
--- /dev/null
+++ b/main/xen/xsa138-qemuu-3.patch
@@ -0,0 +1,71 @@
+From 1d3c2268f8708126a34064c2e0c1000b40e6f3e5 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf@redhat.com>
+Date: Wed, 3 Jun 2015 14:41:27 +0200
+Subject: [PATCH 3/3] ide: Clear DRQ after handling all expected accesses
+
+This is additional hardening against an end_transfer_func that fails to
+clear the DRQ status bit. The bit must be unset as soon as the PIO
+transfer has completed, so it's better to do this in a central place
+instead of duplicating the code in all commands (and forgetting it in
+some).
+
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+---
+ hw/ide/core.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 44fcc23..50449ca 100644
+--- a/tools/qemu-xen/hw/ide/core.c
++++ b/tools/qemu-xen/hw/ide/core.c
+@@ -2028,8 +2028,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
+ *(uint16_t *)p = le16_to_cpu(val);
+ p += 2;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ }
+
+ uint32_t ide_data_readw(void *opaque, uint32_t addr)
+@@ -2053,8 +2055,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
+ ret = cpu_to_le16(*(uint16_t *)p);
+ p += 2;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ return ret;
+ }
+
+@@ -2078,8 +2082,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
+ *(uint32_t *)p = le32_to_cpu(val);
+ p += 4;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ }
+
+ uint32_t ide_data_readl(void *opaque, uint32_t addr)
+@@ -2103,8 +2109,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
+ ret = cpu_to_le32(*(uint32_t *)p);
+ p += 4;
+ s->data_ptr = p;
+- if (p >= s->data_end)
++ if (p >= s->data_end) {
++ s->status &= ~DRQ_STAT;
+ s->end_transfer_func(s);
++ }
+ return ret;
+ }
+
+--
+1.8.3.1
+