El 30/06/18 a las 17:51, Guido Günther escribió: > On Sat, Jun 30, 2018 at 05:42:37PM +0200, Santiago R.R. wrote: > > Dear security team, > > > > I am working on the jessie package of qemu (the first time I work on > > it), and I notice it hasn't been updated in jessie since May 2017. > > There were various stretch updates since then, and I wonder if the > > reason why jessie wasn't updated was mainly lack of time/resources, or > > is there anything else I should be aware of (and I am missing in the > > doc)? > > Please look at what was done for the wheezy package. I backported some > drivers from newer QEMU versions (cirrus, 9pfs) and this is needed in > Jessie as well for further security updates to make sense. If there's no > rush I can also take a look. Thanks Guido for the offer. If it is still valid, could you please review the attached debdiff? I had indeed taken into account what was done on wheezy, and also the patches from stretch and ubuntu. For the moment, I have tested simple uses cases (creating images, installing a system, accessing them via vnc…), and I will do more later. For this release, that would fix a large number of CVEs, I find it particularly helpful to have some feedback. As usual, test packages are available at: deb https://people.debian.org/~santiago/debian santiago-jessie-security/ deb-src https://people.debian.org/~santiago/debian santiago-jessie-security Cheers, Santiago P.S. I still have to address CVE-2018-5683 and CVE-2018-7550, but I prefer to publish the current state. I will send the new debdiff and publish an updated version of the packages in a couple of days.
diff -Nru qemu-2.1+dfsg/debian/changelog qemu-2.1+dfsg/debian/changelog --- qemu-2.1+dfsg/debian/changelog 2016-05-08 15:35:16.000000000 +0200 +++ qemu-2.1+dfsg/debian/changelog 2018-07-29 15:33:43.000000000 +0200 @@ -1,3 +1,99 @@ +qemu (1:2.1+dfsg-12+deb8u7~4.gbpf05699) UNRELEASED; urgency=medium + + ** SNAPSHOT build @f05699642f8998227d18299f710abc06227b6b76 ** + + * Non-maintainer upload by the LTS Team. + * Add CVE-2016-2198-usb-ehci-add-capability-mmio-write-function.patch + (Closes: #813193) + * Add CVE-2016-6833-vmxnet3-check-for-device_active-before-write.patch + (Closes: #834904) + * Add CVE-2016-6835-net-vmxnet-check-IP-header-length.patch + (Closes: #835031) + * Add CVE-2016-9603-cirrus-vnc-zap-bitblit-support-from-console-code.patch + (Closes: #857744) + * Add CVE-2016-8576-fix-infinite-loop.patch + * CVE-2016-8667: dma: rc4030 divide by zero error in set_next_tick allowing + local guest OS administrators to cause a DoS via a large interval timer + reload value. + (Closes: #840950) + * CVE-2016-8669: char: divide by zero error in serial_update_parameters + (Closes: #840945) + * CVE-2016-9602: 9p: virtfs allows guest to access host filesystem + (Closes: #853006) + * CVE-2016-9776: net: mcf_fec: infinite loop while receiving data in + mcf_fec_receive + * CVE-2016-9907: usb: redirector: memory leakage when destroying redirector + (Closes: #847953) + * CVE-2016-9911: usb: ehci: memory leakage in ehci_init_transfer + (Closes: #847951) + * CVE-2016-9914: 9pfs: add missing cleanup operation in FileOperations + (Closes: #847496) + * CVE-2016-9915: 9pfs: add missing cleanup operation in the handle backend. + * CVE-2016-9916: 9pfs: add missing cleanup operation in the proxy backend + driver + * CVE-2016-9921, CVE-2016-9922: display: cirrus_vga: a divide by zero in + cirrus_do_copy + (Closes: #847960) + * CVE-2016-10155: Memory leak in hw/watchdog/wdt_i6300esb.c allowing local + guest OS privileged users to cause a denial of service (host memory + consumption and QEMU process crash) via a large number of device unplug + operations. + (Closes: #852232) + * CVE-2017-2615: cirrus: out-of-bounds access issue + * Add CVE-2017-2620-cirrus-add-blit_is_unsafe-call-to-cirrus_bi.patch + * CVE-2017-5525: memory leakage in ac97 device + * CVE-2017-5526: memory leakage in es1370 device (Closes: #851910) + * CVE-2017-5579: serial: host memory leakage 16550A UART emulation + (Closes: #853002) + * CVE-2017-5667: sd: sdhci: check data length during dma_memory_read + (Closes: #853996) + * CVE-2017-5715: mitigations against the Spectre v2 vulnerability. + (Closes: #886532) + * CVE-2017-5856: Memory leak in the megasas_handle_dcmd function in + hw/scsi/megasas.cc + (Closes: #853996) + * CVE-2017-5987: sd: infinite loop issue in multi block transfers + * CVE-2017-5973: infinite loop while doing control transfer in xhci_kick_epctx + * CVE-2017-6505: infinite loop issue in ohci_service_ed_list + * CVE-2017-7377: 9pfs: host memory leakage via v9fs_create + * CVE-2017-7471: improper access control issue + * CVE-2017-7493: 9pfs access control issue + * CVE-2017-7718: cirrus out-of-bounds access issue + * CVE-2017-7980: cirrus: heap-based buffer overflow + * CVE-2017-8086: 9pfs: host memory leakage via v9pfs_list_xattr + * CVE-2017-8112: vmw_pvscsi: infinite loop in pvscsi_log2 (Closes: #861351) + * CVE-2017-8309: audio: host memory leakage via capture buffer + * CVE-2017-8379: input: host memory lekage via keyboard + * CVE-2017-9330: usb: ohci: infinite loop due to incorrect return value + * CVE-2017-9373 ide: ahci host memory leakage during hotunplug. + CVE-2017-9374: usb: ehci host memory leakage during hotunplug + (Closes: #864216, #864568) + * CVE-2017-9503: megasas: null pointer dereference while processing megasas + command + (Closes: 865754) + * CVE-2017-10664: qemu-nbd: server breaks with SIGPIPE upon client abort + (Closes: #866674) + * CVE-2017-10806: usb-redirect: stack buffer overflow in debug logging + (Closes: #867751) + * Add xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch + (Closes: #869706) + * CVE-2017-11434: slirp: out-of-bounds read while parsing dhcp options + (Closes: #869171) + * CVE-2017-14167: i386: multiboot OOB access while loading guest kernel + image + (Closes: #874606) + * CVE-2017-15038: 9p: virtfs: information disclosure when reading extended + attributes + (Closes: #877890) + * CVE-2017-15289: cirrus: OOB access issue in mode4and5 write functions + (Closes: #880832) + * CVE-2017-16845: ps2: information leakage via post_load routine + (Closes: #882136) + * CVE-2017-18030: cirrus out-of-bounds array access + * CVE-2017-18043: Integer overflow in the macro ROUND_UP (n, d) + + -- Santiago R.R. <santiagorr@riseup.net> Sun, 29 Jul 2018 15:33:43 +0200 + qemu (1:2.1+dfsg-12+deb8u6) jessie-security; urgency=high * Non-maintainer upload by the Security Team. diff -Nru qemu-2.1+dfsg/debian/patches/0001-cirrus-fix-oob-access-issue-CVE-2017-2615.patch qemu-2.1+dfsg/debian/patches/0001-cirrus-fix-oob-access-issue-CVE-2017-2615.patch --- qemu-2.1+dfsg/debian/patches/0001-cirrus-fix-oob-access-issue-CVE-2017-2615.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/0001-cirrus-fix-oob-access-issue-CVE-2017-2615.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,50 @@ +Origin: backported, https://git.qemu.org/?p=qemu.git;a=commit;h=f054cead44cef75d330cfba39aa0c46be483813d +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> + +From f054cead44cef75d330cfba39aa0c46be483813d Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Wed, 1 Feb 2017 09:35:01 +0100 +Subject: [PATCH] cirrus: fix oob access issue (CVE-2017-2615) + +When doing bitblt copy in backward mode, we should minus the +blt width first just like the adding in the forward mode. This +can avoid the oob access of the front of vga's vram. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> + +{ kraxel: with backward blits (negative pitch) addr is the topmost + address, so check it as-is against vram size ] + +Cc: qemu-stable@nongnu.org +Cc: P J P <ppandit@redhat.com> +Cc: Laszlo Ersek <lersek@redhat.com> +Cc: Paolo Bonzini <pbonzini@redhat.com> +Cc: Wolfgang Bumiller <w.bumiller@proxmox.com> +Fixes: d3532a0db02296e687711b8cdc7791924efccea0 (CVE-2014-8106) +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1485938101-26602-1-git-send-email-kraxel@redhat.com +Reviewed-by: Laszlo Ersek <lersek@redhat.com> +(cherry picked from commit 62d4c6bd5263bb8413a06c80144fc678df6dfb64) +Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com> +--- + hw/display/cirrus_vga.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +Index: qemu/hw/display/cirrus_vga.c +=================================================================== +--- qemu.orig/hw/display/cirrus_vga.c ++++ qemu/hw/display/cirrus_vga.c +@@ -272,10 +272,9 @@ static bool blit_region_is_unsafe(struct + } + if (pitch < 0) { + int64_t min = addr +- + ((int64_t)s->cirrus_blt_height-1) * pitch; +- int32_t max = addr +- + s->cirrus_blt_width; +- if (min < 0 || max >= s->vga.vram_size) { ++ + ((int64_t)s->cirrus_blt_height - 1) * pitch ++ - s->cirrus_blt_width; ++ if (min < -1 || addr >= s->vga.vram_size) { + return true; + } + } else { diff -Nru qemu-2.1+dfsg/debian/patches/9pfs-local-forbid-client-access-to-metadata-CVE-2017-7493.patch qemu-2.1+dfsg/debian/patches/9pfs-local-forbid-client-access-to-metadata-CVE-2017-7493.patch --- qemu-2.1+dfsg/debian/patches/9pfs-local-forbid-client-access-to-metadata-CVE-2017-7493.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/9pfs-local-forbid-client-access-to-metadata-CVE-2017-7493.patch 2018-06-29 21:25:26.000000000 +0200 @@ -0,0 +1,174 @@ +From: Greg Kurz <groug@kaod.org> +Date: Fri, 5 May 2017 14:48:08 +0200 +Subject: 9pfs: local: forbid client access to metadata (CVE-2017-7493) +Commit-Id: 7a95434e0ca8a037fd8aa1a2e2461f92585eb77b + +When using the mapped-file security mode, we shouldn't let the client mess +with the metadata. The current code already tries to hide the metadata dir +from the client by skipping it in local_readdir(). But the client can still +access or modify it through several other operations. This can be used to +escalate privileges in the guest. + +Affected backend operations are: +- local_mknod() +- local_mkdir() +- local_open2() +- local_symlink() +- local_link() +- local_unlinkat() +- local_renameat() +- local_rename() +- local_name_to_path() + +Other operations are safe because they are only passed a fid path, which +is computed internally in local_name_to_path(). + +This patch converts all the functions listed above to fail and return +EINVAL when being passed the name of the metadata dir. This may look +like a poor choice for errno, but there's no such thing as an illegal +path name on Linux and I could not think of anything better. + +This fixes CVE-2017-7493. + +Reported-by: Leo Gaspard <leo@gaspard.io> +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Eric Blake <eblake@redhat.com> +--- + hw/9pfs/9p-local.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 56 insertions(+), 2 deletions(-) + +diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c +index f3ebca4f7a..a2486566af 100644 +--- a/hw/9pfs/9p-local.c ++++ b/hw/9pfs/9p-local.c +@@ -452,6 +452,11 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) + return telldir(fs->dir.stream); + } + ++static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name) ++{ ++ return !strcmp(name, VIRTFS_META_DIR); ++} ++ + static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs) + { + struct dirent *entry; +@@ -465,8 +470,8 @@ again: + if (ctx->export_flags & V9FS_SM_MAPPED) { + entry->d_type = DT_UNKNOWN; + } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- if (!strcmp(entry->d_name, VIRTFS_META_DIR)) { +- /* skp the meta data directory */ ++ if (local_is_mapped_file_metadata(ctx, entry->d_name)) { ++ /* skip the meta data directory */ + goto again; + } + entry->d_type = DT_UNKNOWN; +@@ -559,6 +564,12 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); + if (dirfd == -1) { + return -1; +@@ -605,6 +616,12 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); + if (dirfd == -1) { + return -1; +@@ -694,6 +711,12 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + /* + * Mark all the open to not follow symlinks + */ +@@ -752,6 +775,12 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); + if (dirfd == -1) { + return -1; +@@ -826,6 +855,12 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath, + int ret = -1; + int odirfd, ndirfd; + ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + odirfd = local_opendir_nofollow(ctx, odirpath); + if (odirfd == -1) { + goto out; +@@ -1096,6 +1131,12 @@ static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path, + static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, + const char *name, V9fsPath *target) + { ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + if (dir_path) { + v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); + } else if (strcmp(name, "/")) { +@@ -1116,6 +1157,13 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir, + int ret; + int odirfd, ndirfd; + ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ (local_is_mapped_file_metadata(ctx, old_name) || ++ local_is_mapped_file_metadata(ctx, new_name))) { ++ errno = EINVAL; ++ return -1; ++ } ++ + odirfd = local_opendir_nofollow(ctx, olddir->data); + if (odirfd == -1) { + return -1; +@@ -1206,6 +1254,12 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, + int ret; + int dirfd; + ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(ctx, dir->data); + if (dirfd == -1) { + return -1; +-- +2.11.0 + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-10155.patch qemu-2.1+dfsg/debian/patches/CVE-2016-10155.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-10155.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-10155.patch 2018-07-24 11:52:34.000000000 +0200 @@ -0,0 +1,35 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 852232 + +Backport of: + +From eb7a20a3616085d46aa6b4b4224e15587ec67e6e Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Mon, 28 Nov 2016 17:49:04 -0800 +Subject: [PATCH] watchdog: 6300esb: add exit function + +When the Intel 6300ESB watchdog is hot unplug. The timer allocated +in realize isn't freed thus leaking memory leak. This patch avoid +this through adding the exit function. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-Id: <583cde9c.3223ed0a.7f0c2.886e@mx.google.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/watchdog/wdt_i6300esb.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/watchdog/wdt_i6300esb.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/watchdog/wdt_i6300esb.c 2017-04-06 09:50:33.025128615 -0400 ++++ qemu-2.0.0+dfsg/hw/watchdog/wdt_i6300esb.c 2017-04-06 09:52:51.550860890 -0400 +@@ -430,6 +430,8 @@ + I6300State *d = DO_UPCAST(I6300State, dev, dev); + + memory_region_destroy(&d->io_mem); ++ timer_del(d->timer); ++ timer_free(d->timer); + } + + static WatchdogTimerModel model = { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-2198-usb-ehci-add-capability-mmio-write-function.patch qemu-2.1+dfsg/debian/patches/CVE-2016-2198-usb-ehci-add-capability-mmio-write-function.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-2198-usb-ehci-add-capability-mmio-write-function.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-2198-usb-ehci-add-capability-mmio-write-function.patch 2018-06-28 16:15:31.000000000 +0200 @@ -0,0 +1,43 @@ +From dff0367cf66f489aa772320fa2937a8cac1ca30d Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Fri, 29 Jan 2016 18:30:34 +0530 +Subject: [PATCH] usb: ehci: add capability mmio write function + +USB Ehci emulation supports host controller capability registers. +But its mmio '.write' function was missing, which lead to a null +pointer dereference issue. Add a do nothing 'ehci_caps_write' +definition to avoid it; Do nothing because capability registers +are Read Only(RO). + +Reported-by: Zuozhi Fzz <zuozhi.fzz@alibaba-inc.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 1454072434-16045-1-git-send-email-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/usb/hcd-ehci.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: qemu/hw/usb/hcd-ehci.c +=================================================================== +--- qemu.orig/hw/usb/hcd-ehci.c ++++ qemu/hw/usb/hcd-ehci.c +@@ -899,6 +899,11 @@ static uint64_t ehci_caps_read(void *ptr + return s->caps[addr]; + } + ++static void ehci_caps_write(void *ptr, hwaddr addr, ++ uint64_t val, unsigned size) ++{ ++} ++ + static uint64_t ehci_opreg_read(void *ptr, hwaddr addr, + unsigned size) + { +@@ -2317,6 +2322,7 @@ static void ehci_frame_timer(void *opaqu + + static const MemoryRegionOps ehci_mmio_caps_ops = { + .read = ehci_caps_read, ++ .write = ehci_caps_write, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-6833-vmxnet3-check-for-device_active-before-write.patch qemu-2.1+dfsg/debian/patches/CVE-2016-6833-vmxnet3-check-for-device_active-before-write.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-6833-vmxnet3-check-for-device_active-before-write.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-6833-vmxnet3-check-for-device_active-before-write.patch 2018-06-27 19:13:47.000000000 +0200 @@ -0,0 +1,31 @@ +commit 6c352ca9b4ee3e1e286ea9e8434bd8e69ac7d0d8 +Author: Li Qiang <liqiang6-s@360.cn> +Date: Mon Aug 8 18:08:31 2016 +0530 + + net: vmxnet3: check for device_active before write + + Vmxnet3 device emulator does not check if the device is active, + before using it for write. It leads to a use after free issue, + if the vmxnet3_io_bar0_write routine is called after the device is + deactivated. Add check to avoid it. + + Reported-by: Li Qiang <liqiang6-s@360.cn> + Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> + Acked-by: Dmitry Fleytman <dmitry@daynix.com> + Signed-off-by: Jason Wang <jasowang@redhat.com> + +Index: qemu/hw/net/vmxnet3.c +=================================================================== +--- qemu.orig/hw/net/vmxnet3.c ++++ qemu/hw/net/vmxnet3.c +@@ -1071,6 +1071,10 @@ vmxnet3_io_bar0_write(void *opaque, hwad + { + VMXNET3State *s = opaque; + ++ if (!s->device_active) { ++ return; ++ } ++ + if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_TXPROD, + VMXNET3_DEVICE_MAX_TX_QUEUES, VMXNET3_REG_ALIGN)) { + int tx_queue_idx = diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-6835-net-vmxnet-check-IP-header-length.patch qemu-2.1+dfsg/debian/patches/CVE-2016-6835-net-vmxnet-check-IP-header-length.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-6835-net-vmxnet-check-IP-header-length.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-6835-net-vmxnet-check-IP-header-length.patch 2018-06-28 13:12:23.000000000 +0200 @@ -0,0 +1,33 @@ +From 93060258ae748573ca7197204125a2670047896d Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Tue, 9 Aug 2016 16:49:47 +0530 +Subject: [PATCH] net: vmxnet: check IP header length + +Vmxnet3 device emulator when parsing packet headers does not check +for IP header length. It could lead to a OOB access when reading +further packet data. Add check to avoid it. + +Reported-by: Li Qiang <liqiang6-s@360.cn> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Reviewed-by: Dmitry Fleytman <dmitry@daynix.com> +Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com> +--- + hw/net/vmxnet_tx_pkt.c | 5 +++++ + 1 file changed, 5 insertions(+) + +Index: qemu/hw/net/vmxnet_tx_pkt.c +=================================================================== +--- qemu.orig/hw/net/vmxnet_tx_pkt.c ++++ qemu/hw/net/vmxnet_tx_pkt.c +@@ -177,6 +177,11 @@ static bool vmxnet_tx_pkt_parse_headers( + } + + l3_hdr->iov_len = IP_HDR_GET_LEN(l3_hdr->iov_base); ++ if(l3_hdr->iov_len < sizeof(struct ip_header)) ++ { ++ l3_hdr->iov_len = 0; ++ return false; ++ } + pkt->l4proto = ((struct ip_header *) l3_hdr->iov_base)->ip_p; + + /* copy optional IPv4 header data */ diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-8576-fix-infinite-loop.patch qemu-2.1+dfsg/debian/patches/CVE-2016-8576-fix-infinite-loop.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-8576-fix-infinite-loop.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-8576-fix-infinite-loop.patch 2018-07-08 18:03:38.000000000 +0200 @@ -0,0 +1,55 @@ +Description: xhci: limit the number of link trbs we are willing to process + Needed to avoid we run in circles forever in case the guest builds + an endless loop with link trbs. +Origin: upstream, http://git.qemu.org/?p=qemu.git;a=commit;h=05f43d44e4bc26611ce25fd7d726e483f73363ce +Bug-Debian: https://bugs.debian.org/840343 +Index: qemu/hw/usb/hcd-xhci.c +=================================================================== +--- qemu.orig/hw/usb/hcd-xhci.c ++++ qemu/hw/usb/hcd-xhci.c +@@ -52,6 +52,8 @@ + * to the specs when it gets them */ + #define ER_FULL_HACK + ++#define TRB_LINK_LIMIT 4 ++ + #define LEN_CAP 0x40 + #define LEN_OPER (0x400 + 0x10 * MAXPORTS) + #define LEN_RUNTIME ((MAXINTRS + 1) * 0x20) +@@ -994,6 +996,8 @@ static TRBType xhci_ring_fetch(XHCIState + { + PCIDevice *pci_dev = PCI_DEVICE(xhci); + ++ uint32_t link_cnt = 0; ++ + while (1) { + TRBType type; + pci_dma_read(pci_dev, ring->dequeue, trb, TRB_SIZE); +@@ -1019,6 +1023,9 @@ static TRBType xhci_ring_fetch(XHCIState + ring->dequeue += TRB_SIZE; + return type; + } else { ++ if (++link_cnt > TRB_LINK_LIMIT) { ++ return 0; ++ } + ring->dequeue = xhci_mask64(trb->parameter); + if (trb->control & TRB_LK_TC) { + ring->ccs = !ring->ccs; +@@ -1036,6 +1043,7 @@ static int xhci_ring_chain_length(XHCISt + bool ccs = ring->ccs; + /* hack to bundle together the two/three TDs that make a setup transfer */ + bool control_td_set = 0; ++ uint32_t link_cnt = 0; + + while (1) { + TRBType type; +@@ -1051,6 +1059,9 @@ static int xhci_ring_chain_length(XHCISt + type = TRB_TYPE(trb); + + if (type == TR_LINK) { ++ if (++link_cnt > TRB_LINK_LIMIT) { ++ return -length; ++ } + dequeue = xhci_mask64(trb.parameter); + if (trb.control & TRB_LK_TC) { + ccs = !ccs; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-8667.patch qemu-2.1+dfsg/debian/patches/CVE-2016-8667.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-8667.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-8667.patch 2018-07-24 13:46:16.000000000 +0200 @@ -0,0 +1,39 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 840950 + +From c0a3172fa6bbddcc73192f2a2c48d0bf3a7ba61c Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Wed, 12 Oct 2016 18:07:41 +0530 +Subject: [PATCH] dma: rc4030: limit interval timer reload value +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +The JAZZ RC4030 chipset emulator has a periodic timer and +associated interval reload register. The reload value is used +as divider when computing timer's next tick value. If reload +value is large, it could lead to divide by zero error. Limit +the interval reload value to avoid it. + +Reported-by: Huawei PSIRT <psirt@huawei.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Tested-by: Hervé Poussineau <hpoussin@reactos.org> +Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com> +--- + hw/dma/rc4030.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/dma/rc4030.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/dma/rc4030.c 2017-04-05 11:22:52.516941129 -0400 ++++ qemu-2.0.0+dfsg/hw/dma/rc4030.c 2017-04-05 11:22:52.512941077 -0400 +@@ -377,7 +377,7 @@ + break; + /* Interval timer reload */ + case 0x0228: +- s->itr = val; ++ s->itr = val & 0x01FF; + qemu_irq_lower(s->timer_irq); + set_next_tick(s); + break; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-8669.patch qemu-2.1+dfsg/debian/patches/CVE-2016-8669.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-8669.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-8669.patch 2018-07-24 14:00:51.000000000 +0200 @@ -0,0 +1,38 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 840945 + +From 3592fe0c919cf27a81d8e9f9b4f269553418bb01 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Wed, 12 Oct 2016 11:28:08 +0530 +Subject: [PATCH] char: serial: check divider value against baud base + +16550A UART device uses an oscillator to generate frequencies +(baud base), which decide communication speed. This speed could +be changed by dividing it by a divider. If the divider is +greater than the baud base, speed is set to zero, leading to a +divide by zero error. Add check to avoid it. + +Reported-by: Huawei PSIRT <psirt@huawei.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-Id: <1476251888-20238-1-git-send-email-ppandit@redhat.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/char/serial.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: qemu-2.5+dfsg/hw/char/serial.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/char/serial.c 2017-04-04 13:50:18.820499175 -0400 ++++ qemu-2.5+dfsg/hw/char/serial.c 2017-04-04 13:50:18.820499175 -0400 +@@ -150,8 +150,9 @@ + int speed, parity, data_bits, stop_bits, frame_size; + QEMUSerialSetParams ssp; + +- if (s->divider == 0) ++ if (s->divider == 0 || s->divider > s->baudbase) { + return; ++ } + + /* Start bit. */ + frame_size = 1; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-10.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-10.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-10.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-10.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,167 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 72f0d0bf51362011c4d841a89fb8f5cfb16e0bf3 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:51 +0100 +Subject: [PATCH] 9pfs: local: lremovexattr: don't follow symlinks + +The local_lremovexattr() callback is vulnerable to symlink attacks because +it calls lremovexattr() which follows symbolic links in all path elements +but the rightmost one. + +This patch introduces a helper to emulate the non-existing fremovexattrat() +function: it is implemented with /proc/self/fd which provides a trusted +path that can be safely passed to lremovexattr(). + +local_lremovexattr() is converted to use this helper and opendir_nofollow(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-posix-acl.c | 10 ++-------- + hw/9pfs/9p-xattr-user.c | 8 +------- + hw/9pfs/9p-xattr.c | 36 +++++++++++++++++++++++++++++++----- + hw/9pfs/9p-xattr.h | 2 ++ + 4 files changed, 36 insertions(+), 20 deletions(-) + +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-posix-acl.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-posix-acl.c 2017-04-04 14:03:50.582929034 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-posix-acl.c 2017-04-04 14:03:50.578928983 -0400 +@@ -59,10 +59,8 @@ + const char *path, const char *name) + { + int ret; +- char *buffer; + +- buffer = rpath(ctx, path); +- ret = lremovexattr(buffer, MAP_ACL_ACCESS); ++ ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS); + if (ret == -1 && errno == ENODATA) { + /* + * We don't get ENODATA error when trying to remove a +@@ -72,7 +70,6 @@ + errno = 0; + ret = 0; + } +- g_free(buffer); + return ret; + } + +@@ -112,10 +109,8 @@ + const char *path, const char *name) + { + int ret; +- char *buffer; + +- buffer = rpath(ctx, path); +- ret = lremovexattr(buffer, MAP_ACL_DEFAULT); ++ ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT); + if (ret == -1 && errno == ENODATA) { + /* + * We don't get ENODATA error when trying to remove a +@@ -125,7 +120,6 @@ + errno = 0; + ret = 0; + } +- g_free(buffer); + return ret; + } + +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr-user.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-xattr-user.c 2017-04-04 14:03:50.582929034 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr-user.c 2017-04-04 14:03:50.582929034 -0400 +@@ -82,9 +82,6 @@ + static int mp_user_removexattr(FsContext *ctx, + const char *path, const char *name) + { +- char *buffer; +- int ret; +- + if (strncmp(name, "user.virtfs.", 12) == 0) { + /* + * Don't allow fetch of user.virtfs namesapce +@@ -93,10 +90,7 @@ + errno = EACCES; + return -1; + } +- buffer = rpath(ctx, path); +- ret = lremovexattr(buffer, name); +- g_free(buffer); +- return ret; ++ return local_removexattr_nofollow(ctx, path, name); + } + + XattrOperations mapped_user_xattr = { +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-xattr.c 2017-04-04 14:03:50.582929034 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.c 2017-04-04 14:03:50.582929034 -0400 +@@ -234,17 +234,43 @@ + return local_setxattr_nofollow(ctx, path, name, value, size, flags); + } + +-int pt_removexattr(FsContext *ctx, const char *path, const char *name) ++static ssize_t fremovexattrat_nofollow(int dirfd, const char *filename, ++ const char *name) + { +- char *buffer; ++ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename); + int ret; + +- buffer = rpath(ctx, path); +- ret = lremovexattr(path, name); +- g_free(buffer); ++ ret = lremovexattr(proc_path, name); ++ g_free(proc_path); + return ret; + } + ++ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path, ++ const char *name) ++{ ++ char *dirpath = g_path_get_dirname(path); ++ char *filename = g_path_get_basename(path); ++ int dirfd; ++ ssize_t ret = -1; ++ ++ dirfd = local_opendir_nofollow(ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } ++ ++ ret = fremovexattrat_nofollow(dirfd, filename, name); ++ close_preserve_errno(dirfd); ++out: ++ g_free(dirpath); ++ g_free(filename); ++ return ret; ++} ++ ++int pt_removexattr(FsContext *ctx, const char *path, const char *name) ++{ ++ return local_removexattr_nofollow(ctx, path, name); ++} ++ + ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size) + { +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.h +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-xattr.h 2017-04-04 14:03:50.582929034 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.h 2017-04-04 14:03:50.582929034 -0400 +@@ -33,6 +33,8 @@ + ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path, + const char *name, void *value, size_t size, + int flags); ++ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path, ++ const char *name); + + extern XattrOperations mapped_user_xattr; + extern XattrOperations passthrough_user_xattr; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-11.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-11.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-11.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-11.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,150 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From df4938a6651b1f980018f9eaf86af43e6b9d7fed Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:00 +0100 +Subject: [PATCH] 9pfs: local: unlinkat: don't follow symlinks + +The local_unlinkat() callback is vulnerable to symlink attacks because it +calls remove() which follows symbolic links in all path elements but the +rightmost one. + +This patch converts local_unlinkat() to rely on opendir_nofollow() and +unlinkat() instead. + +Most of the code is moved to a separate local_unlinkat_common() helper +which will be reused in a subsequent patch to fix the same issue in +local_remove(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 99 ++++++++++++++++++++++++++++++------------------------ + 1 file changed, 56 insertions(+), 43 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:32:33.340403789 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:32:33.336403738 -0400 +@@ -981,6 +981,56 @@ + return ret; + } + ++static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name, ++ int flags) ++{ ++ int ret = -1; ++ ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ int map_dirfd; ++ ++ if (flags == AT_REMOVEDIR) { ++ int fd; ++ ++ fd = openat(dirfd, name, O_RDONLY | O_DIRECTORY | O_PATH); ++ if (fd == -1) { ++ goto err_out; ++ } ++ /* ++ * If directory remove .virtfs_metadata contained in the ++ * directory ++ */ ++ ret = unlinkat(fd, VIRTFS_META_DIR, AT_REMOVEDIR); ++ close_preserve_errno(fd); ++ if (ret < 0 && errno != ENOENT) { ++ /* ++ * We didn't had the .virtfs_metadata file. May be file created ++ * in non-mapped mode ?. Ignore ENOENT. ++ */ ++ goto err_out; ++ } ++ } ++ /* ++ * Now remove the name from parent directory ++ * .virtfs_metadata directory. ++ */ ++ map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); ++ ret = unlinkat(map_dirfd, name, 0); ++ close_preserve_errno(map_dirfd); ++ if (ret < 0 && errno != ENOENT) { ++ /* ++ * We didn't had the .virtfs_metadata file. May be file created ++ * in non-mapped mode ?. Ignore ENOENT. ++ */ ++ goto err_out; ++ } ++ } ++ ++ ret = unlinkat(dirfd, name, flags); ++err_out: ++ return ret; ++} ++ + static int local_remove(FsContext *ctx, const char *path) + { + int err; +@@ -1133,52 +1183,15 @@ + const char *name, int flags) + { + int ret; +- V9fsString fullname; +- char *buffer; ++ int dirfd; + +- v9fs_string_init(&fullname); +- +- v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); +- if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- if (flags == AT_REMOVEDIR) { +- /* +- * If directory remove .virtfs_metadata contained in the +- * directory +- */ +- buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, +- fullname.data, VIRTFS_META_DIR); +- ret = remove(buffer); +- g_free(buffer); +- if (ret < 0 && errno != ENOENT) { +- /* +- * We didn't had the .virtfs_metadata file. May be file created +- * in non-mapped mode ?. Ignore ENOENT. +- */ +- goto err_out; +- } +- } +- /* +- * Now remove the name from parent directory +- * .virtfs_metadata directory. +- */ +- buffer = local_mapped_attr_path(ctx, fullname.data); +- ret = remove(buffer); +- g_free(buffer); +- if (ret < 0 && errno != ENOENT) { +- /* +- * We didn't had the .virtfs_metadata file. May be file created +- * in non-mapped mode ?. Ignore ENOENT. +- */ +- goto err_out; +- } ++ dirfd = local_opendir_nofollow(ctx, dir->data); ++ if (dirfd == -1) { ++ return -1; + } +- /* Remove the name finally */ +- buffer = rpath(ctx, fullname.data); +- ret = remove(buffer); +- g_free(buffer); + +-err_out: +- v9fs_string_free(&fullname); ++ ret = local_unlinkat_common(ctx, dirfd, name, flags); ++ close_preserve_errno(dirfd); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-12.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-12.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-12.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-12.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,109 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From a0e640a87210b1e986bcd4e7f7de03beb3db0a4a Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:08 +0100 +Subject: [PATCH] 9pfs: local: remove: don't follow symlinks + +The local_remove() callback is vulnerable to symlink attacks because it +calls: + +(1) lstat() which follows symbolic links in all path elements but the + rightmost one +(2) remove() which follows symbolic links in all path elements but the + rightmost one + +This patch converts local_remove() to rely on opendir_nofollow(), +fstatat(AT_SYMLINK_NOFOLLOW) to fix (1) and unlinkat() to fix (2). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 64 ++++++++++++++++++------------------------------------ + 1 file changed, 21 insertions(+), 43 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:32:42.912526775 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:32:42.912526775 -0400 +@@ -1033,54 +1033,32 @@ + + static int local_remove(FsContext *ctx, const char *path) + { +- int err; + struct stat stbuf; +- char *buffer; ++ char *dirpath = g_path_get_dirname(path); ++ char *name = g_path_get_basename(path); ++ int flags = 0; ++ int dirfd; ++ int err = -1; + +- if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- buffer = rpath(ctx, path); +- err = lstat(buffer, &stbuf); +- g_free(buffer); +- if (err) { +- goto err_out; +- } +- /* +- * If directory remove .virtfs_metadata contained in the +- * directory +- */ +- if (S_ISDIR(stbuf.st_mode)) { +- buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, +- path, VIRTFS_META_DIR); +- err = remove(buffer); +- g_free(buffer); +- if (err < 0 && errno != ENOENT) { +- /* +- * We didn't had the .virtfs_metadata file. May be file created +- * in non-mapped mode ?. Ignore ENOENT. +- */ +- goto err_out; +- } +- } +- /* +- * Now remove the name from parent directory +- * .virtfs_metadata directory +- */ +- buffer = local_mapped_attr_path(ctx, path); +- err = remove(buffer); +- g_free(buffer); +- if (err < 0 && errno != ENOENT) { +- /* +- * We didn't had the .virtfs_metadata file. May be file created +- * in non-mapped mode ?. Ignore ENOENT. +- */ +- goto err_out; +- } ++ dirfd = local_opendir_nofollow(ctx, dirpath); ++ if (dirfd) { ++ goto out; + } + +- buffer = rpath(ctx, path); +- err = remove(buffer); +- g_free(buffer); ++ if (fstatat(dirfd, path, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) { ++ goto err_out; ++ } ++ ++ if (S_ISDIR(stbuf.st_mode)) { ++ flags |= AT_REMOVEDIR; ++ } ++ ++ err = local_unlinkat_common(ctx, dirfd, name, flags); + err_out: ++ close_preserve_errno(dirfd); ++out: ++ g_free(name); ++ g_free(dirpath); + return err; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-13.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-13.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-13.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-13.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,59 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From a33eda0dd99e00faa3bacae43d19490bb9500e07 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:17 +0100 +Subject: [PATCH] 9pfs: local: utimensat: don't follow symlinks + +The local_utimensat() callback is vulnerable to symlink attacks because it +calls qemu_utimens()->utimensat(AT_SYMLINK_NOFOLLOW) which follows symbolic +links in all path elements but the rightmost one or qemu_utimens()->utimes() +which follows symbolic links for all path elements. + +This patch converts local_utimensat() to rely on opendir_nofollow() and +utimensat(AT_SYMLINK_NOFOLLOW) directly instead of using qemu_utimens(). +It is hence assumed that the OS supports utimensat(), i.e. has glibc 2.6 +or higher and linux 2.6.22 or higher, which seems reasonable nowadays. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:32:54.092670423 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:32:54.088670370 -0400 +@@ -971,13 +971,20 @@ + static int local_utimensat(FsContext *s, V9fsPath *fs_path, + const struct timespec *buf) + { +- char *buffer; +- int ret; +- char *path = fs_path->data; ++ char *dirpath = g_path_get_dirname(fs_path->data); ++ char *name = g_path_get_basename(fs_path->data); ++ int dirfd, ret = -1; + +- buffer = rpath(s, path); +- ret = qemu_utimens(buffer, buf); +- g_free(buffer); ++ dirfd = local_opendir_nofollow(s, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } ++ ++ ret = utimensat(dirfd, name, buf, AT_SYMLINK_NOFOLLOW); ++ close_preserve_errno(dirfd); ++out: ++ g_free(dirpath); ++ g_free(name); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-14.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-14.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-14.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-14.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,46 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 31e51d1c15b35dc98b88a301812914b70a2b55dc Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:25 +0100 +Subject: [PATCH] 9pfs: local: statfs: don't follow symlinks + +The local_statfs() callback is vulnerable to symlink attacks because it +calls statfs() which follows symbolic links in all path elements. + +This patch converts local_statfs() to rely on open_nofollow() and fstatfs() +instead. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:33:00.680755069 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:33:00.676755017 -0400 +@@ -1089,13 +1089,11 @@ + + static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) + { +- char *buffer; +- int ret; +- char *path = fs_path->data; ++ int fd, ret; + +- buffer = rpath(s, path); +- ret = statfs(buffer, stbuf); +- g_free(buffer); ++ fd = local_open_nofollow(s, fs_path->data, O_RDONLY, 0); ++ ret = fstatfs(fd, stbuf); ++ close_preserve_errno(fd); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-15.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-15.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-15.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-15.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,49 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From ac125d993b461d4dee4d6df4d93ac3f2eb959d1d Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:32 +0100 +Subject: [PATCH] 9pfs: local: truncate: don't follow symlinks + +The local_truncate() callback is vulnerable to symlink attacks because +it calls truncate() which follows symbolic links in all path elements. + +This patch converts local_truncate() to rely on open_nofollow() and +ftruncate() instead. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:33:06.948835604 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:33:06.944835552 -0400 +@@ -906,13 +906,14 @@ + + static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) + { +- char *buffer; +- int ret; +- char *path = fs_path->data; ++ int fd, ret; + +- buffer = rpath(ctx, path); +- ret = truncate(buffer, size); +- g_free(buffer); ++ fd = local_open_nofollow(ctx, fs_path->data, O_WRONLY, 0); ++ if (fd == -1) { ++ return -1; ++ } ++ ret = ftruncate(fd, size); ++ close_preserve_errno(fd); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-16.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-16.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-16.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-16.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,79 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From bec1e9546e03b9e7f5152cf3e8c95cf8acff5e12 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:40 +0100 +Subject: [PATCH] 9pfs: local: readlink: don't follow symlinks + +The local_readlink() callback is vulnerable to symlink attacks because it +calls: + +(1) open(O_NOFOLLOW) which follows symbolic links for all path elements but + the rightmost one +(2) readlink() which follows symbolic links for all path elements but the + rightmost one + +This patch converts local_readlink() to rely on open_nofollow() to fix (1) +and opendir_nofollow(), readlinkat() to fix (2). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:33:15.120940602 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:34:21.017787272 -0400 +@@ -339,28 +339,36 @@ + char *buf, size_t bufsz) + { + ssize_t tsize = -1; +- char *buffer; +- char *path = fs_path->data; + + if ((fs_ctx->export_flags & V9FS_SM_MAPPED) || + (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { + int fd; +- buffer = rpath(fs_ctx, path); +- fd = open(buffer, O_RDONLY | O_NOFOLLOW); +- g_free(buffer); ++ ++ fd = local_open_nofollow(fs_ctx, fs_path->data, O_RDONLY, 0); + if (fd == -1) { + return -1; + } + do { + tsize = read(fd, (void *)buf, bufsz); + } while (tsize == -1 && errno == EINTR); +- close(fd); ++ close_preserve_errno(fd); + return tsize; + } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || + (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, path); +- tsize = readlink(buffer, buf, bufsz); +- g_free(buffer); ++ char *dirpath = g_path_get_dirname(fs_path->data); ++ char *name = g_path_get_basename(fs_path->data); ++ int dirfd; ++ ++ dirfd = local_opendir_nofollow(fs_ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } ++ ++ tsize = readlinkat(dirfd, name, buf, bufsz); ++ close_preserve_errno(dirfd); ++ out: ++ g_free(name); ++ g_free(dirpath); + } + return tsize; + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-17.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-17.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-17.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-17.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,160 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From f9aef99b3e6df88036436b0d3dc3d504b9346c8c Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:48 +0100 +Subject: [PATCH] 9pfs: local: lstat: don't follow symlinks + +The local_lstat() callback is vulnerable to symlink attacks because it +calls: + +(1) lstat() which follows symbolic links in all path elements but the + rightmost one +(2) getxattr() which follows symbolic links in all path elements +(3) local_mapped_file_attr()->local_fopen()->openat(O_NOFOLLOW) which + follows symbolic links in all path elements but the rightmost + one + +This patch converts local_lstat() to rely on opendir_nofollow() and +fstatat(AT_SYMLINK_NOFOLLOW) to fix (1), fgetxattrat_nofollow() to +fix (2). + +A new local_fopenat() helper is introduced as a replacement to +local_fopen() to fix (3). No effort is made to factor out code +because local_fopen() will be dropped when all users have been +converted to call local_fopenat(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 78 ++++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 61 insertions(+), 17 deletions(-) + +Index: qemu/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-local.c ++++ qemu/hw/9pfs/virtio-9p-local.c +@@ -111,17 +111,49 @@ static FILE *local_fopen(const char *pat + return fp; + } + ++static FILE *local_fopenat(int dirfd, const char *name, const char *mode) ++{ ++ int fd, o_mode = 0; ++ FILE *fp; ++ int flags; ++ /* ++ * only supports two modes ++ */ ++ if (mode[0] == 'r') { ++ flags = O_RDONLY; ++ } else if (mode[0] == 'w') { ++ flags = O_WRONLY | O_TRUNC | O_CREAT; ++ o_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; ++ } else { ++ return NULL; ++ } ++ fd = openat_file(dirfd, name, flags, o_mode); ++ if (fd == -1) { ++ return NULL; ++ } ++ fp = fdopen(fd, mode); ++ if (!fp) { ++ close(fd); ++ } ++ return fp; ++} ++ + #define ATTR_MAX 100 +-static void local_mapped_file_attr(FsContext *ctx, const char *path, ++static void local_mapped_file_attr(int dirfd, const char *name, + struct stat *stbuf) + { + FILE *fp; + char buf[ATTR_MAX]; +- char *attr_path; ++ int map_dirfd; ++ ++ map_dirfd = openat(dirfd, VIRTFS_META_DIR, ++ O_RDONLY | O_DIRECTORY | O_NOFOLLOW); ++ if (map_dirfd == -1) { ++ return; ++ } + +- attr_path = local_mapped_attr_path(ctx, path); +- fp = local_fopen(attr_path, "r"); +- g_free(attr_path); ++ fp = local_fopenat(map_dirfd, name, "r"); ++ close_preserve_errno(map_dirfd); + if (!fp) { + return; + } +@@ -143,12 +175,17 @@ static void local_mapped_file_attr(FsCon + + static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) + { +- int err; +- char *buffer; +- char *path = fs_path->data; ++ int err = -1; ++ char *dirpath = g_path_get_dirname(fs_path->data); ++ char *name = g_path_get_basename(fs_path->data); ++ int dirfd; ++ ++ dirfd = local_opendir_nofollow(fs_ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } + +- buffer = rpath(fs_ctx, path); +- err = lstat(buffer, stbuf); ++ err = fstatat(dirfd, name, stbuf, AT_SYMLINK_NOFOLLOW); + if (err) { + goto err_out; + } +@@ -158,25 +195,33 @@ static int local_lstat(FsContext *fs_ctx + gid_t tmp_gid; + mode_t tmp_mode; + dev_t tmp_dev; +- if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { ++ ++ if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.uid", &tmp_uid, ++ sizeof(uid_t)) > 0) { + stbuf->st_uid = le32_to_cpu(tmp_uid); + } +- if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { ++ if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.gid", &tmp_gid, ++ sizeof(gid_t)) > 0) { + stbuf->st_gid = le32_to_cpu(tmp_gid); + } +- if (getxattr(buffer, "user.virtfs.mode", +- &tmp_mode, sizeof(mode_t)) > 0) { ++ if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.mode", &tmp_mode, ++ sizeof(mode_t)) > 0) { ++ + stbuf->st_mode = le32_to_cpu(tmp_mode); + } +- if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { ++ if (fgetxattrat_nofollow(dirfd, name, "user.virtfs.rdev", &tmp_dev, ++ sizeof(dev_t)) > 0) { + stbuf->st_rdev = le64_to_cpu(tmp_dev); + } + } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- local_mapped_file_attr(fs_ctx, path, stbuf); ++ local_mapped_file_attr(dirfd, name, stbuf); + } + + err_out: +- g_free(buffer); ++ close_preserve_errno(dirfd); ++out: ++ g_free(name); ++ g_free(dirpath); + return err; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-18.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-18.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-18.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-18.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,126 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 99f2cf4b2dad7b37c69759deb0d0b19d3ec1a24a Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:43:55 +0100 +Subject: [PATCH] 9pfs: local: renameat: don't follow symlinks + +The local_renameat() callback is currently a wrapper around local_rename() +which is vulnerable to symlink attacks. + +This patch rewrites local_renameat() to have its own implementation, based +on local_opendir_nofollow() and renameat(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 64 insertions(+), 10 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:37:10.935970451 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:37:10.931970400 -0400 +@@ -64,6 +64,14 @@ + return local_open_nofollow(fs_ctx, path, O_DIRECTORY | O_RDONLY, 0); + } + ++static void renameat_preserve_errno(int odirfd, const char *opath, int ndirfd, ++ const char *npath) ++{ ++ int serrno = errno; ++ renameat(odirfd, opath, ndirfd, npath); ++ errno = serrno; ++} ++ + #define VIRTFS_META_DIR ".virtfs_metadata" + + static char *local_mapped_attr_path(FsContext *ctx, const char *path) +@@ -145,8 +153,7 @@ + char buf[ATTR_MAX]; + int map_dirfd; + +- map_dirfd = openat(dirfd, VIRTFS_META_DIR, +- O_RDONLY | O_DIRECTORY | O_NOFOLLOW); ++ map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); + if (map_dirfd == -1) { + return; + } +@@ -1201,17 +1208,64 @@ + const char *new_name) + { + int ret; +- V9fsString old_full_name, new_full_name; ++ int odirfd, ndirfd; ++ ++ odirfd = local_opendir_nofollow(ctx, olddir->data); ++ if (odirfd == -1) { ++ return -1; ++ } ++ ++ ndirfd = local_opendir_nofollow(ctx, newdir->data); ++ if (ndirfd == -1) { ++ close_preserve_errno(odirfd); ++ return -1; ++ } ++ ++ ret = renameat(odirfd, old_name, ndirfd, new_name); ++ if (ret < 0) { ++ goto out; ++ } + +- v9fs_string_init(&old_full_name); +- v9fs_string_init(&new_full_name); ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ int omap_dirfd, nmap_dirfd; + +- v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name); +- v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name); ++ ret = mkdirat(ndirfd, VIRTFS_META_DIR, 0700); ++ if (ret < 0 && errno != EEXIST) { ++ goto err_undo_rename; ++ } + +- ret = local_rename(ctx, old_full_name.data, new_full_name.data); +- v9fs_string_free(&old_full_name); +- v9fs_string_free(&new_full_name); ++ omap_dirfd = openat(odirfd, VIRTFS_META_DIR, ++ O_RDONLY | O_DIRECTORY | O_NOFOLLOW); ++ if (omap_dirfd == -1) { ++ goto err; ++ } ++ ++ nmap_dirfd = openat(ndirfd, VIRTFS_META_DIR, ++ O_RDONLY | O_DIRECTORY | O_NOFOLLOW); ++ if (nmap_dirfd == -1) { ++ close_preserve_errno(omap_dirfd); ++ goto err; ++ } ++ ++ /* rename the .virtfs_metadata files */ ++ ret = renameat(omap_dirfd, old_name, nmap_dirfd, new_name); ++ close_preserve_errno(nmap_dirfd); ++ close_preserve_errno(omap_dirfd); ++ if (ret < 0 && errno != ENOENT) { ++ goto err_undo_rename; ++ } ++ ++ ret = 0; ++ } ++ goto out; ++ ++err: ++ ret = -1; ++err_undo_rename: ++ renameat_preserve_errno(ndirfd, new_name, odirfd, old_name); ++out: ++ close_preserve_errno(ndirfd); ++ close_preserve_errno(odirfd); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-19.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-19.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-19.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-19.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,100 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From d2767edec582558f1e6c52e1dd9370d62e2b30fc Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:03 +0100 +Subject: [PATCH] 9pfs: local: rename: use renameat + +The local_rename() callback is vulnerable to symlink attacks because it +uses rename() which follows symbolic links in all path elements but the +rightmost one. + +This patch simply transforms local_rename() into a wrapper around +local_renameat() which is symlink-attack safe. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 57 ++++++++++++++++++++++++++---------------------------- + 1 file changed, 27 insertions(+), 30 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:37:16.872046721 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:37:16.868046669 -0400 +@@ -976,36 +976,6 @@ + return ret; + } + +-static int local_rename(FsContext *ctx, const char *oldpath, +- const char *newpath) +-{ +- int err; +- char *buffer, *buffer1; +- +- if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- err = local_create_mapped_attr_dir(ctx, newpath); +- if (err < 0) { +- return err; +- } +- /* rename the .virtfs_metadata files */ +- buffer = local_mapped_attr_path(ctx, oldpath); +- buffer1 = local_mapped_attr_path(ctx, newpath); +- err = rename(buffer, buffer1); +- g_free(buffer); +- g_free(buffer1); +- if (err < 0 && errno != ENOENT) { +- return err; +- } +- } +- +- buffer = rpath(ctx, oldpath); +- buffer1 = rpath(ctx, newpath); +- err = rename(buffer, buffer1); +- g_free(buffer); +- g_free(buffer1); +- return err; +-} +- + static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) + { + char *buffer; +@@ -1269,6 +1239,33 @@ + return ret; + } + ++static void v9fs_path_init_dirname(V9fsPath *path, const char *str) ++{ ++ path->data = g_path_get_dirname(str); ++ path->size = strlen(path->data) + 1; ++} ++ ++static int local_rename(FsContext *ctx, const char *oldpath, ++ const char *newpath) ++{ ++ int err; ++ char *oname = g_path_get_basename(oldpath); ++ char *nname = g_path_get_basename(newpath); ++ V9fsPath olddir, newdir; ++ ++ v9fs_path_init_dirname(&olddir, oldpath); ++ v9fs_path_init_dirname(&newdir, newpath); ++ ++ err = local_renameat(ctx, &olddir, oname, &newdir, nname); ++ ++ v9fs_path_free(&newdir); ++ v9fs_path_free(&olddir); ++ g_free(nname); ++ g_free(oname); ++ ++ return err; ++} ++ + static int local_unlinkat(FsContext *ctx, V9fsPath *dir, + const char *name, int flags) + { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-1.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-1.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,184 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 56fc494bdcba35d74da27e1d34dbb6db6fa7bd67 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:41:40 +0100 +Subject: [PATCH] 9pfs: local: move xattr security ops to 9p-xattr.c + +These functions are always called indirectly. It really doesn't make sense +for them to sit in a header file. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-xattr.c | 61 +++++++++++++++++++++++++++++++++++++++++ + hw/9pfs/9p-xattr.h | 80 ++++++++++-------------------------------------------- + 2 files changed, 75 insertions(+), 66 deletions(-) + +Index: qemu-2.6.1+dfsg/hw/9pfs/virtio-9p-xattr.c +=================================================================== +--- qemu-2.6.1+dfsg.orig/hw/9pfs/virtio-9p-xattr.c 2017-04-04 08:06:34.775512919 -0400 ++++ qemu-2.6.1+dfsg/hw/9pfs/virtio-9p-xattr.c 2017-04-04 08:06:34.767512815 -0400 +@@ -143,6 +143,67 @@ + + } + ++ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name, ++ void *value, size_t size) ++{ ++ char *buffer; ++ ssize_t ret; ++ ++ buffer = rpath(ctx, path); ++ ret = lgetxattr(buffer, name, value, size); ++ g_free(buffer); ++ return ret; ++} ++ ++int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, ++ size_t size, int flags) ++{ ++ char *buffer; ++ int ret; ++ ++ buffer = rpath(ctx, path); ++ ret = lsetxattr(buffer, name, value, size, flags); ++ g_free(buffer); ++ return ret; ++} ++ ++int pt_removexattr(FsContext *ctx, const char *path, const char *name) ++{ ++ char *buffer; ++ int ret; ++ ++ buffer = rpath(ctx, path); ++ ret = lremovexattr(path, name); ++ g_free(buffer); ++ return ret; ++} ++ ++ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name, ++ void *value, size_t size) ++{ ++ errno = ENOTSUP; ++ return -1; ++} ++ ++int notsup_setxattr(FsContext *ctx, const char *path, const char *name, ++ void *value, size_t size, int flags) ++{ ++ errno = ENOTSUP; ++ return -1; ++} ++ ++ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name, ++ void *value, size_t size) ++{ ++ return 0; ++} ++ ++int notsup_removexattr(FsContext *ctx, const char *path, const char *name) ++{ ++ errno = ENOTSUP; ++ return -1; ++} ++ + XattrOperations *mapped_xattr_ops[] = { + &mapped_user_xattr, + &mapped_pacl_xattr, +Index: qemu-2.6.1+dfsg/hw/9pfs/virtio-9p-xattr.h +=================================================================== +--- qemu-2.6.1+dfsg.orig/hw/9pfs/virtio-9p-xattr.h 2017-04-04 08:06:34.775512919 -0400 ++++ qemu-2.6.1+dfsg/hw/9pfs/virtio-9p-xattr.h 2017-04-04 08:06:34.771512867 -0400 +@@ -48,73 +48,21 @@ + int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size, int flags); + int v9fs_remove_xattr(FsContext *ctx, const char *path, const char *name); ++ + ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value, + size_t size); +- +-static inline ssize_t pt_getxattr(FsContext *ctx, const char *path, +- const char *name, void *value, size_t size) +-{ +- char *buffer; +- ssize_t ret; +- +- buffer = rpath(ctx, path); +- ret = lgetxattr(buffer, name, value, size); +- g_free(buffer); +- return ret; +-} +- +-static inline int pt_setxattr(FsContext *ctx, const char *path, +- const char *name, void *value, +- size_t size, int flags) +-{ +- char *buffer; +- int ret; +- +- buffer = rpath(ctx, path); +- ret = lsetxattr(buffer, name, value, size, flags); +- g_free(buffer); +- return ret; +-} +- +-static inline int pt_removexattr(FsContext *ctx, +- const char *path, const char *name) +-{ +- char *buffer; +- int ret; +- +- buffer = rpath(ctx, path); +- ret = lremovexattr(path, name); +- g_free(buffer); +- return ret; +-} +- +-static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path, +- const char *name, void *value, +- size_t size) +-{ +- errno = ENOTSUP; +- return -1; +-} +- +-static inline int notsup_setxattr(FsContext *ctx, const char *path, +- const char *name, void *value, +- size_t size, int flags) +-{ +- errno = ENOTSUP; +- return -1; +-} +- +-static inline ssize_t notsup_listxattr(FsContext *ctx, const char *path, +- char *name, void *value, size_t size) +-{ +- return 0; +-} +- +-static inline int notsup_removexattr(FsContext *ctx, +- const char *path, const char *name) +-{ +- errno = ENOTSUP; +- return -1; +-} ++ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name, ++ void *value, size_t size); ++int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, ++ size_t size, int flags); ++int pt_removexattr(FsContext *ctx, const char *path, const char *name); ++ ++ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name, ++ void *value, size_t size); ++int notsup_setxattr(FsContext *ctx, const char *path, const char *name, ++ void *value, size_t size, int flags); ++ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name, ++ void *value, size_t size); ++int notsup_removexattr(FsContext *ctx, const char *path, const char *name); + + #endif diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-20.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-20.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-20.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-20.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,94 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 6dd4b1f1d026e478d9177b28169b377e212400f3 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:11 +0100 +Subject: [PATCH] 9pfs: local: improve error handling in link op + +When using the mapped-file security model, we also have to create a link +for the metadata file if it exists. In case of failure, we should rollback. + +That's what this patch does. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:37:23.432131007 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:37:23.428130956 -0400 +@@ -932,6 +932,7 @@ + int ret; + V9fsString newpath; + char *buffer, *buffer1; ++ int serrno; + + v9fs_string_init(&newpath); + v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); +@@ -940,25 +941,36 @@ + buffer1 = rpath(ctx, newpath.data); + ret = link(buffer, buffer1); + g_free(buffer); +- g_free(buffer1); ++ if (ret < 0) { ++ goto out; ++ } + + /* now link the virtfs_metadata files */ +- if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ char *vbuffer, *vbuffer1; ++ + /* Link the .virtfs_metadata files. Create the metada directory */ + ret = local_create_mapped_attr_dir(ctx, newpath.data); + if (ret < 0) { + goto err_out; + } +- buffer = local_mapped_attr_path(ctx, oldpath->data); +- buffer1 = local_mapped_attr_path(ctx, newpath.data); +- ret = link(buffer, buffer1); +- g_free(buffer); +- g_free(buffer1); ++ vbuffer = local_mapped_attr_path(ctx, oldpath->data); ++ vbuffer1 = local_mapped_attr_path(ctx, newpath.data); ++ ret = link(vbuffer, vbuffer1); ++ g_free(vbuffer); ++ g_free(vbuffer1); + if (ret < 0 && errno != ENOENT) { + goto err_out; + } + } ++ goto out; ++ + err_out: ++ serrno = errno; ++ remove(buffer1); ++ errno = serrno; ++out: ++ g_free(buffer1); + v9fs_string_free(&newpath); + return ret; + } +@@ -1204,14 +1216,12 @@ + goto err_undo_rename; + } + +- omap_dirfd = openat(odirfd, VIRTFS_META_DIR, +- O_RDONLY | O_DIRECTORY | O_NOFOLLOW); ++ omap_dirfd = openat_dir(odirfd, VIRTFS_META_DIR); + if (omap_dirfd == -1) { + goto err; + } + +- nmap_dirfd = openat(ndirfd, VIRTFS_META_DIR, +- O_RDONLY | O_DIRECTORY | O_NOFOLLOW); ++ nmap_dirfd = openat_dir(ndirfd, VIRTFS_META_DIR); + if (nmap_dirfd == -1) { + close_preserve_errno(omap_dirfd); + goto err; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-21.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-21.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-21.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-21.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,147 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From ad0b46e6ac769b187cb4dcf0065675ef8a198a5e Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:20 +0100 +Subject: [PATCH] 9pfs: local: link: don't follow symlinks + +The local_link() callback is vulnerable to symlink attacks because it calls: + +(1) link() which follows symbolic links for all path elements but the + rightmost one +(2) local_create_mapped_attr_dir()->mkdir() which follows symbolic links + for all path elements but the rightmost one + +This patch converts local_link() to rely on opendir_nofollow() and linkat() +to fix (1), mkdirat() to fix (2). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 84 +++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 55 insertions(+), 29 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:34.521044387 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:34.517044336 -0400 +@@ -72,6 +72,13 @@ + errno = serrno; + } + ++static void unlinkat_preserve_errno(int dirfd, const char *path, int flags) ++{ ++ int serrno = errno; ++ unlinkat(dirfd, path, flags); ++ errno = serrno; ++} ++ + #define VIRTFS_META_DIR ".virtfs_metadata" + + static char *local_mapped_attr_path(FsContext *ctx, const char *path) +@@ -929,49 +936,68 @@ + static int local_link(FsContext *ctx, V9fsPath *oldpath, + V9fsPath *dirpath, const char *name) + { +- int ret; +- V9fsString newpath; +- char *buffer, *buffer1; +- int serrno; +- +- v9fs_string_init(&newpath); +- v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); +- +- buffer = rpath(ctx, oldpath->data); +- buffer1 = rpath(ctx, newpath.data); +- ret = link(buffer, buffer1); +- g_free(buffer); +- if (ret < 0) { ++ char *odirpath = g_path_get_dirname(oldpath->data); ++ char *oname = g_path_get_basename(oldpath->data); ++ int ret = -1; ++ int odirfd, ndirfd; ++ ++ odirfd = local_opendir_nofollow(ctx, odirpath); ++ if (odirfd == -1) { + goto out; + } + ++ ndirfd = local_opendir_nofollow(ctx, dirpath->data); ++ if (ndirfd == -1) { ++ close_preserve_errno(odirfd); ++ goto out; ++ } ++ ++ ret = linkat(odirfd, oname, ndirfd, name, 0); ++ if (ret < 0) { ++ goto out_close; ++ } ++ + /* now link the virtfs_metadata files */ + if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- char *vbuffer, *vbuffer1; ++ int omap_dirfd, nmap_dirfd; ++ ++ ret = mkdirat(ndirfd, VIRTFS_META_DIR, 0700); ++ if (ret < 0 && errno != EEXIST) { ++ goto err_undo_link; ++ } ++ ++ omap_dirfd = openat_dir(odirfd, VIRTFS_META_DIR); ++ if (omap_dirfd == -1) { ++ goto err; ++ } ++ ++ nmap_dirfd = openat_dir(ndirfd, VIRTFS_META_DIR); ++ if (nmap_dirfd == -1) { ++ close_preserve_errno(omap_dirfd); ++ goto err; ++ } + +- /* Link the .virtfs_metadata files. Create the metada directory */ +- ret = local_create_mapped_attr_dir(ctx, newpath.data); +- if (ret < 0) { +- goto err_out; +- } +- vbuffer = local_mapped_attr_path(ctx, oldpath->data); +- vbuffer1 = local_mapped_attr_path(ctx, newpath.data); +- ret = link(vbuffer, vbuffer1); +- g_free(vbuffer); +- g_free(vbuffer1); ++ ret = linkat(omap_dirfd, oname, nmap_dirfd, name, 0); ++ close_preserve_errno(nmap_dirfd); ++ close_preserve_errno(omap_dirfd); + if (ret < 0 && errno != ENOENT) { +- goto err_out; ++ goto err_undo_link; + } ++ ++ ret = 0; + } +- goto out; ++ goto out_close; + +-err_out: +- serrno = errno; +- remove(buffer1); +- errno = serrno; ++err: ++ ret = -1; ++err_undo_link: ++ unlinkat_preserve_errno(ndirfd, name, 0); ++out_close: ++ close_preserve_errno(ndirfd); ++ close_preserve_errno(odirfd); + out: +- g_free(buffer1); +- v9fs_string_free(&newpath); ++ g_free(oname); ++ g_free(odirpath); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-22.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-22.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-22.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-22.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,245 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From e3187a45dd02a7490f9191c16527dc28a4ba45b9 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:28 +0100 +Subject: [PATCH] 9pfs: local: chmod: don't follow symlinks + +The local_chmod() callback is vulnerable to symlink attacks because it +calls: + +(1) chmod() which follows symbolic links for all path elements +(2) local_set_xattr()->setxattr() which follows symbolic links for all + path elements +(3) local_set_mapped_file_attr() which calls in turn local_fopen() and + mkdir(), both functions following symbolic links for all path + elements but the rightmost one + +We would need fchmodat() to implement AT_SYMLINK_NOFOLLOW to fix (1). This +isn't the case on linux unfortunately: the kernel doesn't even have a flags +argument to the syscall :-\ It is impossible to fix it in userspace in +a race-free manner. This patch hence converts local_chmod() to rely on +open_nofollow() and fchmod(). This fixes the vulnerability but introduces +a limitation: the target file must readable and/or writable for the call +to openat() to succeed. + +It introduces a local_set_xattrat() replacement to local_set_xattr() +based on fsetxattrat() to fix (2), and a local_set_mapped_file_attrat() +replacement to local_set_mapped_file_attr() based on local_fopenat() +and mkdirat() to fix (3). No effort is made to factor out code because +both local_set_xattr() and local_set_mapped_file_attr() will be dropped +when all users have been converted to use the "at" versions. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 167 insertions(+), 11 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:40.141116596 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:40.137116544 -0400 +@@ -366,6 +366,155 @@ + return 0; + } + ++static int local_set_mapped_file_attrat(int dirfd, const char *name, ++ FsCred *credp) ++{ ++ FILE *fp; ++ int ret; ++ char buf[ATTR_MAX]; ++ int uid = -1, gid = -1, mode = -1, rdev = -1; ++ int map_dirfd; ++ ++ ret = mkdirat(dirfd, VIRTFS_META_DIR, 0700); ++ if (ret < 0 && errno != EEXIST) { ++ return -1; ++ } ++ ++ map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); ++ if (map_dirfd == -1) { ++ return -1; ++ } ++ ++ fp = local_fopenat(map_dirfd, name, "r"); ++ if (!fp) { ++ if (errno == ENOENT) { ++ goto update_map_file; ++ } else { ++ close_preserve_errno(map_dirfd); ++ return -1; ++ } ++ } ++ memset(buf, 0, ATTR_MAX); ++ while (fgets(buf, ATTR_MAX, fp)) { ++ if (!strncmp(buf, "virtfs.uid", 10)) { ++ uid = atoi(buf + 11); ++ } else if (!strncmp(buf, "virtfs.gid", 10)) { ++ gid = atoi(buf + 11); ++ } else if (!strncmp(buf, "virtfs.mode", 11)) { ++ mode = atoi(buf + 12); ++ } else if (!strncmp(buf, "virtfs.rdev", 11)) { ++ rdev = atoi(buf + 12); ++ } ++ memset(buf, 0, ATTR_MAX); ++ } ++ fclose(fp); ++ ++update_map_file: ++ fp = local_fopenat(map_dirfd, name, "w"); ++ close_preserve_errno(map_dirfd); ++ if (!fp) { ++ return -1; ++ } ++ ++ if (credp->fc_uid != -1) { ++ uid = credp->fc_uid; ++ } ++ if (credp->fc_gid != -1) { ++ gid = credp->fc_gid; ++ } ++ if (credp->fc_mode != -1) { ++ mode = credp->fc_mode; ++ } ++ if (credp->fc_rdev != -1) { ++ rdev = credp->fc_rdev; ++ } ++ ++ if (uid != -1) { ++ fprintf(fp, "virtfs.uid=%d\n", uid); ++ } ++ if (gid != -1) { ++ fprintf(fp, "virtfs.gid=%d\n", gid); ++ } ++ if (mode != -1) { ++ fprintf(fp, "virtfs.mode=%d\n", mode); ++ } ++ if (rdev != -1) { ++ fprintf(fp, "virtfs.rdev=%d\n", rdev); ++ } ++ fclose(fp); ++ ++ return 0; ++} ++ ++static int fchmodat_nofollow(int dirfd, const char *name, mode_t mode) ++{ ++ int fd, ret; ++ ++ /* FIXME: this should be handled with fchmodat(AT_SYMLINK_NOFOLLOW). ++ * Unfortunately, the linux kernel doesn't implement it yet. As an ++ * alternative, let's open the file and use fchmod() instead. This ++ * may fail depending on the permissions of the file, but it is the ++ * best we can do to avoid TOCTTOU. We first try to open read-only ++ * in case name points to a directory. If that fails, we try write-only ++ * in case name doesn't point to a directory. ++ */ ++ fd = openat_file(dirfd, name, O_RDONLY, 0); ++ if (fd == -1) { ++ /* In case the file is writable-only and isn't a directory. */ ++ if (errno == EACCES) { ++ fd = openat_file(dirfd, name, O_WRONLY, 0); ++ } ++ if (fd == -1 && errno == EISDIR) { ++ errno = EACCES; ++ } ++ } ++ if (fd == -1) { ++ return -1; ++ } ++ ret = fchmod(fd, mode); ++ close_preserve_errno(fd); ++ return ret; ++} ++ ++static int local_set_xattrat(int dirfd, const char *path, FsCred *credp) ++{ ++ int err; ++ ++ if (credp->fc_uid != -1) { ++ uint32_t tmp_uid = cpu_to_le32(credp->fc_uid); ++ err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.uid", &tmp_uid, ++ sizeof(uid_t), 0); ++ if (err) { ++ return err; ++ } ++ } ++ if (credp->fc_gid != -1) { ++ uint32_t tmp_gid = cpu_to_le32(credp->fc_gid); ++ err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.gid", &tmp_gid, ++ sizeof(gid_t), 0); ++ if (err) { ++ return err; ++ } ++ } ++ if (credp->fc_mode != -1) { ++ uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); ++ err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.mode", &tmp_mode, ++ sizeof(mode_t), 0); ++ if (err) { ++ return err; ++ } ++ } ++ if (credp->fc_rdev != -1) { ++ uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev); ++ err = fsetxattrat_nofollow(dirfd, path, "user.virtfs.rdev", &tmp_rdev, ++ sizeof(dev_t), 0); ++ if (err) { ++ return err; ++ } ++ } ++ return 0; ++} ++ + static int local_post_create_passthrough(FsContext *fs_ctx, const char *path, + FsCred *credp) + { +@@ -554,22 +703,29 @@ + + static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) + { +- char *buffer; ++ char *dirpath = g_path_get_dirname(fs_path->data); ++ char *name = g_path_get_basename(fs_path->data); + int ret = -1; +- char *path = fs_path->data; ++ int dirfd; ++ ++ dirfd = local_opendir_nofollow(fs_ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } + + if (fs_ctx->export_flags & V9FS_SM_MAPPED) { +- buffer = rpath(fs_ctx, path); +- ret = local_set_xattr(buffer, credp); +- g_free(buffer); ++ ret = local_set_xattrat(dirfd, name, credp); + } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- return local_set_mapped_file_attr(fs_ctx, path, credp); +- } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || +- (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, path); +- ret = chmod(buffer, credp->fc_mode); +- g_free(buffer); +- } ++ ret = local_set_mapped_file_attrat(dirfd, name, credp); ++ } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH || ++ fs_ctx->export_flags & V9FS_SM_NONE) { ++ ret = fchmodat_nofollow(dirfd, name, credp->fc_mode); ++ } ++ close_preserve_errno(dirfd); ++ ++out: ++ g_free(dirpath); ++ g_free(name); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-23.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-23.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-23.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-23.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,78 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From d369f20763a857eac544a5289a046d0285a91df8 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:37 +0100 +Subject: [PATCH] 9pfs: local: chown: don't follow symlinks + +The local_chown() callback is vulnerable to symlink attacks because it +calls: + +(1) lchown() which follows symbolic links for all path elements but the + rightmost one +(2) local_set_xattr()->setxattr() which follows symbolic links for all + path elements +(3) local_set_mapped_file_attr() which calls in turn local_fopen() and + mkdir(), both functions following symbolic links for all path + elements but the rightmost one + +This patch converts local_chown() to rely on open_nofollow() and +fchownat() to fix (1), as well as local_set_xattrat() and +local_set_mapped_file_attrat() to fix (2) and (3) respectively. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:45.673187674 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:45.669187622 -0400 +@@ -1172,23 +1172,31 @@ + + static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) + { +- char *buffer; ++ char *dirpath = g_path_get_dirname(fs_path->data); ++ char *name = g_path_get_basename(fs_path->data); + int ret = -1; +- char *path = fs_path->data; ++ int dirfd; ++ ++ dirfd = local_opendir_nofollow(fs_ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } + + if ((credp->fc_uid == -1 && credp->fc_gid == -1) || + (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || + (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, path); +- ret = lchown(buffer, credp->fc_uid, credp->fc_gid); +- g_free(buffer); ++ ret = fchownat(dirfd, name, credp->fc_uid, credp->fc_gid, ++ AT_SYMLINK_NOFOLLOW); + } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) { +- buffer = rpath(fs_ctx, path); +- ret = local_set_xattr(buffer, credp); +- g_free(buffer); ++ ret = local_set_xattrat(dirfd, name, credp); + } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- return local_set_mapped_file_attr(fs_ctx, path, credp); ++ ret = local_set_mapped_file_attrat(dirfd, name, credp); + } ++ ++ close_preserve_errno(dirfd); ++out: ++ g_free(name); ++ g_free(dirpath); + return ret; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-24.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-24.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-24.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-24.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,172 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 38771613ea6759f499645afd709aa422161eb27e Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:46 +0100 +Subject: [PATCH] 9pfs: local: symlink: don't follow symlinks + +The local_symlink() callback is vulnerable to symlink attacks because it +calls: + +(1) symlink() which follows symbolic links for all path elements but the + rightmost one +(2) open(O_NOFOLLOW) which follows symbolic links for all path elements but + the rightmost one +(3) local_set_xattr()->setxattr() which follows symbolic links for all + path elements +(4) local_set_mapped_file_attr() which calls in turn local_fopen() and + mkdir(), both functions following symbolic links for all path + elements but the rightmost one + +This patch converts local_symlink() to rely on opendir_nofollow() and +symlinkat() to fix (1), openat(O_NOFOLLOW) to fix (2), as well as +local_set_xattrat() and local_set_mapped_file_attrat() to fix (3) and +(4) respectively. + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 81 +++++++++++++++++------------------------------------- + 1 file changed, 25 insertions(+), 56 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:38:53.361286453 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:43:39.164958577 -0400 +@@ -987,24 +987,22 @@ + V9fsPath *dir_path, const char *name, FsCred *credp) + { + int err = -1; +- int serrno = 0; +- char *newpath; +- V9fsString fullname; +- char *buffer; +- +- v9fs_string_init(&fullname); +- v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); +- newpath = fullname.data; ++ int dirfd; ++ ++ dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); ++ if (dirfd == -1) { ++ return -1; ++ } + + /* Determine the security model */ +- if (fs_ctx->export_flags & V9FS_SM_MAPPED) { ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED || ++ fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { + int fd; + ssize_t oldpath_size, write_size; +- buffer = rpath(fs_ctx, newpath); +- fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); ++ ++ fd = openat_file(dirfd, name, O_CREAT | O_EXCL | O_RDWR, ++ SM_LOCAL_MODE_BITS); + if (fd == -1) { +- g_free(buffer); +- err = fd; + goto out; + } + /* Write the oldpath (target) to the file. */ +@@ -1012,80 +1010,48 @@ + do { + write_size = write(fd, (void *)oldpath, oldpath_size); + } while (write_size == -1 && errno == EINTR); ++ close_preserve_errno(fd); + + if (write_size != oldpath_size) { +- serrno = errno; +- close(fd); +- err = -1; + goto err_end; + } +- close(fd); + /* Set cleint credentials in symlink's xattr */ +- credp->fc_mode = credp->fc_mode|S_IFLNK; +- err = local_set_xattr(buffer, credp); +- if (err == -1) { +- serrno = errno; +- goto err_end; +- } +- } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- int fd; +- ssize_t oldpath_size, write_size; +- buffer = rpath(fs_ctx, newpath); +- fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); +- if (fd == -1) { +- g_free(buffer); +- err = fd; +- goto out; +- } +- /* Write the oldpath (target) to the file. */ +- oldpath_size = strlen(oldpath); +- do { +- write_size = write(fd, (void *)oldpath, oldpath_size); +- } while (write_size == -1 && errno == EINTR); ++ credp->fc_mode = credp->fc_mode | S_IFLNK; + +- if (write_size != oldpath_size) { +- serrno = errno; +- close(fd); +- err = -1; +- goto err_end; ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { ++ err = local_set_xattrat(dirfd, name, credp); ++ } else { ++ err = local_set_mapped_file_attrat(dirfd, name, credp); + } +- close(fd); +- /* Set cleint credentials in symlink's xattr */ +- credp->fc_mode = credp->fc_mode|S_IFLNK; +- err = local_set_mapped_file_attr(fs_ctx, newpath, credp); + if (err == -1) { +- serrno = errno; + goto err_end; + } +- } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || +- (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, newpath); +- err = symlink(oldpath, buffer); ++ } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH || ++ fs_ctx->export_flags & V9FS_SM_NONE) { ++ err = symlinkat(oldpath, dirfd, name); + if (err) { +- g_free(buffer); + goto out; + } +- err = lchown(buffer, credp->fc_uid, credp->fc_gid); ++ err = fchownat(dirfd, name, credp->fc_uid, credp->fc_gid, ++ AT_SYMLINK_NOFOLLOW); + if (err == -1) { + /* + * If we fail to change ownership and if we are + * using security model none. Ignore the error + */ + if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { +- serrno = errno; + goto err_end; +- } else ++ } else { + err = 0; ++ } + } + } + goto out; + + err_end: +- remove(buffer); +- errno = serrno; +- g_free(buffer); ++ unlinkat_preserve_errno(dirfd, name, 0); + out: +- v9fs_string_free(&fullname); ++ close_preserve_errno(dirfd); + return err; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-25.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-25.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-25.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-25.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,155 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From d815e7219036d6911fce12efe3e59906264c8536 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:44:54 +0100 +Subject: [PATCH] 9pfs: local: mknod: don't follow symlinks + +The local_mknod() callback is vulnerable to symlink attacks because it +calls: + +(1) mknod() which follows symbolic links for all path elements but the + rightmost one +(2) local_set_xattr()->setxattr() which follows symbolic links for all + path elements +(3) local_set_mapped_file_attr() which calls in turn local_fopen() and + mkdir(), both functions following symbolic links for all path + elements but the rightmost one +(4) local_post_create_passthrough() which calls in turn lchown() and + chmod(), both functions also following symbolic links + +This patch converts local_mknod() to rely on opendir_nofollow() and +mknodat() to fix (1), as well as local_set_xattrat() and +local_set_mapped_file_attrat() to fix (2) and (3) respectively. + +A new local_set_cred_passthrough() helper based on fchownat() and +fchmodat_nofollow() is introduced as a replacement to +local_post_create_passthrough() to fix (4). + +The mapped and mapped-file security modes are supposed to be identical, +except for the place where credentials and file modes are stored. While +here, we also make that explicit by sharing the call to mknodat(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 68 ++++++++++++++++++++++++++++-------------------------- + 1 file changed, 35 insertions(+), 33 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:44:35.673684625 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:46:59.295529938 -0400 +@@ -542,6 +542,23 @@ + return -1; + } + ++static int local_set_cred_passthrough(FsContext *fs_ctx, int dirfd, ++ const char *name, FsCred *credp) ++{ ++ if (fchownat(dirfd, name, credp->fc_uid, credp->fc_gid, ++ AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH) < 0) { ++ /* ++ * If we fail to change ownership and if we are ++ * using security model none. Ignore the error ++ */ ++ if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { ++ return -1; ++ } ++ } ++ ++ return fchmodat_nofollow(dirfd, name, credp->fc_mode & 07777); ++} ++ + static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, + char *buf, size_t bufsz) + { +@@ -732,64 +749,45 @@ + static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, + const char *name, FsCred *credp) + { +- char *path; + int err = -1; +- int serrno = 0; +- V9fsString fullname; +- char *buffer; +- +- v9fs_string_init(&fullname); +- v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); +- path = fullname.data; ++ int dirfd; + +- /* Determine the security model */ +- if (fs_ctx->export_flags & V9FS_SM_MAPPED) { +- buffer = rpath(fs_ctx, path); +- err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); +- if (err == -1) { +- g_free(buffer); +- goto out; +- } +- err = local_set_xattr(buffer, credp); +- if (err == -1) { +- serrno = errno; +- goto err_end; +- } +- } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); ++ if (dirfd == -1) { ++ return -1; ++ } + +- buffer = rpath(fs_ctx, path); +- err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED || ++ fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ err = mknodat(dirfd, name, SM_LOCAL_MODE_BITS | S_IFREG, 0); + if (err == -1) { +- g_free(buffer); + goto out; + } +- err = local_set_mapped_file_attr(fs_ctx, path, credp); ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { ++ err = local_set_xattrat(dirfd, name, credp); ++ } else { ++ err = local_set_mapped_file_attrat(dirfd, name, credp); ++ } + if (err == -1) { +- serrno = errno; + goto err_end; + } +- } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || +- (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, path); +- err = mknod(buffer, credp->fc_mode, credp->fc_rdev); ++ } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH || ++ fs_ctx->export_flags & V9FS_SM_NONE) { ++ err = mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev); + if (err == -1) { +- g_free(buffer); + goto out; + } +- err = local_post_create_passthrough(fs_ctx, path, credp); ++ err = local_set_cred_passthrough(fs_ctx, dirfd, name, credp); + if (err == -1) { +- serrno = errno; + goto err_end; + } + } + goto out; + + err_end: +- remove(buffer); +- errno = serrno; +- g_free(buffer); ++ unlinkat_preserve_errno(dirfd, name, 0); + out: +- v9fs_string_free(&fullname); ++ close_preserve_errno(dirfd); + return err; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-26.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-26.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-26.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-26.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,130 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 3f3a16990b09e62d787bd2eb2dd51aafbe90019a Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:45:02 +0100 +Subject: [PATCH] 9pfs: local: mkdir: don't follow symlinks + +The local_mkdir() callback is vulnerable to symlink attacks because it +calls: + +(1) mkdir() which follows symbolic links for all path elements but the + rightmost one +(2) local_set_xattr()->setxattr() which follows symbolic links for all + path elements +(3) local_set_mapped_file_attr() which calls in turn local_fopen() and + mkdir(), both functions following symbolic links for all path + elements but the rightmost one +(4) local_post_create_passthrough() which calls in turn lchown() and + chmod(), both functions also following symbolic links + +This patch converts local_mkdir() to rely on opendir_nofollow() and +mkdirat() to fix (1), as well as local_set_xattrat(), +local_set_mapped_file_attrat() and local_set_cred_passthrough() to +fix (2), (3) and (4) respectively. + +The mapped and mapped-file security modes are supposed to be identical, +except for the place where credentials and file modes are stored. While +here, we also make that explicit by sharing the call to mkdirat(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 55 ++++++++++++++++++++---------------------------------- + 1 file changed, 20 insertions(+), 35 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:47:47.348147338 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:49:54.265778028 -0400 +@@ -794,65 +794,47 @@ + static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, + const char *name, FsCred *credp) + { +- char *path; + int err = -1; +- int serrno = 0; +- V9fsString fullname; +- char *buffer; ++ int dirfd; + +- v9fs_string_init(&fullname); +- v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); +- path = fullname.data; ++ dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); ++ if (dirfd == -1) { ++ return -1; ++ } + +- /* Determine the security model */ +- if (fs_ctx->export_flags & V9FS_SM_MAPPED) { +- buffer = rpath(fs_ctx, path); +- err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED || ++ fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ err = mkdirat(dirfd, name, SM_LOCAL_DIR_MODE_BITS); + if (err == -1) { +- g_free(buffer); + goto out; + } +- credp->fc_mode = credp->fc_mode|S_IFDIR; +- err = local_set_xattr(buffer, credp); +- if (err == -1) { +- serrno = errno; +- goto err_end; +- } +- } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- buffer = rpath(fs_ctx, path); +- err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); +- if (err == -1) { +- g_free(buffer); +- goto out; ++ credp->fc_mode = credp->fc_mode | S_IFDIR; ++ ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { ++ err = local_set_xattrat(dirfd, name, credp); ++ } else { ++ err = local_set_mapped_file_attrat(dirfd, name, credp); + } +- credp->fc_mode = credp->fc_mode|S_IFDIR; +- err = local_set_mapped_file_attr(fs_ctx, path, credp); + if (err == -1) { +- serrno = errno; + goto err_end; + } +- } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || +- (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, path); +- err = mkdir(buffer, credp->fc_mode); ++ } else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH || ++ fs_ctx->export_flags & V9FS_SM_NONE) { ++ err = mkdirat(dirfd, name, credp->fc_mode); + if (err == -1) { +- g_free(buffer); + goto out; + } +- err = local_post_create_passthrough(fs_ctx, path, credp); ++ err = local_set_cred_passthrough(fs_ctx, dirfd, name, credp); + if (err == -1) { +- serrno = errno; + goto err_end; + } + } + goto out; + + err_end: +- remove(buffer); +- errno = serrno; +- g_free(buffer); ++ unlinkat_preserve_errno(dirfd, name, AT_REMOVEDIR); + out: +- v9fs_string_free(&fullname); ++ close_preserve_errno(dirfd); + return err; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-27.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-27.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-27.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-27.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,144 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From a565fea56546e254b7610305b07711f0a3bda0c7 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:45:09 +0100 +Subject: [PATCH] 9pfs: local: open2: don't follow symlinks + +The local_open2() callback is vulnerable to symlink attacks because it +calls: + +(1) open() which follows symbolic links for all path elements but the + rightmost one +(2) local_set_xattr()->setxattr() which follows symbolic links for all + path elements +(3) local_set_mapped_file_attr() which calls in turn local_fopen() and + mkdir(), both functions following symbolic links for all path + elements but the rightmost one +(4) local_post_create_passthrough() which calls in turn lchown() and + chmod(), both functions also following symbolic links + +This patch converts local_open2() to rely on opendir_nofollow() and +mkdirat() to fix (1), as well as local_set_xattrat(), +local_set_mapped_file_attrat() and local_set_cred_passthrough() to +fix (2), (3) and (4) respectively. Since local_open2() already opens +a descriptor to the target file, local_set_cred_passthrough() is +modified to reuse it instead of opening a new one. + +The mapped and mapped-file security modes are supposed to be identical, +except for the place where credentials and file modes are stored. While +here, we also make that explicit by sharing the call to openat(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 56 ++++++++++++++++++------------------------------------ + 1 file changed, 19 insertions(+), 37 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:50:11.093994244 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:53:00.292168172 -0400 +@@ -886,65 +886,45 @@ + static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, + int flags, FsCred *credp, V9fsFidOpenState *fs) + { +- char *path; + int fd = -1; + int err = -1; +- int serrno = 0; +- V9fsString fullname; +- char *buffer; ++ int dirfd; + + /* + * Mark all the open to not follow symlinks + */ + flags |= O_NOFOLLOW; + +- v9fs_string_init(&fullname); +- v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); +- path = fullname.data; ++ dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); ++ if (dirfd == -1) { ++ return -1; ++ } + + /* Determine the security model */ +- if (fs_ctx->export_flags & V9FS_SM_MAPPED) { +- buffer = rpath(fs_ctx, path); +- fd = open(buffer, flags, SM_LOCAL_MODE_BITS); ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED || ++ fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { ++ fd = openat_file(dirfd, name, flags, SM_LOCAL_MODE_BITS); + if (fd == -1) { +- g_free(buffer); +- err = fd; + goto out; + } + credp->fc_mode = credp->fc_mode|S_IFREG; +- /* Set cleint credentials in xattr */ +- err = local_set_xattr(buffer, credp); +- if (err == -1) { +- serrno = errno; +- goto err_end; ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { ++ /* Set cleint credentials in xattr */ ++ err = local_set_xattrat(dirfd, name, credp); ++ } else { ++ err = local_set_mapped_file_attrat(dirfd, name, credp); + } +- } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { +- buffer = rpath(fs_ctx, path); +- fd = open(buffer, flags, SM_LOCAL_MODE_BITS); +- if (fd == -1) { +- g_free(buffer); +- err = fd; +- goto out; +- } +- credp->fc_mode = credp->fc_mode|S_IFREG; +- /* Set client credentials in .virtfs_metadata directory files */ +- err = local_set_mapped_file_attr(fs_ctx, path, credp); + if (err == -1) { +- serrno = errno; + goto err_end; + } + } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || + (fs_ctx->export_flags & V9FS_SM_NONE)) { +- buffer = rpath(fs_ctx, path); +- fd = open(buffer, flags, credp->fc_mode); ++ fd = openat_file(dirfd, name, flags, credp->fc_mode); + if (fd == -1) { +- g_free(buffer); +- err = fd; + goto out; + } +- err = local_post_create_passthrough(fs_ctx, path, credp); ++ err = local_set_cred_passthrough(fs_ctx, dirfd, name, credp); + if (err == -1) { +- serrno = errno; + goto err_end; + } + } +@@ -953,12 +933,11 @@ + goto out; + + err_end: +- close(fd); +- remove(buffer); +- errno = serrno; +- g_free(buffer); ++ unlinkat_preserve_errno(dirfd, name, ++ flags & O_DIRECTORY ? AT_REMOVEDIR : 0); ++ close_preserve_errno(fd); + out: +- v9fs_string_free(&fullname); ++ close_preserve_errno(dirfd); + return err; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-28.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-28.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-28.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-28.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,244 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From c23d5f1d5bc0e23aeb845b1af8f996f16783ce98 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:45:17 +0100 +Subject: [PATCH] 9pfs: local: drop unused code + +Now that the all callbacks have been converted to use "at" syscalls, we +can drop this code. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 198 ----------------------------------------------------- + 1 file changed, 198 deletions(-) + +Index: qemu/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-local.c ++++ qemu/hw/9pfs/virtio-9p-local.c +@@ -82,50 +82,6 @@ static void unlinkat_preserve_errno(int + + #define VIRTFS_META_DIR ".virtfs_metadata" + +-static char *local_mapped_attr_path(FsContext *ctx, const char *path) +-{ +- char *dir_name; +- char *tmp_path = g_strdup(path); +- char *base_name = basename(tmp_path); +- char *buffer; +- +- /* NULL terminate the directory */ +- dir_name = tmp_path; +- *(base_name - 1) = '\0'; +- +- buffer = g_strdup_printf("%s/%s/%s/%s", +- ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name); +- g_free(tmp_path); +- return buffer; +-} +- +-static FILE *local_fopen(const char *path, const char *mode) +-{ +- int fd, o_mode = 0; +- FILE *fp; +- int flags = O_NOFOLLOW; +- /* +- * only supports two modes +- */ +- if (mode[0] == 'r') { +- flags |= O_RDONLY; +- } else if (mode[0] == 'w') { +- flags |= O_WRONLY | O_TRUNC | O_CREAT; +- o_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; +- } else { +- return NULL; +- } +- fd = open(path, flags, o_mode); +- if (fd == -1) { +- return NULL; +- } +- fp = fdopen(fd, mode); +- if (!fp) { +- close(fd); +- } +- return fp; +-} +- + static FILE *local_fopenat(int dirfd, const char *name, const char *mode) + { + int fd, o_mode = 0; +@@ -239,135 +195,6 @@ out: + return err; + } + +-static int local_create_mapped_attr_dir(FsContext *ctx, const char *path) +-{ +- int err; +- char *attr_dir; +- char *tmp_path = g_strdup(path); +- +- attr_dir = g_strdup_printf("%s/%s/%s", +- ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); +- +- err = mkdir(attr_dir, 0700); +- if (err < 0 && errno == EEXIST) { +- err = 0; +- } +- g_free(attr_dir); +- g_free(tmp_path); +- return err; +-} +- +-static int local_set_mapped_file_attr(FsContext *ctx, +- const char *path, FsCred *credp) +-{ +- FILE *fp; +- int ret = 0; +- char buf[ATTR_MAX]; +- char *attr_path; +- int uid = -1, gid = -1, mode = -1, rdev = -1; +- +- attr_path = local_mapped_attr_path(ctx, path); +- fp = local_fopen(attr_path, "r"); +- if (!fp) { +- goto create_map_file; +- } +- memset(buf, 0, ATTR_MAX); +- while (fgets(buf, ATTR_MAX, fp)) { +- if (!strncmp(buf, "virtfs.uid", 10)) { +- uid = atoi(buf+11); +- } else if (!strncmp(buf, "virtfs.gid", 10)) { +- gid = atoi(buf+11); +- } else if (!strncmp(buf, "virtfs.mode", 11)) { +- mode = atoi(buf+12); +- } else if (!strncmp(buf, "virtfs.rdev", 11)) { +- rdev = atoi(buf+12); +- } +- memset(buf, 0, ATTR_MAX); +- } +- fclose(fp); +- goto update_map_file; +- +-create_map_file: +- ret = local_create_mapped_attr_dir(ctx, path); +- if (ret < 0) { +- goto err_out; +- } +- +-update_map_file: +- fp = local_fopen(attr_path, "w"); +- if (!fp) { +- ret = -1; +- goto err_out; +- } +- +- if (credp->fc_uid != -1) { +- uid = credp->fc_uid; +- } +- if (credp->fc_gid != -1) { +- gid = credp->fc_gid; +- } +- if (credp->fc_mode != -1) { +- mode = credp->fc_mode; +- } +- if (credp->fc_rdev != -1) { +- rdev = credp->fc_rdev; +- } +- +- +- if (uid != -1) { +- fprintf(fp, "virtfs.uid=%d\n", uid); +- } +- if (gid != -1) { +- fprintf(fp, "virtfs.gid=%d\n", gid); +- } +- if (mode != -1) { +- fprintf(fp, "virtfs.mode=%d\n", mode); +- } +- if (rdev != -1) { +- fprintf(fp, "virtfs.rdev=%d\n", rdev); +- } +- fclose(fp); +- +-err_out: +- g_free(attr_path); +- return ret; +-} +- +-static int local_set_xattr(const char *path, FsCred *credp) +-{ +- int err; +- +- if (credp->fc_uid != -1) { +- uint32_t tmp_uid = cpu_to_le32(credp->fc_uid); +- err = setxattr(path, "user.virtfs.uid", &tmp_uid, sizeof(uid_t), 0); +- if (err) { +- return err; +- } +- } +- if (credp->fc_gid != -1) { +- uint32_t tmp_gid = cpu_to_le32(credp->fc_gid); +- err = setxattr(path, "user.virtfs.gid", &tmp_gid, sizeof(gid_t), 0); +- if (err) { +- return err; +- } +- } +- if (credp->fc_mode != -1) { +- uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); +- err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0); +- if (err) { +- return err; +- } +- } +- if (credp->fc_rdev != -1) { +- uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev); +- err = setxattr(path, "user.virtfs.rdev", &tmp_rdev, sizeof(dev_t), 0); +- if (err) { +- return err; +- } +- } +- return 0; +-} +- + static int local_set_mapped_file_attrat(int dirfd, const char *name, + FsCred *credp) + { +@@ -517,33 +344,6 @@ static int local_set_xattrat(int dirfd, + return 0; + } + +-static int local_post_create_passthrough(FsContext *fs_ctx, const char *path, +- FsCred *credp) +-{ +- char *buffer; +- +- buffer = rpath(fs_ctx, path); +- if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) { +- /* +- * If we fail to change ownership and if we are +- * using security model none. Ignore the error +- */ +- if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { +- goto err; +- } +- } +- +- if (chmod(buffer, credp->fc_mode & 07777) < 0) { +- goto err; +- } +- +- g_free(buffer); +- return 0; +-err: +- g_free(buffer); +- return -1; +-} +- + static int local_set_cred_passthrough(FsContext *fs_ctx, int dirfd, + const char *name, FsCred *credp) + { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-29.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-29.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-29.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-29.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,53 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From b003fc0d8aa5e7060dbf7e5862b8013c73857c7f Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Mon, 6 Mar 2017 17:34:01 +0100 +Subject: [PATCH] 9pfs: fix vulnerability in openat_dir() and + local_unlinkat_common() + +We should pass O_NOFOLLOW otherwise openat() will follow symlinks and make +QEMU vulnerable. + +While here, we also fix local_unlinkat_common() to use openat_dir() for +the same reasons (it was a leftover in the original patchset actually). + +This fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Daniel P. Berrange <berrange@redhat.com> +Reviewed-by: Eric Blake <eblake@redhat.com> +--- + hw/9pfs/9p-local.c | 2 +- + hw/9pfs/9p-util.h | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-04 14:05:54.056515474 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-04 14:05:54.052515422 -0400 +@@ -956,7 +956,7 @@ + if (flags == AT_REMOVEDIR) { + int fd; + +- fd = openat(dirfd, name, O_RDONLY | O_DIRECTORY | O_PATH); ++ fd = openat_dir(dirfd, name); + if (fd == -1) { + goto err_out; + } +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-util.h +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-util.h 2017-04-04 14:05:54.056515474 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-util.h 2017-04-04 14:05:54.056515474 -0400 +@@ -22,7 +22,7 @@ + + static inline int openat_dir(int dirfd, const char *name) + { +- return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_PATH); ++ return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_PATH); + } + + static inline int openat_file(int dirfd, const char *name, int flags, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-2.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-2.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,75 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 00c90bd1c2ff6aabb9ca948a254ba044a403e399 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:41:48 +0100 +Subject: [PATCH] 9pfs: remove side-effects in local_init() + +If this function fails, it should not modify *ctx. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 37 +++++++++++++++++++------------------ + 1 file changed, 19 insertions(+), 18 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:29:08.129767157 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:29:08.125767106 -0400 +@@ -1183,9 +1183,25 @@ + + static int local_init(FsContext *ctx) + { +- int err = 0; + struct statfs stbuf; + ++#ifdef FS_IOC_GETVERSION ++ /* ++ * use ioc_getversion only if the ioctl is definied ++ */ ++ if (statfs(ctx->fs_root, &stbuf) < 0) { ++ return -1; ++ } ++ switch (stbuf.f_type) { ++ case EXT2_SUPER_MAGIC: ++ case BTRFS_SUPER_MAGIC: ++ case REISERFS_SUPER_MAGIC: ++ case XFS_SUPER_MAGIC: ++ ctx->exops.get_st_gen = local_ioc_getversion; ++ break; ++ } ++#endif ++ + if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { + ctx->xops = passthrough_xattr_ops; + } else if (ctx->export_flags & V9FS_SM_MAPPED) { +@@ -1200,23 +1216,8 @@ + ctx->xops = passthrough_xattr_ops; + } + ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; +-#ifdef FS_IOC_GETVERSION +- /* +- * use ioc_getversion only if the iocl is definied +- */ +- err = statfs(ctx->fs_root, &stbuf); +- if (!err) { +- switch (stbuf.f_type) { +- case EXT2_SUPER_MAGIC: +- case BTRFS_SUPER_MAGIC: +- case REISERFS_SUPER_MAGIC: +- case XFS_SUPER_MAGIC: +- ctx->exops.get_st_gen = local_ioc_getversion; +- break; +- } +- } +-#endif +- return err; ++ ++ return 0; + } + + static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-3.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-3.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-3.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-3.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,58 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 21328e1e57f526e3f0c2fcd00f10c8aa6e7bc07f Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:41:55 +0100 +Subject: [PATCH] 9pfs: remove side-effects in local_open() and local_opendir() + +If these functions fail, they should not change *fs. Let's use local +variables to fix this. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-local.c 2017-04-05 11:31:19.635456797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-local.c 2017-04-05 11:31:19.631456746 -0400 +@@ -356,10 +356,15 @@ + { + char *buffer; + char *path = fs_path->data; ++ int fd; + + buffer = rpath(ctx, path); +- fs->fd = open(buffer, flags | O_NOFOLLOW); ++ fd = open(buffer, flags | O_NOFOLLOW); + g_free(buffer); ++ if (fd == -1) { ++ return -1; ++ } ++ fs->fd = fd; + return fs->fd; + } + +@@ -368,13 +373,15 @@ + { + char *buffer; + char *path = fs_path->data; ++ DIR *stream; + + buffer = rpath(ctx, path); +- fs->dir = opendir(buffer); ++ stream = opendir(buffer); + g_free(buffer); +- if (!fs->dir) { ++ if (!stream) { + return -1; + } ++ fs->dir = stream; + return 0; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-4.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-4.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-4.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-4.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,191 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 6482a961636d66cc10928dde5d4d908206e5f65a Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:03 +0100 +Subject: [PATCH] 9pfs: introduce relative_openat_nofollow() helper + +When using the passthrough security mode, symbolic links created by the +guest are actual symbolic links on the host file system. + +Since the resolution of symbolic links during path walk is supposed to +occur on the client side. The server should hence never receive any path +pointing to an actual symbolic link. This isn't guaranteed by the protocol +though, and malicious code in the guest can trick the server to issue +various syscalls on paths whose one or more elements are symbolic links. +In the case of the "local" backend using the "passthrough" or "none" +security modes, the guest can directly create symbolic links to arbitrary +locations on the host (as per spec). The "mapped-xattr" and "mapped-file" +security modes are also affected to a lesser extent as they require some +help from an external entity to create actual symbolic links on the host, +i.e. another guest using "passthrough" mode for example. + +The current code hence relies on O_NOFOLLOW and "l*()" variants of system +calls. Unfortunately, this only applies to the rightmost path component. +A guest could maliciously replace any component in a trusted path with a +symbolic link. This could allow any guest to escape a virtfs shared folder. + +This patch introduces a variant of the openat() syscall that successively +opens each path element with O_NOFOLLOW. When passing a file descriptor +pointing to a trusted directory, one is guaranteed to be returned a +file descriptor pointing to a path which is beneath the trusted directory. +This will be used by subsequent patches to implement symlink-safe path walk +for any access to the backend. + +Symbolic links aren't the only threats actually: a malicious guest could +change a path element to point to other types of file with undesirable +effects: +- a named pipe or any other thing that would cause openat() to block +- a terminal device which would become QEMU's controlling terminal + +These issues can be addressed with O_NONBLOCK and O_NOCTTY. + +Two helpers are introduced: one to open intermediate path elements and one +to open the rightmost path element. + +Suggested-by: Jann Horn <jannh@google.com> +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +(renamed openat_nofollow() to relative_openat_nofollow(), + assert path is relative and doesn't contain '//', + fixed side-effect in assert, Greg Kurz) +Signed-off-by: Greg Kurz <groug@kaod.org> +--- + hw/9pfs/9p-util.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ + hw/9pfs/9p-util.h | 50 ++++++++++++++++++++++++++++++++++++++++++++ + hw/9pfs/Makefile.objs | 2 +- + 3 files changed, 108 insertions(+), 1 deletion(-) + create mode 100644 hw/9pfs/9p-util.c + create mode 100644 hw/9pfs/9p-util.h + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.c 2017-04-06 08:58:38.617979891 -0400 +@@ -0,0 +1,58 @@ ++/* ++ * 9p utilities ++ * ++ * Copyright IBM, Corp. 2017 ++ * ++ * Authors: ++ * Greg Kurz <groug@kaod.org> ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/virtio/virtio.h" ++#include "virtio-9p-util.h" ++ ++int relative_openat_nofollow(int dirfd, const char *path, int flags, ++ mode_t mode) ++{ ++ int fd; ++ ++ fd = dup(dirfd); ++ if (fd == -1) { ++ return -1; ++ } ++ ++ while (*path) { ++ const char *c; ++ int next_fd; ++ char *head; ++ ++ /* Only relative paths without consecutive slashes */ ++ assert(path[0] != '/'); ++ ++ head = g_strdup(path); ++ c = strchr(path, '/'); ++ if (c) { ++ head[c - path] = 0; ++ next_fd = openat_dir(fd, head); ++ } else { ++ next_fd = openat_file(fd, head, flags, mode); ++ } ++ g_free(head); ++ if (next_fd == -1) { ++ close_preserve_errno(fd); ++ return -1; ++ } ++ close(fd); ++ fd = next_fd; ++ ++ if (!c) { ++ break; ++ } ++ path = c + 1; ++ } ++ ++ return fd; ++} +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.h 2017-04-06 08:58:23.481788107 -0400 +@@ -0,0 +1,50 @@ ++/* ++ * 9p utilities ++ * ++ * Copyright IBM, Corp. 2017 ++ * ++ * Authors: ++ * Greg Kurz <groug@kaod.org> ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef QEMU_9P_UTIL_H ++#define QEMU_9P_UTIL_H ++ ++static inline void close_preserve_errno(int fd) ++{ ++ int serrno = errno; ++ close(fd); ++ errno = serrno; ++} ++ ++static inline int openat_dir(int dirfd, const char *name) ++{ ++ return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_PATH); ++} ++ ++static inline int openat_file(int dirfd, const char *name, int flags, ++ mode_t mode) ++{ ++ int fd, serrno, ret; ++ ++ fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK, ++ mode); ++ if (fd == -1) { ++ return -1; ++ } ++ ++ serrno = errno; ++ /* O_NONBLOCK was only needed to open the file. Let's drop it. */ ++ ret = fcntl(fd, F_SETFL, flags); ++ assert(!ret); ++ errno = serrno; ++ return fd; ++} ++ ++int relative_openat_nofollow(int dirfd, const char *path, int flags, ++ mode_t mode); ++ ++#endif +Index: qemu-2.0.0+dfsg/hw/9pfs/Makefile.objs +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/Makefile.objs 2017-04-06 08:58:23.481788107 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/Makefile.objs 2017-04-06 08:58:23.481788107 -0400 +@@ -1,4 +1,4 @@ +-common-obj-y = virtio-9p.o ++common-obj-y = virtio-9p.o virtio-9p-util.o + common-obj-y += virtio-9p-local.o virtio-9p-xattr.o + common-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o + common-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-5.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-5.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-5.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-5.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,94 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 0e35a3782948c6154d7fafe9a02a86bc130199c7 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:10 +0100 +Subject: [PATCH] 9pfs: local: keep a file descriptor on the shared folder + +This patch opens the shared folder and caches the file descriptor, so that +it can be used to do symlink-safe path walk. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +Index: qemu/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-local.c ++++ qemu/hw/9pfs/virtio-9p-local.c +@@ -14,6 +14,7 @@ + #include "hw/virtio/virtio.h" + #include "virtio-9p.h" + #include "virtio-9p-xattr.h" ++#include "virtio-9p-util.h" + #include "fsdev/qemu-fsdev.h" /* local_ops */ + #include <arpa/inet.h> + #include <pwd.h> +@@ -41,6 +42,10 @@ + #define BTRFS_SUPER_MAGIC 0x9123683E + #endif + ++typedef struct { ++ int mountfd; ++} LocalData; ++ + #define VIRTFS_META_DIR ".virtfs_metadata" + + static char *local_mapped_attr_path(FsContext *ctx, const char *path) +@@ -1192,13 +1197,20 @@ static int local_ioc_getversion(FsContex + static int local_init(FsContext *ctx) + { + struct statfs stbuf; ++ LocalData *data = g_malloc(sizeof(*data)); ++ ++ data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY); ++ if (data->mountfd == -1) { ++ goto err; ++ } + + #ifdef FS_IOC_GETVERSION + /* + * use ioc_getversion only if the ioctl is definied + */ +- if (statfs(ctx->fs_root, &stbuf) < 0) { +- return -1; ++ if (fstatfs(data->mountfd, &stbuf) < 0) { ++ close_preserve_errno(data->mountfd); ++ goto err; + } + switch (stbuf.f_type) { + case EXT2_SUPER_MAGIC: +@@ -1225,7 +1237,20 @@ static int local_init(FsContext *ctx) + } + ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; + ++ ctx->private = data; + return 0; ++ ++err: ++ g_free(data); ++ return -1; ++} ++ ++static void local_cleanup(FsContext *ctx) ++{ ++ LocalData *data = ctx->private; ++ ++ close(data->mountfd); ++ g_free(data); + } + + static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) +@@ -1268,6 +1293,7 @@ static int local_parse_opts(QemuOpts *op + FileOperations local_ops = { + .parse_opts = local_parse_opts, + .init = local_init, ++ .cleanup = local_cleanup, + .lstat = local_lstat, + .readlink = local_readlink, + .close = local_close, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-6.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-6.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-6.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-6.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,129 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 996a0d76d7e756e4023ef79bc37bfe629b9eaca7 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:18 +0100 +Subject: [PATCH] 9pfs: local: open/opendir: don't follow symlinks + +The local_open() and local_opendir() callbacks are vulnerable to symlink +attacks because they call: + +(1) open(O_NOFOLLOW) which follows symbolic links in all path elements but + the rightmost one +(2) opendir() which follows symbolic links in all path elements + +This patch converts both callbacks to use new helpers based on +openat_nofollow() to only open files and directories if they are +below the virtfs shared folder + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-local.c | 37 +++++++++++++++++++++++++++---------- + hw/9pfs/9p-local.h | 20 ++++++++++++++++++++ + 2 files changed, 47 insertions(+), 10 deletions(-) + create mode 100644 hw/9pfs/9p-local.h + +Index: qemu/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-local.c ++++ qemu/hw/9pfs/virtio-9p-local.c +@@ -13,6 +13,7 @@ + + #include "hw/virtio/virtio.h" + #include "virtio-9p.h" ++#include "virtio-9p-local.h" + #include "virtio-9p-xattr.h" + #include "virtio-9p-util.h" + #include "fsdev/qemu-fsdev.h" /* local_ops */ +@@ -46,6 +47,24 @@ typedef struct { + int mountfd; + } LocalData; + ++int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, ++ mode_t mode) ++{ ++ LocalData *data = fs_ctx->private; ++ ++ /* All paths are relative to the path data->mountfd points to */ ++ while (*path == '/') { ++ path++; ++ } ++ ++ return relative_openat_nofollow(data->mountfd, path, flags, mode); ++} ++ ++int local_opendir_nofollow(FsContext *fs_ctx, const char *path) ++{ ++ return local_open_nofollow(fs_ctx, path, O_DIRECTORY | O_RDONLY, 0); ++} ++ + #define VIRTFS_META_DIR ".virtfs_metadata" + + static char *local_mapped_attr_path(FsContext *ctx, const char *path) +@@ -360,13 +379,9 @@ static int local_closedir(FsContext *ctx + static int local_open(FsContext *ctx, V9fsPath *fs_path, + int flags, V9fsFidOpenState *fs) + { +- char *buffer; +- char *path = fs_path->data; + int fd; + +- buffer = rpath(ctx, path); +- fd = open(buffer, flags | O_NOFOLLOW); +- g_free(buffer); ++ fd = local_open_nofollow(ctx, fs_path->data, flags, 0); + if (fd == -1) { + return -1; + } +@@ -377,13 +392,15 @@ static int local_open(FsContext *ctx, V9 + static int local_opendir(FsContext *ctx, + V9fsPath *fs_path, V9fsFidOpenState *fs) + { +- char *buffer; +- char *path = fs_path->data; ++ int dirfd; + DIR *stream; + +- buffer = rpath(ctx, path); +- stream = opendir(buffer); +- g_free(buffer); ++ dirfd = local_opendir_nofollow(ctx, fs_path->data); ++ if (dirfd == -1) { ++ return -1; ++ } ++ ++ stream = fdopendir(dirfd); + if (!stream) { + return -1; + } +Index: qemu/hw/9pfs/virtio-9p-local.h +=================================================================== +--- /dev/null ++++ qemu/hw/9pfs/virtio-9p-local.h +@@ -0,0 +1,20 @@ ++/* ++ * 9p local backend utilities ++ * ++ * Copyright IBM, Corp. 2017 ++ * ++ * Authors: ++ * Greg Kurz <groug@kaod.org> ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef QEMU_9P_LOCAL_H ++#define QEMU_9P_LOCAL_H ++ ++int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, ++ mode_t mode); ++int local_opendir_nofollow(FsContext *fs_ctx, const char *path); ++ ++#endif diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-7.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-7.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-7.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-7.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,197 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 56ad3e54dad6cdcee8668d170df161d89581846f Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:26 +0100 +Subject: [PATCH] 9pfs: local: lgetxattr: don't follow symlinks + +The local_lgetxattr() callback is vulnerable to symlink attacks because +it calls lgetxattr() which follows symbolic links in all path elements but +the rightmost one. + +This patch introduces a helper to emulate the non-existing fgetxattrat() +function: it is implemented with /proc/self/fd which provides a trusted +path that can be safely passed to lgetxattr(). + +local_lgetxattr() is converted to use this helper and opendir_nofollow(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-posix-acl.c | 16 ++-------------- + hw/9pfs/9p-util.c | 12 ++++++++++++ + hw/9pfs/9p-util.h | 2 ++ + hw/9pfs/9p-xattr-user.c | 8 +------- + hw/9pfs/9p-xattr.c | 31 ++++++++++++++++++++++++------- + hw/9pfs/9p-xattr.h | 2 ++ + 6 files changed, 43 insertions(+), 28 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-posix-acl.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-posix-acl.c 2017-04-06 08:58:51.798146797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-posix-acl.c 2017-04-06 08:58:51.794146746 -0400 +@@ -26,13 +26,7 @@ + static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path, + const char *name, void *value, size_t size) + { +- char *buffer; +- ssize_t ret; +- +- buffer = rpath(ctx, path); +- ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size); +- g_free(buffer); +- return ret; ++ return local_getxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size); + } + + static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path, +@@ -90,13 +84,7 @@ + static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path, + const char *name, void *value, size_t size) + { +- char *buffer; +- ssize_t ret; +- +- buffer = rpath(ctx, path); +- ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size); +- g_free(buffer); +- return ret; ++ return local_getxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size); + } + + static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path, +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-util.c 2017-04-06 08:58:51.798146797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.c 2017-04-06 08:59:04.450306939 -0400 +@@ -11,6 +11,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/xattr.h" + #include "hw/virtio/virtio.h" + #include "virtio-9p-util.h" + +@@ -56,3 +57,14 @@ + + return fd; + } ++ ++ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name, ++ void *value, size_t size) ++{ ++ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename); ++ int ret; ++ ++ ret = lgetxattr(proc_path, name, value, size); ++ g_free(proc_path); ++ return ret; ++} +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-util.h 2017-04-06 08:58:51.798146797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-util.h 2017-04-06 08:58:51.794146746 -0400 +@@ -46,5 +46,7 @@ + + int relative_openat_nofollow(int dirfd, const char *path, int flags, + mode_t mode); ++ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name, ++ void *value, size_t size); + + #endif +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-xattr-user.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-xattr-user.c 2017-04-06 08:58:51.798146797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-xattr-user.c 2017-04-06 08:58:51.794146746 -0400 +@@ -21,9 +21,6 @@ + static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, + const char *name, void *value, size_t size) + { +- char *buffer; +- ssize_t ret; +- + if (strncmp(name, "user.virtfs.", 12) == 0) { + /* + * Don't allow fetch of user.virtfs namesapce +@@ -32,10 +29,7 @@ + errno = ENOATTR; + return -1; + } +- buffer = rpath(ctx, path); +- ret = lgetxattr(buffer, name, value, size); +- g_free(buffer); +- return ret; ++ return local_getxattr_nofollow(ctx, path, name, value, size); + } + + static ssize_t mp_user_listxattr(FsContext *ctx, const char *path, +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-xattr.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-xattr.c 2017-04-06 08:58:51.798146797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-xattr.c 2017-04-06 08:58:51.794146746 -0400 +@@ -15,6 +15,8 @@ + #include "virtio-9p.h" + #include "fsdev/file-op-9p.h" + #include "virtio-9p-xattr.h" ++#include "virtio-9p-util.h" ++#include "virtio-9p-local.h" + + + static XattrOperations *get_xattr_operations(XattrOperations **h, +@@ -143,16 +145,31 @@ + + } + ++ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path, ++ const char *name, void *value, size_t size) ++{ ++ char *dirpath = g_path_get_dirname(path); ++ char *filename = g_path_get_basename(path); ++ int dirfd; ++ ssize_t ret = -1; ++ ++ dirfd = local_opendir_nofollow(ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } ++ ++ ret = fgetxattrat_nofollow(dirfd, filename, name, value, size); ++ close_preserve_errno(dirfd); ++out: ++ g_free(dirpath); ++ g_free(filename); ++ return ret; ++} ++ + ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size) + { +- char *buffer; +- ssize_t ret; +- +- buffer = rpath(ctx, path); +- ret = lgetxattr(buffer, name, value, size); +- g_free(buffer); +- return ret; ++ return local_getxattr_nofollow(ctx, path, name, value, size); + } + + int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-xattr.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-xattr.h 2017-04-06 08:58:51.798146797 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-xattr.h 2017-04-06 08:58:51.794146746 -0400 +@@ -28,6 +28,8 @@ + const char *path, const char *name); + } XattrOperations; + ++ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path, ++ const char *name, void *value, size_t size); + + extern XattrOperations mapped_user_xattr; + extern XattrOperations passthrough_user_xattr; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-8.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-8.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-8.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-8.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,96 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 5507904e362df252f6065cb27d1ff98372db6abc Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:34 +0100 +Subject: [PATCH] 9pfs: local: llistxattr: don't follow symlinks + +The local_llistxattr() callback is vulnerable to symlink attacks because +it calls llistxattr() which follows symbolic links in all path elements but +the rightmost one. + +This patch introduces a helper to emulate the non-existing flistxattrat() +function: it is implemented with /proc/self/fd which provides a trusted +path that can be safely passed to llistxattr(). + +local_llistxattr() is converted to use this helper and opendir_nofollow(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-xattr.c | 35 +++++++++++++++++++++++++++++------ + 1 file changed, 29 insertions(+), 6 deletions(-) + +diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c +index aa4391e..54193c6 100644 +--- a/hw/9pfs/virtio-9p-xattr.c ++++ b/hw/9pfs/virtio-9p-xattr.c +@@ -60,6 +60,16 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, + return name_size; + } + ++static ssize_t flistxattrat_nofollow(int dirfd, const char *filename, ++ char *list, size_t size) ++{ ++ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename); ++ int ret; ++ ++ ret = llistxattr(proc_path, list, size); ++ g_free(proc_path); ++ return ret; ++} + + /* + * Get the list and pass to each layer to find out whether +@@ -69,24 +79,37 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, + void *value, size_t vsize) + { + ssize_t size = 0; +- char *buffer; + void *ovalue = value; + XattrOperations *xops; + char *orig_value, *orig_value_start; + ssize_t xattr_len, parsed_len = 0, attr_len; ++ char *dirpath, *name; ++ int dirfd; + + /* Get the actual len */ +- buffer = rpath(ctx, path); +- xattr_len = llistxattr(buffer, value, 0); ++ dirpath = g_path_get_dirname(path); ++ dirfd = local_opendir_nofollow(ctx, dirpath); ++ g_free(dirpath); ++ if (dirfd == -1) { ++ return -1; ++ } ++ ++ name = g_path_get_basename(path); ++ xattr_len = flistxattrat_nofollow(dirfd, name, value, 0); + if (xattr_len <= 0) { +- g_free(buffer); ++ g_free(name); ++ close_preserve_errno(dirfd); + return xattr_len; + } + + /* Now fetch the xattr and find the actual size */ + orig_value = g_malloc(xattr_len); +- xattr_len = llistxattr(buffer, orig_value, xattr_len); +- g_free(buffer); ++ xattr_len = flistxattrat_nofollow(dirfd, name, orig_value, xattr_len); ++ g_free(name); ++ close_preserve_errno(dirfd); ++ if (xattr_len < 0) { ++ return -1; ++ } + + /* store the orig pointer */ + orig_value_start = orig_value; +-- +1.8.3.1 + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-9.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-9.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-9.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-9.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,176 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 3e36aba757f76673007a80b3cd56a4062c2e3462 Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Sun, 26 Feb 2017 23:42:43 +0100 +Subject: [PATCH] 9pfs: local: lsetxattr: don't follow symlinks + +The local_lsetxattr() callback is vulnerable to symlink attacks because +it calls lsetxattr() which follows symbolic links in all path elements but +the rightmost one. + +This patch introduces a helper to emulate the non-existing fsetxattrat() +function: it is implemented with /proc/self/fd which provides a trusted +path that can be safely passed to lsetxattr(). + +local_lsetxattr() is converted to use this helper and opendir_nofollow(). + +This partly fixes CVE-2016-9602. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> +--- + hw/9pfs/9p-posix-acl.c | 18 ++++-------------- + hw/9pfs/9p-util.h | 2 ++ + hw/9pfs/9p-xattr-user.c | 8 +------- + hw/9pfs/9p-xattr.c | 39 +++++++++++++++++++++++++++++++++------ + hw/9pfs/9p-xattr.h | 3 +++ + 5 files changed, 43 insertions(+), 27 deletions(-) + +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-posix-acl.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-posix-acl.c 2017-04-04 14:03:42.470824807 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-posix-acl.c 2017-04-04 14:03:42.466824755 -0400 +@@ -51,13 +51,8 @@ + static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size, int flags) + { +- char *buffer; +- int ret; +- +- buffer = rpath(ctx, path); +- ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags); +- g_free(buffer); +- return ret; ++ return local_setxattr_nofollow(ctx, path, MAP_ACL_ACCESS, value, size, ++ flags); + } + + static int mp_pacl_removexattr(FsContext *ctx, +@@ -109,13 +104,8 @@ + static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size, int flags) + { +- char *buffer; +- int ret; +- +- buffer = rpath(ctx, path); +- ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags); +- g_free(buffer); +- return ret; ++ return local_setxattr_nofollow(ctx, path, MAP_ACL_DEFAULT, value, size, ++ flags); + } + + static int mp_dacl_removexattr(FsContext *ctx, +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-util.h +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-util.h 2017-04-04 14:03:42.470824807 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-util.h 2017-04-04 14:03:42.466824755 -0400 +@@ -48,5 +48,7 @@ + mode_t mode); + ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name, + void *value, size_t size); ++int fsetxattrat_nofollow(int dirfd, const char *path, const char *name, ++ void *value, size_t size, int flags); + + #endif +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr-user.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-xattr-user.c 2017-04-04 14:03:42.470824807 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr-user.c 2017-04-04 14:03:42.466824755 -0400 +@@ -68,9 +68,6 @@ + static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name, + void *value, size_t size, int flags) + { +- char *buffer; +- int ret; +- + if (strncmp(name, "user.virtfs.", 12) == 0) { + /* + * Don't allow fetch of user.virtfs namesapce +@@ -79,10 +76,7 @@ + errno = EACCES; + return -1; + } +- buffer = rpath(ctx, path); +- ret = lsetxattr(buffer, name, value, size, flags); +- g_free(buffer); +- return ret; ++ return local_setxattr_nofollow(ctx, path, name, value, size, flags); + } + + static int mp_user_removexattr(FsContext *ctx, +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-xattr.c 2017-04-04 14:03:42.470824807 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.c 2017-04-04 14:03:42.466824755 -0400 +@@ -195,18 +195,45 @@ + return local_getxattr_nofollow(ctx, path, name, value, size); + } + +-int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, +- size_t size, int flags) ++int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name, ++ void *value, size_t size, int flags) + { +- char *buffer; ++ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename); + int ret; + +- buffer = rpath(ctx, path); +- ret = lsetxattr(buffer, name, value, size, flags); +- g_free(buffer); ++ ret = lsetxattr(proc_path, name, value, size, flags); ++ g_free(proc_path); + return ret; + } + ++ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path, ++ const char *name, void *value, size_t size, ++ int flags) ++{ ++ char *dirpath = g_path_get_dirname(path); ++ char *filename = g_path_get_basename(path); ++ int dirfd; ++ ssize_t ret = -1; ++ ++ dirfd = local_opendir_nofollow(ctx, dirpath); ++ if (dirfd == -1) { ++ goto out; ++ } ++ ++ ret = fsetxattrat_nofollow(dirfd, filename, name, value, size, flags); ++ close_preserve_errno(dirfd); ++out: ++ g_free(dirpath); ++ g_free(filename); ++ return ret; ++} ++ ++int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, ++ size_t size, int flags) ++{ ++ return local_setxattr_nofollow(ctx, path, name, value, size, flags); ++} ++ + int pt_removexattr(FsContext *ctx, const char *path, const char *name) + { + char *buffer; +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.h +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-xattr.h 2017-04-04 14:03:42.470824807 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-xattr.h 2017-04-04 14:03:42.466824755 -0400 +@@ -30,6 +30,9 @@ + + ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path, + const char *name, void *value, size_t size); ++ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path, ++ const char *name, void *value, size_t size, ++ int flags); + + extern XattrOperations mapped_user_xattr; + extern XattrOperations passthrough_user_xattr; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9602-pre.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9602-pre.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9602-pre.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9602-pre.patch 2018-07-24 14:28:26.000000000 +0200 @@ -0,0 +1,47 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853006 +Backport of: + +From 529490e5d664a20d5c4223070dd7c03a0e02b6bd Mon Sep 17 00:00:00 2001 +From: Peter Maydell <peter.maydell@linaro.org> +Date: Fri, 4 Dec 2015 17:34:20 +0000 +Subject: [PATCH] osdep.h: Include glib-compat.h in osdep.h rather than + qemu-common.h + +Our use of glib is now pervasive across QEMU. Move the include of glib-compat.h +from qemu-common.h to osdep.h so that it is more widely accessible and doesn't +get forgotten by accident. (Failure to include it will result in build failure +on old versions of glib which is likely to be unnoticed by most developers.) + +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> +--- + include/qemu-common.h | 1 - + include/qemu/osdep.h | 2 ++ + 2 files changed, 2 insertions(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/include/qemu-common.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/include/qemu-common.h 2017-04-05 11:55:10.681843473 -0400 ++++ qemu-2.0.0+dfsg/include/qemu-common.h 2017-04-05 11:55:32.738126860 -0400 +@@ -40,7 +40,6 @@ + #include <sys/time.h> + #include <assert.h> + #include <signal.h> +-#include "glib-compat.h" + + #ifdef _WIN32 + #include "sysemu/os-win32.h" +Index: qemu-2.0.0+dfsg/include/qemu/osdep.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/include/qemu/osdep.h 2017-04-05 11:55:10.681843473 -0400 ++++ qemu-2.0.0+dfsg/include/qemu/osdep.h 2017-04-05 11:56:10.790615775 -0400 +@@ -18,6 +18,7 @@ + #endif + + #include <sys/time.h> ++#include "glib-compat.h" + + #if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10 + /* [u]int_fast*_t not in <sys/int_types.h> */ diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9603-cirrus-vnc-zap-bitblit-support-from-console-code.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9603-cirrus-vnc-zap-bitblit-support-from-console-code.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9603-cirrus-vnc-zap-bitblit-support-from-console-code.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9603-cirrus-vnc-zap-bitblit-support-from-console-code.patch 2018-06-29 12:54:05.000000000 +0200 @@ -0,0 +1,254 @@ +Origin: backported, https://git.qemu.org/?p=qemu.git;a=commit;h=50628d3479e4f9aa97e323506856e394fe7ad7a6 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> + +From 50628d3479e4f9aa97e323506856e394fe7ad7a6 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Tue, 14 Mar 2017 13:26: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. + +Oh, and one more reason: Turns out (after writing the patch) we have a +security bug in that code path ... + +Fixes: CVE-2016-9603 +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1489494419-14340-1-git-send-email-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 12 ++--- + include/ui/console.h | 7 --- + ui/console.c | 28 ----------- + ui/vnc.c | 100 ---------------------------------------- + 4 files changed, 3 insertions(+), 144 deletions(-) + +Index: qemu/hw/display/cirrus_vga.c +=================================================================== +--- qemu.orig/hw/display/cirrus_vga.c ++++ qemu/hw/display/cirrus_vga.c +@@ -753,11 +753,6 @@ static void cirrus_do_copy(CirrusVGAStat + } + } + +- /* 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 + +@@ -766,10 +761,9 @@ static void cirrus_do_copy(CirrusVGAStat + 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 +Index: qemu/ui/console.c +=================================================================== +--- qemu.orig/ui/console.c ++++ qemu/ui/console.c +@@ -1433,27 +1433,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; +@@ -1883,13 +1862,6 @@ void qemu_console_resize(QemuConsole *s, + 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; +Index: qemu/ui/vnc.c +=================================================================== +--- qemu.orig/ui/vnc.c ++++ qemu/ui/vnc.c +@@ -733,96 +733,6 @@ int vnc_send_framebuffer_update(VncState + 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) + { +@@ -2948,7 +2858,6 @@ static void vnc_listen_websocket_read(vo + 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, +Index: qemu/include/ui/console.h +=================================================================== +--- qemu.orig/include/ui/console.h ++++ qemu/include/ui/console.h +@@ -220,8 +220,6 @@ int dpy_set_ui_info(QemuConsole *con, Qe + 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); +@@ -305,8 +303,6 @@ void text_consoles_set_display(DisplaySt + 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 -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9776.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9776.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9776.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9776.patch 2018-07-24 19:51:25.000000000 +0200 @@ -0,0 +1,35 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 846797 + +From 77d54985b85a0cb760330ec2bd92505e0a2a97a9 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 29 Nov 2016 00:38:39 +0530 +Subject: [PATCH] net: mcf: check receive buffer size register value + +ColdFire Fast Ethernet Controller uses a receive buffer size +register(EMRBR) to hold maximum size of all receive buffers. +It is set by a user before any operation. If it was set to be +zero, ColdFire emulator would go into an infinite loop while +receiving data in mcf_fec_receive. Add check to avoid it. + +Reported-by: Wjjzhang <wjjzhang@tencent.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Signed-off-by: Jason Wang <jasowang@redhat.com> +--- + hw/net/mcf_fec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/net/mcf_fec.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/net/mcf_fec.c 2017-04-06 09:43:19.147684514 -0400 ++++ qemu-2.0.0+dfsg/hw/net/mcf_fec.c 2017-04-06 09:43:19.143684462 -0400 +@@ -344,7 +344,7 @@ + s->tx_descriptor = s->etdsr; + break; + case 0x188: +- s->emrbr = value & 0x7f0; ++ s->emrbr = value > 0 ? value & 0x7F0 : 0x7F0; + break; + default: + hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9907.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9907.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9907.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9907.patch 2018-07-24 19:55:04.000000000 +0200 @@ -0,0 +1,57 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847953 + +Backport of: + +From 07b026fd82d6cf11baf7d7c603c4f5f6070b35bf Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Mon, 7 Nov 2016 21:57:46 -0800 +Subject: [PATCH] usbredir: free vm_change_state_handler in usbredir destroy + dispatch +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +In usbredir destroy dispatch function, it doesn't free the vm change +state handler once registered in usbredir_realize function. This will +lead a memory leak issue. This patch avoid this. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> +Message-id: 58216976.d0236b0a.77b99.bcd6@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/usb/redirect.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/usb/redirect.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/redirect.c 2017-04-06 09:47:06.502540944 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/redirect.c 2017-04-06 09:47:34.630893762 -0400 +@@ -122,6 +122,7 @@ + struct usbredirfilter_rule *filter_rules; + int filter_rules_count; + int compatible_speedmask; ++ VMChangeStateEntry *vmstate; + }; + + static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); +@@ -1313,7 +1314,8 @@ + qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read, + usbredir_chardev_read, usbredir_chardev_event, dev); + +- qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); ++ dev->vmstate = ++ qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); + add_boot_device_path(dev->bootindex, &udev->qdev, NULL); + return 0; + } +@@ -1351,6 +1353,7 @@ + } + + free(dev->filter_rules); ++ qemu_del_vm_change_state_handler(dev->vmstate); + } + + static int usbredir_check_filter(USBRedirDevice *dev) diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9911.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9911.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9911.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9911.patch 2018-07-25 12:36:38.000000000 +0200 @@ -0,0 +1,32 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847951 + +From 791f97758e223de3290592d169f8e6339c281714 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Tue, 8 Nov 2016 04:11:10 -0800 +Subject: [PATCH] usb: ehci: fix memory leak in ehci_init_transfer + +In ehci_init_transfer function, if the 'cpage' is bigger than 4, +it doesn't free the 'p->sgl' once allocated previously thus leading +a memory leak issue. This patch avoid this. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-id: 5821c0f4.091c6b0a.e0c92.e811@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/usb/hcd-ehci.c | 1 + + 1 file changed, 1 insertion(+) + +Index: qemu-2.0.0+dfsg/hw/usb/hcd-ehci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/hcd-ehci.c 2017-04-06 10:02:39.414228874 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/hcd-ehci.c 2017-04-06 10:02:39.410228824 -0400 +@@ -1270,6 +1270,7 @@ + while (bytes > 0) { + if (cpage > 4) { + fprintf(stderr, "cpage out of range (%d)\n", cpage); ++ qemu_sglist_destroy(&p->sgl); + return -1; + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9914-1.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9914-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9914-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9914-1.patch 2018-07-24 16:16:32.000000000 +0200 @@ -0,0 +1,30 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847496 + +Index: qemu/fsdev/file-op-9p.h +=================================================================== +--- qemu.orig/fsdev/file-op-9p.h ++++ qemu/fsdev/file-op-9p.h +@@ -102,6 +102,7 @@ struct FileOperations + { + int (*parse_opts)(QemuOpts *, struct FsDriverEntry *); + int (*init)(struct FsContext *); ++ void (*cleanup)(struct FsContext *); + int (*lstat)(FsContext *, V9fsPath *, struct stat *); + ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t); + int (*chmod)(FsContext *, V9fsPath *, FsCred *); +Index: qemu/hw/9pfs/virtio-9p-device.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-device.c ++++ qemu/hw/9pfs/virtio-9p-device.c +@@ -131,6 +131,9 @@ static void virtio_9p_device_realize(Dev + + return; + out: ++ if (s->ops->cleanup && s->ctx.private) { ++ s->ops->cleanup(&s->ctx); ++ } + g_free(s->ctx.fs_root); + g_free(s->tag); + virtio_cleanup(vdev); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9914-2.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9914-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9914-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9914-2.patch 2018-07-24 16:16:41.000000000 +0200 @@ -0,0 +1,35 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847496 + +Backport of: + +From f2b58c43758efc61e2a49b899f5e58848489d0dc Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Tue, 3 Jan 2017 17:28:44 +0100 +Subject: [PATCH] 9pfs: fix crash when fsdev is missing + +If the user passes -device virtio-9p without the corresponding -fsdev, QEMU +dereferences a NULL pointer and crashes. + +This is a 2.8 regression introduced by commit 702dbcc274e2c. + +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Li Qiang <liq3ea@gmail.com> +--- + hw/9pfs/9p.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu/hw/9pfs/virtio-9p-device.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-device.c ++++ qemu/hw/9pfs/virtio-9p-device.c +@@ -131,7 +131,7 @@ static void virtio_9p_device_realize(Dev + + return; + out: +- if (s->ops->cleanup && s->ctx.private) { ++ if (s->ops && s->ops->cleanup && s->ctx.private) { + s->ops->cleanup(&s->ctx); + } + g_free(s->ctx.fs_root); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9915.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9915.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9915.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9915.patch 2018-07-24 17:43:36.000000000 +0200 @@ -0,0 +1,49 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847496 +Backport of: + +From 971f406b77a6eb84e0ad27dcc416b663765aee30 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liq3ea@gmail.com> +Date: Wed, 23 Nov 2016 13:53:34 +0100 +Subject: [PATCH] 9pfs: add cleanup operation for handle backend driver + +In the init operation of handle backend dirver, it allocates a +handle_data struct and opens a mount file. We should free these +resources when the 9pfs device is unrealized. This is what this +patch does. + +Signed-off-by: Li Qiang <liq3ea@gmail.com> +Reviewed-by: Greg Kurz <groug@kaod.org> +Signed-off-by: Greg Kurz <groug@kaod.org> +--- + hw/9pfs/9p-handle.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: qemu-2.5+dfsg/hw/9pfs/virtio-9p-handle.c +=================================================================== +--- qemu-2.5+dfsg.orig/hw/9pfs/virtio-9p-handle.c 2017-04-04 15:09:45.489743312 -0400 ++++ qemu-2.5+dfsg/hw/9pfs/virtio-9p-handle.c 2017-04-04 15:09:45.485743261 -0400 +@@ -650,6 +650,14 @@ + return ret; + } + ++static void handle_cleanup(FsContext *ctx) ++{ ++ struct handle_data *data = ctx->private; ++ ++ close(data->mountfd); ++ g_free(data); ++} ++ + static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) + { + const char *sec_model = qemu_opt_get(opts, "security_model"); +@@ -672,6 +680,7 @@ + FileOperations handle_ops = { + .parse_opts = handle_parse_opts, + .init = handle_init, ++ .cleanup = handle_cleanup, + .lstat = handle_lstat, + .readlink = handle_readlink, + .close = handle_close, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9916.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9916.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9916.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9916.patch 2018-07-24 17:56:06.000000000 +0200 @@ -0,0 +1,49 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847496 +Backport of: + +From 898ae90a44551d25b8e956fd87372d303c82fe68 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liq3ea@gmail.com> +Date: Wed, 23 Nov 2016 13:53:34 +0100 +Subject: [PATCH] 9pfs: add cleanup operation for proxy backend driver + +In the init operation of proxy backend dirver, it allocates a +V9fsProxy struct and some other resources. We should free these +resources when the 9pfs device is unrealized. This is what this +patch does. + +Signed-off-by: Li Qiang <liq3ea@gmail.com> +Reviewed-by: Greg Kurz <groug@kaod.org> +Signed-off-by: Greg Kurz <groug@kaod.org> +--- + hw/9pfs/9p-proxy.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-proxy.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p-proxy.c 2017-04-05 11:58:58.092765342 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p-proxy.c 2017-04-05 11:58:58.088765291 -0400 +@@ -1175,9 +1175,22 @@ + return 0; + } + ++static void proxy_cleanup(FsContext *ctx) ++{ ++ V9fsProxy *proxy = ctx->private; ++ ++ g_free(proxy->out_iovec.iov_base); ++ g_free(proxy->in_iovec.iov_base); ++ if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) { ++ close(proxy->sockfd); ++ } ++ g_free(proxy); ++} ++ + FileOperations proxy_ops = { + .parse_opts = proxy_parse_opts, + .init = proxy_init, ++ .cleanup = proxy_cleanup, + .lstat = proxy_lstat, + .readlink = proxy_readlink, + .close = proxy_close, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2016-9921-9922.patch qemu-2.1+dfsg/debian/patches/CVE-2016-9921-9922.patch --- qemu-2.1+dfsg/debian/patches/CVE-2016-9921-9922.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2016-9921-9922.patch 2018-07-25 00:10:11.000000000 +0200 @@ -0,0 +1,77 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 847960 + +From 4299b90e9ba9ce5ca9024572804ba751aa1a7e70 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 18 Oct 2016 13:15:17 +0530 +Subject: [PATCH] display: cirrus: check vga bits per pixel(bpp) value + +In Cirrus CLGD 54xx VGA Emulator, if cirrus graphics mode is VGA, +'cirrus_get_bpp' returns zero(0), which could lead to a divide +by zero error in while copying pixel data. The same could occur +via blit pitch values. Add check to avoid it. + +Reported-by: Huawei PSIRT <psirt@huawei.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 1476776717-24807-1-git-send-email-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/display/cirrus_vga.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-04-06 09:49:10.260092350 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-04-06 09:49:10.256092300 -0400 +@@ -267,6 +267,9 @@ + static bool blit_region_is_unsafe(struct CirrusVGAState *s, + int32_t pitch, int32_t addr) + { ++ if (!pitch) { ++ return true; ++ } + if (pitch < 0) { + int64_t min = addr + + ((int64_t)s->cirrus_blt_height-1) * pitch; +@@ -710,7 +713,7 @@ + s->cirrus_addr_mask)); + } + +-static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) ++static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) + { + int sx = 0, sy = 0; + int dx = 0, dy = 0; +@@ -724,6 +727,9 @@ + int width, height; + + depth = s->vga.get_bpp(&s->vga) / 8; ++ if (!depth) { ++ return 0; ++ } + s->vga.get_resolution(&s->vga, &width, &height); + + /* extra x, y */ +@@ -772,6 +778,8 @@ + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); ++ ++ return 1; + } + + static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) +@@ -779,11 +787,9 @@ + if (blit_is_unsafe(s)) + return 0; + +- cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, ++ return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, + s->cirrus_blt_srcaddr - s->vga.start_addr, + s->cirrus_blt_width, s->cirrus_blt_height); +- +- return 1; + } + + /*************************************** diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-10664-Ignore-SIGPIPE.patch qemu-2.1+dfsg/debian/patches/CVE-2017-10664-Ignore-SIGPIPE.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-10664-Ignore-SIGPIPE.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-10664-Ignore-SIGPIPE.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,45 @@ +Origin: debian, 1.1.2+dfsg-6+deb7u23 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 866674 + +From: Max Reitz <mreitz@redhat.com> +Date: Sun, 11 Jun 2017 14:37:14 +0200 +Subject: CVE-2017-10664: Ignore SIGPIPE + +qemu proper has done so for 13 years +(8a7ddc38a60648257dc0645ab4a05b33d6040063), qemu-img and qemu-io have +done so for four years (526eda14a68d5b3596be715505289b541288ef2a). +Ignoring this signal is especially important in qemu-nbd because +otherwise a client can easily take down the qemu-nbd server by dropping +the connection when the server wants to send something, for example: + +$ qemu-nbd -x foo -f raw -t null-co:// & +[1] 12726 +$ qemu-io -c quit nbd://localhost/bar +can't open device nbd://localhost/bar: No export with name 'bar' available +[1] + 12726 broken pipe qemu-nbd -x foo -f raw -t null-co:// + +In this case, the client sends an NBD_OPT_ABORT and closes the +connection (because it is not required to wait for a reply), but the +server replies with an NBD_REP_ACK (because it is required to reply). + +This upstream commit 041e32b8d9d076980b4e35317c0339e57ab888f1 +--- + qemu-nbd.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Index: qemu/qemu-nbd.c +=================================================================== +--- qemu.orig/qemu-nbd.c ++++ qemu/qemu-nbd.c +@@ -442,6 +442,10 @@ int main(int argc, char **argv) + sigaction(SIGTERM, &sa_sigterm, NULL); + qemu_init_exec_dir(argv[0]); + ++#ifdef CONFIG_POSIX ++ signal(SIGPIPE, SIG_IGN); ++#endif ++ + while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { + switch (ch) { + case 's': diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-10806.patch qemu-2.1+dfsg/debian/patches/CVE-2017-10806.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-10806.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-10806.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,51 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 867751 + +From bd4a683505b27adc1ac809f71e918e58573d851d Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Tue, 9 May 2017 13:01:28 +0200 +Subject: [PATCH] usb-redir: fix stack overflow in usbredir_log_data +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Don't reinvent a broken wheel, just use the hexdump function we have. + +Impact: low, broken code doesn't run unless you have debug logging +enabled. + +Reported-by: æ??强 <liqiang6-s@360.cn> +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 20170509110128.27261-1-kraxel@redhat.com +--- + hw/usb/redirect.c | 13 +------------ + 1 file changed, 1 insertion(+), 12 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/usb/redirect.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/redirect.c 2017-08-22 12:34:43.028840902 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/redirect.c 2017-08-22 12:34:43.024840901 -0400 +@@ -216,21 +216,10 @@ static void usbredir_log(void *priv, int + static void usbredir_log_data(USBRedirDevice *dev, const char *desc, + const uint8_t *data, int len) + { +- int i, j, n; +- + if (dev->debug < usbredirparser_debug_data) { + return; + } +- +- for (i = 0; i < len; i += j) { +- char buf[128]; +- +- n = sprintf(buf, "%s", desc); +- for (j = 0; j < 8 && i + j < len; j++) { +- n += sprintf(buf + n, " %02X", data[i + j]); +- } +- error_report("%s", buf); +- } ++ qemu_hexdump((char *)data, stderr, desc, len); + } + + /* diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-11434-slirp-check-len-against-dhcp-options-array.patch qemu-2.1+dfsg/debian/patches/CVE-2017-11434-slirp-check-len-against-dhcp-options-array.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-11434-slirp-check-len-against-dhcp-options-array.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-11434-slirp-check-len-against-dhcp-options-array.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,36 @@ +Origin: debian, 1.1.2+dfsg-6+deb7u23 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 869171 + +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Mon, 17 Jul 2017 17:33:26 +0530 +Subject: CVE-2017-11434: slirp: check len against dhcp options array end + +While parsing dhcp options string in 'dhcp_decode', if an options' +length 'len' appeared towards the end of 'bp_vend' array, ensuing +read could lead to an OOB memory access issue. Add check to avoid it. + +This is CVE-2017-11434. + +Reported-by: Reno Robert <renorobert@gmail.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> +(cherry picked from commit 413d463f43fbc4dd3a601e80a5724aa384a265a0) +--- + slirp/bootp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/slirp/bootp.c b/slirp/bootp.c +index 64eac7d..0744135 100644 +--- a/slirp/bootp.c ++++ b/slirp/bootp.c +@@ -116,6 +116,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, + if (p >= p_end) + break; + len = *p++; ++ if (p + len > p_end) { ++ break; ++ } + DPRINTF("dhcp: tag=%d len=%d\n", tag, len); + + switch(tag) { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-14167-multiboot-validate-multiboot-header-addres.patch qemu-2.1+dfsg/debian/patches/CVE-2017-14167-multiboot-validate-multiboot-header-addres.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-14167-multiboot-validate-multiboot-header-addres.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-14167-multiboot-validate-multiboot-header-addres.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,64 @@ +Origin: debian, qemu_1.1.2+dfsg-6+deb7u25 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: https://bugs.debian.org/874606 + +From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org> +Date: Wed, 4 Oct 2017 08:24:40 +0200 +Subject: CVE-2017-14167: multiboot: validate multiboot header address values + +While loading kernel via multiboot-v1 image, (flags & 0x00010000) +indicates that multiboot header contains valid addresses to load +the kernel image. These addresses are used to compute kernel +size and kernel text offset in the OS image. Validate these +address values to avoid an OOB access issue. + +Author: Prasad J Pandit <pjp@fedoraproject.org> +Reported-by: Thomas Garnier <thgarnie@google.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-Id: <20170907063256.7418-1-ppandit@redhat.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> + +This is upstream commit ed4f86e8b6eff8e600c69adee68c7cd34dd2cccb +--- + hw/multiboot.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index b1e04c5..b9d32a7 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -200,15 +200,34 @@ int load_multiboot(void *fw_cfg, + uint32_t mh_header_addr = ldl_p(header+i+12); + uint32_t mh_load_end_addr = ldl_p(header+i+20); + uint32_t mh_bss_end_addr = ldl_p(header+i+24); ++ + mh_load_addr = ldl_p(header+i+16); ++ if (mh_header_addr < mh_load_addr) { ++ fprintf(stderr, "invalid mh_load_addr address\n"); ++ exit(1); ++ } ++ + uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr); + uint32_t mb_load_size = 0; + mh_entry_addr = ldl_p(header+i+28); + + if (mh_load_end_addr) { ++ if (mh_bss_end_addr < mh_load_addr) { ++ fprintf(stderr, "invalid mh_bss_end_addr address\n"); ++ exit(1); ++ } + mb_kernel_size = mh_bss_end_addr - mh_load_addr; ++ ++ if (mh_load_end_addr < mh_load_addr) { ++ fprintf(stderr, "invalid mh_load_end_addr address\n"); ++ exit(1); ++ } + mb_load_size = mh_load_end_addr - mh_load_addr; + } else { ++ if (kernel_file_size < mb_kernel_text_offset) { ++ fprintf(stderr, "invalid kernel_file_size\n"); ++ exit(1); ++ } + mb_kernel_size = kernel_file_size - mb_kernel_text_offset; + mb_load_size = mb_kernel_size; + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-15038-9pfs-use-g_malloc0-to-allocate-space-for-x.patch qemu-2.1+dfsg/debian/patches/CVE-2017-15038-9pfs-use-g_malloc0-to-allocate-space-for-x.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-15038-9pfs-use-g_malloc0-to-allocate-space-for-x.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-15038-9pfs-use-g_malloc0-to-allocate-space-for-x.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,43 @@ +Origin: debian, qemu_1.1.2+dfsg-6+deb7u25 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: https://bugs.debian.org/877890 + +From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org> +Date: Fri, 6 Oct 2017 16:36:27 +0200 +Subject: CVE-2017-15038: 9pfs: use g_malloc0 to allocate space for xattr + +9p back-end first queries the size of an extended attribute, +allocates space for it via g_malloc() and then retrieves its +value into allocated buffer. Race between querying attribute +size and retrieving its could lead to memory bytes disclosure. +Use g_malloc0() to avoid it. + +This is upstream commit cf9c0df3fb3588768034b16f1f836a0ec87da096 + +Author: Prasad J Pandit +--- + hw/9pfs/virtio-9p.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c +index e270b84..b993139 100644 +--- a/hw/9pfs/virtio-9p.c ++++ b/hw/9pfs/virtio-9p.c +@@ -3175,7 +3175,7 @@ static void v9fs_xattrwalk(void *opaque) + xattr_fidp->fid_type = P9_FID_XATTR; + xattr_fidp->fs.xattr.copied_len = -1; + if (size) { +- xattr_fidp->fs.xattr.value = g_malloc(size); ++ xattr_fidp->fs.xattr.value = g_malloc0(size); + err = v9fs_co_llistxattr(pdu, &xattr_fidp->path, + xattr_fidp->fs.xattr.value, + xattr_fidp->fs.xattr.len); +@@ -3208,7 +3208,7 @@ static void v9fs_xattrwalk(void *opaque) + xattr_fidp->fid_type = P9_FID_XATTR; + xattr_fidp->fs.xattr.copied_len = -1; + if (size) { +- xattr_fidp->fs.xattr.value = g_malloc(size); ++ xattr_fidp->fs.xattr.value = g_malloc0(size); + err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path, + &name, xattr_fidp->fs.xattr.value, + xattr_fidp->fs.xattr.len); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-15289.patch qemu-2.1+dfsg/debian/patches/CVE-2017-15289.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-15289.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-15289.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,59 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.43 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: https://bugs.debian.org/880832 + +From eb38e1bc3740725ca29a535351de94107ec58d51 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Wed, 11 Oct 2017 10:43:14 +0200 +Subject: [PATCH] cirrus: fix oob access in mode4and5 write functions + +Move dst calculation into the loop, so we apply the mask on each +interation and will not overflow vga memory. + +Cc: Prasad J Pandit <pjp@fedoraproject.org> +Reported-by: Niu Guoxiang <niuguoxiang@huawei.com> +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 20171011084314.21752-1-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2018-02-15 13:20:27.734984874 -0500 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2018-02-15 13:20:27.730984870 -0500 +@@ -2018,15 +2018,14 @@ static void cirrus_mem_writeb_mode4and5_ + unsigned val = mem_value; + uint8_t *dst; + +- dst = s->vga.vram_ptr + (offset &= s->cirrus_addr_mask); + for (x = 0; x < 8; x++) { ++ dst = s->vga.vram_ptr + ((offset + x) & s->cirrus_addr_mask); + if (val & 0x80) { + *dst = s->cirrus_shadow_gr1; + } else if (mode == 5) { + *dst = s->cirrus_shadow_gr0; + } + val <<= 1; +- dst++; + } + memory_region_set_dirty(&s->vga.vram, offset, 8); + } +@@ -2040,8 +2039,8 @@ static void cirrus_mem_writeb_mode4and5_ + unsigned val = mem_value; + uint8_t *dst; + +- dst = s->vga.vram_ptr + (offset &= s->cirrus_addr_mask); + for (x = 0; x < 8; x++) { ++ dst = s->vga.vram_ptr + ((offset + 2 * x) & s->cirrus_addr_mask & ~1); + if (val & 0x80) { + *dst = s->cirrus_shadow_gr1; + *(dst + 1) = s->vga.gr[0x11]; +@@ -2050,7 +2049,6 @@ static void cirrus_mem_writeb_mode4and5_ + *(dst + 1) = s->vga.gr[0x10]; + } + val <<= 1; +- dst += 2; + } + memory_region_set_dirty(&s->vga.vram, offset, 16); + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-16845.patch qemu-2.1+dfsg/debian/patches/CVE-2017-16845.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-16845.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-16845.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,63 @@ +Origin: debian, 24c3ec9b6367fe3263a0ddd3e7c04a62a38a1970 +Reviewed-By: Santiago R.R. <santiagorr@riseup.net> + +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Thu, 16 Nov 2017 13:21:55 +0530 +Subject: ps2: check PS2Queue pointers in post_load routine +Commit-Id: 802cbcb73002b92e6ddc8464d39b668a71b78d74 +Bug-Debian: http://bugs.debian.org/882136 + +During Qemu guest migration, a destination process invokes ps2 +post_load function. In that, if 'rptr' and 'count' values were +invalid, it could lead to OOB access or infinite loop issue. +Add check to avoid it. + +Reported-by: Cyrille Chatras <cyrille.chatras@orange.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 20171116075155.22378-1-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/input/ps2.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/hw/input/ps2.c b/hw/input/ps2.c +index f388a23c8e..de171a28dd 100644 +--- a/hw/input/ps2.c ++++ b/hw/input/ps2.c +@@ -1225,24 +1225,21 @@ static void ps2_common_reset(PS2State *s) + static void ps2_common_post_load(PS2State *s) + { + PS2Queue *q = &s->queue; +- int size; +- int i; +- int tmp_data[PS2_QUEUE_SIZE]; ++ uint8_t i, size; ++ uint8_t tmp_data[PS2_QUEUE_SIZE]; + + /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ +- size = q->count > PS2_QUEUE_SIZE ? 0 : q->count; ++ size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count; + + /* move the queue elements to the start of data array */ +- if (size > 0) { +- for (i = 0; i < size; i++) { +- /* move the queue elements to the temporary buffer */ +- tmp_data[i] = q->data[q->rptr]; +- if (++q->rptr == 256) { +- q->rptr = 0; +- } ++ for (i = 0; i < size; i++) { ++ if (q->rptr < 0 || q->rptr >= sizeof(q->data)) { ++ q->rptr = 0; + } +- memcpy(q->data, tmp_data, size); ++ tmp_data[i] = q->data[q->rptr++]; + } ++ memcpy(q->data, tmp_data, size); ++ + /* reset rptr/wptr/count */ + q->rptr = 0; + q->wptr = size; +-- +2.11.0 + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-18043.patch qemu-2.1+dfsg/debian/patches/CVE-2017-18043.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-18043.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-18043.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,60 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.22 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> + +Backport of: + +From 2098b073f398cd628c09c5a78537a6854e85830d Mon Sep 17 00:00:00 2001 +From: Eric Blake <eblake@redhat.com> +Date: Thu, 14 Sep 2017 08:49:23 -0500 +Subject: [PATCH] osdep: Fix ROUND_UP(64-bit, 32-bit) +Commit-Id: 2098b073f398cd628c09c5a78537a6854e85830d +Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2017-18043 + +When using bit-wise operations that exploit the power-of-two +nature of the second argument of ROUND_UP(), we still need to +ensure that the mask is as wide as the first argument (done +by using a ternary to force proper arithmetic promotion). +Unpatched, ROUND_UP(2ULL*1024*1024*1024*1024, 512U) produces 0, +instead of the intended 2TiB, because negation of an unsigned +32-bit quantity followed by widening to 64-bits does not +sign-extend the mask. + +Broken since its introduction in commit 292c8e50 (v1.5.0). +Callers that passed the same width type to both macro parameters, +or that had other code to ensure the first parameter's maximum +runtime value did not exceed the second parameter's width, are +unaffected, but I did not audit to see which (if any) existing +clients of the macro could trigger incorrect behavior (I found +the bug while adding a new use of the macro). + +While preparing the patch, checkpatch complained about poor +spacing, so I also fixed that here and in the nearby DIV_ROUND_UP. + +CC: qemu-trivial@nongnu.org +CC: qemu-stable@nongnu.org +Signed-off-by: Eric Blake <eblake@redhat.com> +Reviewed-by: Laszlo Ersek <lersek@redhat.com> +Reviewed-by: Richard Henderson <richard.henderson@linaro.org> +Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> +--- + include/qemu/osdep.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Index: qemu-2.0.0+dfsg/include/qemu/osdep.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/include/qemu/osdep.h 2018-02-15 13:32:59.763152571 -0500 ++++ qemu-2.0.0+dfsg/include/qemu/osdep.h 2018-02-15 13:32:59.759152570 -0500 +@@ -70,11 +70,11 @@ typedef signed int int_fast + #endif + + #ifndef ROUND_UP +-#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d)) ++#define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d))) + #endif + + #ifndef DIV_ROUND_UP +-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) ++#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + #endif + + #ifndef ARRAY_SIZE diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-2615.patch qemu-2.1+dfsg/debian/patches/CVE-2017-2615.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-2615.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-2615.patch 2018-07-25 12:47:32.000000000 +0200 @@ -0,0 +1,51 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 854731 + +Backport of: + +From 62d4c6bd5263bb8413a06c80144fc678df6dfb64 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Wed, 1 Feb 2017 09:35:01 +0100 +Subject: [PATCH] cirrus: fix oob access issue (CVE-2017-2615) + +When doing bitblt copy in backward mode, we should minus the +blt width first just like the adding in the forward mode. This +can avoid the oob access of the front of vga's vram. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> + +{ kraxel: with backward blits (negative pitch) addr is the topmost + address, so check it as-is against vram size ] + +Cc: qemu-stable@nongnu.org +Cc: P J P <ppandit@redhat.com> +Cc: Laszlo Ersek <lersek@redhat.com> +Cc: Paolo Bonzini <pbonzini@redhat.com> +Cc: Wolfgang Bumiller <w.bumiller@proxmox.com> +Fixes: d3532a0db02296e687711b8cdc7791924efccea0 (CVE-2014-8106) +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1485938101-26602-1-git-send-email-kraxel@redhat.com +Reviewed-by: Laszlo Ersek <lersek@redhat.com> +--- + hw/display/cirrus_vga.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-04-06 10:02:47.798333777 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-04-06 10:02:47.794333726 -0400 +@@ -272,10 +272,9 @@ + } + if (pitch < 0) { + int64_t min = addr +- + ((int64_t)s->cirrus_blt_height-1) * pitch; +- int32_t max = addr +- + s->cirrus_blt_width; +- if (min < 0 || max >= s->vga.vram_size) { ++ + ((int64_t)s->cirrus_blt_height - 1) * pitch ++ - s->cirrus_blt_width; ++ if (min < -1 || addr >= s->vga.vram_size) { + return true; + } + } else { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-2620-cirrus-add-blit_is_unsafe-call-to-cirrus_bi.patch qemu-2.1+dfsg/debian/patches/CVE-2017-2620-cirrus-add-blit_is_unsafe-call-to-cirrus_bi.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-2620-cirrus-add-blit_is_unsafe-call-to-cirrus_bi.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-2620-cirrus-add-blit_is_unsafe-call-to-cirrus_bi.patch 2018-07-25 13:24:47.000000000 +0200 @@ -0,0 +1,47 @@ +Origin: backported, from wheezy release 1.1.2+dfsg-6+deb7u20 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855791 + +From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org> +Date: Thu, 23 Feb 2017 16:58:11 +0100 +Subject: CVE-2017-2620: cirrus: add blit_is_unsafe call to cirrus_bitblt + +CIRRUS_BLTMODE_MEMSYSSRC blits do NOT check blit destination +and blit width, at all. Oops. Fix it. + +Security impact: high. + +The missing blit destination check allows to write to host memory. +Basically same as CVE-2014-8106 for the other blit variants. + +Upstream-URL: https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg05244.html +--- + hw/cirrus_vga.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index 6d64c0f..52d9597 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -862,6 +862,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s) + { + int w; + ++ if (blit_is_unsafe(s, true)) { ++ return 0; ++ } ++ + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; +@@ -887,6 +891,10 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s) + } + s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; + } ++ ++ /* the blit_is_unsafe call above should catch this */ ++ assert(s->cirrus_blt_srcpitch <= CIRRUS_BLTBUFSIZE); ++ + s->cirrus_srcptr = s->cirrus_bltbuf; + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + cirrus_update_memory_access(s); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-2620-pre.patch qemu-2.1+dfsg/debian/patches/CVE-2017-2620-pre.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-2620-pre.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-2620-pre.patch 2018-07-25 13:24:17.000000000 +0200 @@ -0,0 +1,74 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855791 + + +From 913a87885f589d263e682c2eb6637c6e14538061 Mon Sep 17 00:00:00 2001 +From: Bruce Rogers <brogers@suse.com> +Date: Mon, 9 Jan 2017 13:35:20 -0700 +Subject: [PATCH] display: cirrus: ignore source pitch value as needed in + blit_is_unsafe + +Commit 4299b90 added a check which is too broad, given that the source +pitch value is not required to be initialized for solid fill operations. +This patch refines the blit_is_unsafe() check to ignore source pitch in +that case. After applying the above commit as a security patch, we +noticed the SLES 11 SP4 guest gui failed to initialize properly. + +Signed-off-by: Bruce Rogers <brogers@suse.com> +Message-id: 20170109203520.5619-1-brogers@suse.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/display/cirrus_vga.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-04-06 09:53:43.551510499 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-04-06 09:53:43.547510449 -0400 +@@ -289,7 +289,7 @@ + return false; + } + +-static bool blit_is_unsafe(struct CirrusVGAState *s) ++static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only) + { + /* should be the case, see cirrus_bitblt_start */ + assert(s->cirrus_blt_width > 0); +@@ -303,6 +303,9 @@ + s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) { + return true; + } ++ if (dst_only) { ++ return false; ++ } + if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch, + s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) { + return true; +@@ -668,7 +671,7 @@ + + dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); + +- if (blit_is_unsafe(s)) ++ if (blit_is_unsafe(s, false)) + return 0; + + (*s->cirrus_rop) (s, dst, src, +@@ -686,7 +689,7 @@ + { + cirrus_fill_t rop_func; + +- if (blit_is_unsafe(s)) { ++ if (blit_is_unsafe(s, true)) { + return 0; + } + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; +@@ -784,7 +787,7 @@ + + static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) + { +- if (blit_is_unsafe(s)) ++ if (blit_is_unsafe(s, false)) + return 0; + + return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5525.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5525.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5525.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5525.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,43 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 852021 + + +Backport of: + +From 12351a91da97b414eec8cdb09f1d9f41e535a401 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Wed, 14 Dec 2016 18:30:21 -0800 +Subject: [PATCH] audio: ac97: add exit function +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Currently the ac97 device emulation doesn't have a exit function, +hot unplug this device will leak some memory. Add a exit function to +avoid this. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> +Message-id: 58520052.4825ed0a.27a71.6cae@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/audio/ac97.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/audio/ac97.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/audio/ac97.c 2017-04-06 09:54:00.803725942 -0400 ++++ qemu-2.0.0+dfsg/hw/audio/ac97.c 2017-04-06 09:54:42.584247535 -0400 +@@ -1396,6 +1396,11 @@ + + memory_region_destroy (&s->io_nam); + memory_region_destroy (&s->io_nabm); ++ ++ AUD_close_in(&s->card, s->voice_pi); ++ AUD_close_out(&s->card, s->voice_po); ++ AUD_close_in(&s->card, s->voice_mc); ++ AUD_remove_card(&s->card); + } + + static int ac97_init (PCIBus *bus) diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5526.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5526.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5526.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5526.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,45 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 851910 + +Backport of: + +From 069eb7b2b8fc47c7cb52e5a4af23ea98d939e3da Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Wed, 14 Dec 2016 18:32:22 -0800 +Subject: [PATCH] audio: es1370: add exit function +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Currently the es1370 device emulation doesn't have a exit function, +hot unplug this device will leak some memory. Add a exit function to +avoid this. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> +Message-id: 585200c9.a968ca0a.1ab80.4c98@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/audio/es1370.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/audio/es1370.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/audio/es1370.c 2017-04-06 09:55:33.204882790 -0400 ++++ qemu-2.0.0+dfsg/hw/audio/es1370.c 2017-04-06 09:56:00.485225815 -0400 +@@ -1047,6 +1047,14 @@ + static void es1370_exitfn (PCIDevice *dev) + { + ES1370State *s = DO_UPCAST (ES1370State, dev, dev); ++ int i; ++ ++ for (i = 0; i < 2; ++i) { ++ AUD_close_out(&s->card, s->dac_voice[i]); ++ } ++ ++ AUD_close_in(&s->card, s->adc_voice); ++ AUD_remove_card(&s->card); + + memory_region_destroy (&s->io); + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5579.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5579.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5579.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5579.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,43 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853002 + +Backport of: + +From 8409dc884a201bf74b30a9d232b6bbdd00cb7e2b Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Wed, 4 Jan 2017 00:43:16 -0800 +Subject: [PATCH] serial: fix memory leak in serial exit + +The serial_exit_core function doesn't free some resources. +This can lead memory leak when hotplug and unplug. This +patch avoid this. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-Id: <586cb5ab.f31d9d0a.38ac3.acf2@mx.google.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/char/serial.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/char/serial.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/char/serial.c 2017-04-06 09:58:00.014727376 -0400 ++++ qemu-2.0.0+dfsg/hw/char/serial.c 2017-04-06 09:58:00.010727325 -0400 +@@ -667,6 +667,16 @@ + void serial_exit_core(SerialState *s) + { + qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); ++ ++ timer_del(s->modem_status_poll); ++ timer_free(s->modem_status_poll); ++ ++ timer_del(s->fifo_timeout_timer); ++ timer_free(s->fifo_timeout_timer); ++ ++ fifo8_destroy(&s->recv_fifo); ++ fifo8_destroy(&s->xmit_fifo); ++ + qemu_unregister_reset(serial_reset, s); + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5667.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5667.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5667.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5667.patch 2018-07-25 13:34:39.000000000 +0200 @@ -0,0 +1,38 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853996 + +From 42922105beb14c2fc58185ea022b9f72fb5465e9 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 7 Feb 2017 18:29:59 +0000 +Subject: [PATCH] sd: sdhci: check data length during dma_memory_read + +While doing multi block SDMA transfer in routine +'sdhci_sdma_transfer_multi_blocks', the 's->fifo_buffer' starting +index 'begin' and data length 's->data_count' could end up to be same. +This could lead to an OOB access issue. Correct transfer data length +to avoid it. + +Cc: qemu-stable@nongnu.org +Reported-by: Jiang Xin <jiangxin1@huawei.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Reviewed-by: Peter Maydell <peter.maydell@linaro.org> +Message-id: 20170130064736.9236-1-ppandit@redhat.com +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +--- + hw/sd/sdhci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/sd/sdhci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/sd/sdhci.c 2017-04-06 09:58:14.098904157 -0400 ++++ qemu-2.0.0+dfsg/hw/sd/sdhci.c 2017-04-06 09:58:14.094904106 -0400 +@@ -518,7 +518,7 @@ + boundary_count -= block_size - begin; + } + dma_memory_read(&address_space_memory, s->sdmasysad, +- &s->fifo_buffer[begin], s->data_count); ++ &s->fifo_buffer[begin], s->data_count - begin); + s->sdmasysad += s->data_count - begin; + if (s->data_count == block_size) { + for (n = 0; n < block_size; n++) { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5715-1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5715-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5715-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5715-1.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,48 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.38 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 886532 + +Backport of: + +From 807e9869b8c4119b81df902625af818519e01759 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost <ehabkost@redhat.com> +Date: Tue, 9 Jan 2018 13:45:13 -0200 +Subject: [PATCH] i386: Change X86CPUDefinition::model_id to const char* + +It is valid to have a 48-character model ID on CPUID, however the +definition of X86CPUDefinition::model_id is char[48], which can +make the compiler drop the null terminator from the string. + +If a CPU model happens to have 48 bytes on model_id, "-cpu help" +will print garbage and the object_property_set_str() call at +x86_cpu_load_def() will read data outside the model_id array. + +We could increase the array size to 49, but this would mean the +compiler would not issue a warning if a 49-char string is used by +mistake for model_id. + +To make things simpler, simply change model_id to be const char*, +and validate the string length using an assert() on +x86_register_cpudef_type(). + +Reported-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +Message-Id: <20180109154519.25634-2-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +--- + target/i386/cpu.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/target-i386/cpu.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/target-i386/cpu.c 2018-01-23 09:07:10.367212408 -0500 ++++ qemu-2.0.0+dfsg/target-i386/cpu.c 2018-01-23 09:07:32.771147171 -0500 +@@ -529,7 +529,7 @@ struct X86CPUDefinition { + int model; + int stepping; + FeatureWordArray features; +- char model_id[48]; ++ char model_id[49]; + bool cache_info_passthrough; + }; + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5715-2.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5715-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5715-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5715-2.patch 2018-07-25 19:13:33.000000000 +0200 @@ -0,0 +1,141 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.38 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 886532 + +Backport of: + +From a33a2cfe2f771b360b3422f6cdf566a560860bfc Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Tue, 9 Jan 2018 13:45:14 -0200 +Subject: [PATCH] i386: Add support for SPEC_CTRL MSR + +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +Message-Id: <20180109154519.25634-3-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +--- + target/i386/cpu.h | 3 +++ + target/i386/kvm.c | 14 ++++++++++++++ + target/i386/machine.c | 20 ++++++++++++++++++++ + 3 files changed, 37 insertions(+) + +Index: qemu/target-i386/cpu.h +=================================================================== +--- qemu.orig/target-i386/cpu.h ++++ qemu/target-i386/cpu.h +@@ -309,6 +309,7 @@ + #define MSR_IA32_APICBASE_BASE (0xfffff<<12) + #define MSR_IA32_FEATURE_CONTROL 0x0000003a + #define MSR_TSC_ADJUST 0x0000003b ++#define MSR_IA32_SPEC_CTRL 0x48 + #define MSR_IA32_TSCDEADLINE 0x6e0 + + #define MSR_P6_PERFCTR0 0xc1 +@@ -874,6 +875,8 @@ typedef struct CPUX86State { + uint64_t pat; + uint32_t smbase; + ++ uint64_t spec_ctrl; ++ + /* End of state preserved by INIT (dummy marker). */ + struct {} end_init_save; + +Index: qemu/target-i386/kvm.c +=================================================================== +--- qemu.orig/target-i386/kvm.c ++++ qemu/target-i386/kvm.c +@@ -80,6 +80,7 @@ static bool has_msr_hv_hypercall; + static bool has_msr_hv_vapic; + static bool has_msr_hv_tsc; + static bool has_msr_mtrr; ++static bool has_msr_spec_ctrl; + + static bool has_msr_architectural_pmu; + static uint32_t num_architectural_pmu_counters; +@@ -814,6 +815,10 @@ static int kvm_get_supported_msrs(KVMSta + has_msr_tsc_adjust = true; + continue; + } ++ if (kvm_msr_list->indices[i] == MSR_IA32_SPEC_CTRL) { ++ has_msr_spec_ctrl = true; ++ continue; ++ } + if (kvm_msr_list->indices[i] == MSR_IA32_TSCDEADLINE) { + has_msr_tsc_deadline = true; + continue; +@@ -1213,6 +1218,9 @@ static int kvm_put_msrs(X86CPU *cpu, int + if (has_msr_bndcfgs) { + kvm_msr_entry_set(&msrs[n++], MSR_IA32_BNDCFGS, env->msr_bndcfgs); + } ++ if (has_msr_spec_ctrl) { ++ kvm_msr_entry_set(&msrs[n++], MSR_IA32_SPEC_CTRL, env->spec_ctrl); ++ } + #ifdef TARGET_X86_64 + if (lm_capable_kernel) { + kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); +@@ -1221,6 +1229,7 @@ static int kvm_put_msrs(X86CPU *cpu, int + kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar); + } + #endif ++ + /* + * The following MSRs have side effects on the guest or are too heavy + * for normal writeback. Limit them to reset or full state updates. +@@ -1551,6 +1560,9 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_bndcfgs) { + msrs[n++].index = MSR_IA32_BNDCFGS; + } ++ if (has_msr_spec_ctrl) { ++ msrs[n++].index = MSR_IA32_SPEC_CTRL; ++ } + + if (!env->tsc_valid) { + msrs[n++].index = MSR_IA32_TSC; +@@ -1789,6 +1801,9 @@ static int kvm_get_msrs(X86CPU *cpu) + env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data; + } + break; ++ case MSR_IA32_SPEC_CTRL: ++ env->spec_ctrl = msrs[i].data; ++ break; + } + } + +Index: qemu/target-i386/machine.c +=================================================================== +--- qemu.orig/target-i386/machine.c ++++ qemu/target-i386/machine.c +@@ -603,6 +603,24 @@ static const VMStateDescription vmstate_ + } + }; + ++static bool spec_ctrl_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->spec_ctrl != 0; ++} ++ ++static const VMStateDescription vmstate_spec_ctrl = { ++ .name = "cpu/spec_ctrl", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]){ ++ VMSTATE_UINT64(env.spec_ctrl, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -746,6 +764,9 @@ VMStateDescription vmstate_x86_cpu = { + .vmsd = &vmstate_msr_hyperv_time, + .needed = hyperv_time_enable_needed, + } , { ++ .vmsd = &vmstate_spec_ctrl, ++ .needed = spec_ctrl_needed, ++ } , { + /* empty */ + } + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,60 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.38 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 886532 + +Backport of: + +From a2381f0934432ef2cd47a335348ba8839632164c Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost <ehabkost@redhat.com> +Date: Tue, 9 Jan 2018 13:45:15 -0200 +Subject: [PATCH] i386: Add spec-ctrl CPUID bit + +Add the feature name and a CPUID_7_0_EDX_SPEC_CTRL macro. + +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +Message-Id: <20180109154519.25634-4-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +--- + +Backport of: + +From a2381f0934432ef2cd47a335348ba8839632164c Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost <ehabkost@redhat.com> +Date: Tue, 9 Jan 2018 13:45:15 -0200 +Subject: [PATCH] i386: Add spec-ctrl CPUID bit + +Add the feature name and a CPUID_7_0_EDX_SPEC_CTRL macro. + +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +Message-Id: <20180109154519.25634-4-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +Index: qemu/target-i386/cpu.c +=================================================================== +--- qemu.orig/target-i386/cpu.c ++++ qemu/target-i386/cpu.c +@@ -274,7 +274,7 @@ static const char *cpuid_7_0_edx_feature + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, "spec-ctrl", NULL, NULL, NULL, NULL, NULL, + }; + + static const char *cpuid_apm_edx_feature_name[] = { +Index: qemu/target-i386/cpu.h +=================================================================== +--- qemu.orig/target-i386/cpu.h ++++ qemu/target-i386/cpu.h +@@ -566,6 +566,7 @@ typedef uint32_t FeatureWordArray[FEATUR + #define CPUID_7_0_EBX_RDSEED (1U << 18) + #define CPUID_7_0_EBX_ADX (1U << 19) + #define CPUID_7_0_EBX_SMAP (1U << 20) ++#define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */ + + /* CPUID[0x80000007].EDX flags: */ + #define CPUID_APM_INVTSC (1U << 8) diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3pre1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3pre1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3pre1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5715-3pre1.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,86 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.38 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 886532 + +Description: add FEAT_7_0_ECX and FEAT_7_0_EDX for backporting reasons +Author: Marc Deslaurers <marc.deslauriers@canonical.com> + +Index: qemu/target-i386/cpu.c +=================================================================== +--- qemu.orig/target-i386/cpu.c ++++ qemu/target-i386/cpu.c +@@ -263,6 +263,20 @@ static const char *cpuid_7_0_ebx_feature + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + }; + ++static const char *cpuid_7_0_ecx_feature_name[] = { ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ ++static const char *cpuid_7_0_edx_feature_name[] = { ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++}; ++ + static const char *cpuid_apm_edx_feature_name[] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +@@ -328,6 +342,8 @@ static const char *cpuid_apm_edx_feature + CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2, + CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM, + CPUID_7_0_EBX_RDSEED */ ++#define TCG_7_0_ECX_FEATURES 0 ++#define TCG_7_0_EDX_FEATURES 0 + #define TCG_APM_FEATURES 0 + + +@@ -377,6 +393,20 @@ static FeatureWordInfo feature_word_info + .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX, + .tcg_features = TCG_SVM_FEATURES, + }, ++ [FEAT_7_0_ECX] = { ++ .feat_names = cpuid_7_0_ecx_feature_name, ++ .cpuid_eax = 7, ++ .cpuid_needs_ecx = true, .cpuid_ecx = 0, ++ .cpuid_reg = R_ECX, ++ .tcg_features = TCG_7_0_ECX_FEATURES, ++ }, ++ [FEAT_7_0_EDX] = { ++ .feat_names = cpuid_7_0_edx_feature_name, ++ .cpuid_eax = 7, ++ .cpuid_needs_ecx = true, .cpuid_ecx = 0, ++ .cpuid_reg = R_EDX, ++ .tcg_features = TCG_7_0_EDX_FEATURES, ++ }, + [FEAT_7_0_EBX] = { + .feat_names = cpuid_7_0_ebx_feature_name, + .cpuid_eax = 7, +@@ -2298,8 +2328,8 @@ void cpu_x86_cpuid(CPUX86State *env, uin + if (count == 0) { + *eax = 0; /* Maximum ECX value for sub-leaves */ + *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */ +- *ecx = 0; /* Reserved */ +- *edx = 0; /* Reserved */ ++ *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */ ++ *edx = env->features[FEAT_7_0_EDX]; /* Feature flags */ + } else { + *eax = 0; + *ebx = 0; +Index: qemu/target-i386/cpu.h +=================================================================== +--- qemu.orig/target-i386/cpu.h ++++ qemu/target-i386/cpu.h +@@ -403,6 +403,8 @@ typedef enum FeatureWord { + FEAT_1_EDX, /* CPUID[1].EDX */ + FEAT_1_ECX, /* CPUID[1].ECX */ + FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */ ++ FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */ ++ FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */ + FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */ + FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */ + FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */ diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5715-4.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5715-4.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5715-4.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5715-4.patch 2018-07-25 19:13:33.000000000 +0200 @@ -0,0 +1,87 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.38 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 886532 + +Backport of: + +From 1b3420e1c4d523c49866cca4e7544753201cd43d Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost <ehabkost@redhat.com> +Date: Tue, 9 Jan 2018 13:45:16 -0200 +Subject: [PATCH] i386: Add FEAT_8000_0008_EBX CPUID feature word + +Add the new feature word and the "ibpb" feature flag. + +Based on a patch by Paolo Bonzini. + +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +Message-Id: <20180109154519.25634-5-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +--- + target/i386/cpu.c | 19 ++++++++++++++++++- + target/i386/cpu.h | 3 +++ + 2 files changed, 21 insertions(+), 1 deletion(-) + +Index: qemu/target-i386/cpu.c +=================================================================== +--- qemu.orig/target-i386/cpu.c ++++ qemu/target-i386/cpu.c +@@ -347,6 +347,17 @@ static const char *cpuid_apm_edx_feature + #define TCG_APM_FEATURES 0 + + ++static const char *cpuid_8000_0008_ebx_feature_name[] = { ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ "ibpb", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++}; ++ + typedef struct FeatureWordInfo { + const char **feat_names; + uint32_t cpuid_eax; /* Input EAX for CPUID */ +@@ -421,6 +432,11 @@ static FeatureWordInfo feature_word_info + .tcg_features = TCG_APM_FEATURES, + .unmigratable_flags = CPUID_APM_INVTSC, + }, ++ [FEAT_8000_0008_EBX] = { ++ .feat_names = cpuid_8000_0008_ebx_feature_name, ++ .cpuid_eax = 0x80000008, ++ .cpuid_reg = R_EBX, ++ }, + }; + + typedef struct X86RegisterInfo32 { +@@ -2495,7 +2511,7 @@ void cpu_x86_cpuid(CPUX86State *env, uin + *eax = 0x00000020; /* 32 bits physical */ + } + } +- *ebx = 0; ++ *ebx = env->features[FEAT_8000_0008_EBX]; + *ecx = 0; + *edx = 0; + if (cs->nr_cores * cs->nr_threads > 1) { +Index: qemu/target-i386/cpu.h +=================================================================== +--- qemu.orig/target-i386/cpu.h ++++ qemu/target-i386/cpu.h +@@ -408,6 +408,7 @@ typedef enum FeatureWord { + FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */ + FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */ + FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */ ++ FEAT_8000_0008_EBX, /* CPUID[8000_0008].EBX */ + FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */ + FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */ + FEAT_SVM, /* CPUID[8000_000A].EDX */ +@@ -571,6 +572,8 @@ typedef uint32_t FeatureWordArray[FEATUR + /* CPUID[0x80000007].EDX flags: */ + #define CPUID_APM_INVTSC (1U << 8) + ++#define CPUID_8000_0008_EBX_IBPB (1U << 12) /* Indirect Branch Prediction Barrier */ ++ + #define CPUID_VENDOR_SZ 12 + + #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5715-5.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5715-5.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5715-5.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5715-5.patch 2018-07-25 19:13:33.000000000 +0200 @@ -0,0 +1,176 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.38 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 886532 + +Backport of: + +From ac96c41354b7e4c70b756342d9b686e31ab87458 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost <ehabkost@redhat.com> +Date: Tue, 9 Jan 2018 13:45:17 -0200 +Subject: [PATCH] i386: Add new -IBRS versions of Intel CPU models + +The new MSR IA32_SPEC_CTRL MSR was introduced by a recent Intel +microcode updated and can be used by OSes to mitigate +CVE-2017-5715. Unfortunately we can't change the existing CPU +models without breaking existing setups, so users need to +explicitly update their VM configuration to use the new *-IBRS +CPU model if they want to expose IBRS to guests. + +The new CPU models are simple copies of the existing CPU models, +with just CPUID_7_0_EDX_SPEC_CTRL added and model_id updated. + +Cc: Jiri Denemark <jdenemar@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +Message-Id: <20180109154519.25634-6-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> +--- + target/i386/cpu.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 378 insertions(+), 1 deletion(-) + +Index: qemu/target-i386/cpu.c +=================================================================== +--- qemu.orig/target-i386/cpu.c ++++ qemu/target-i386/cpu.c +@@ -1004,6 +1004,31 @@ static X86CPUDefinition builtin_x86_defs + .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", + }, + { ++ .name = "Nehalem-IBRS", ++ .level = 4, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 26, ++ .stepping = 3, ++ .features[FEAT_1_EDX] = ++ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | ++ CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_LAHF_LM, ++ .xlevel = 0x8000000A, ++ .model_id = "Intel Core i7 9xx (Nehalem Core i7, IBRS update)", ++ }, ++ { + .name = "Westmere", + .level = 11, + .vendor = CPUID_VENDOR_INTEL, +@@ -1028,6 +1053,32 @@ static X86CPUDefinition builtin_x86_defs + .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", + }, + { ++ .name = "Westmere-IBRS", ++ .level = 11, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 44, ++ .stepping = 1, ++ .features[FEAT_1_EDX] = ++ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | ++ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | ++ CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_LAHF_LM, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL, ++ .xlevel = 0x8000000A, ++ .model_id = "Westmere E56xx/L56xx/X56xx (IBRS update)", ++ }, ++ { + .name = "SandyBridge", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, +@@ -1055,6 +1106,35 @@ static X86CPUDefinition builtin_x86_defs + .model_id = "Intel Xeon E312xx (Sandy Bridge)", + }, + { ++ .name = "SandyBridge-IBRS", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 42, ++ .stepping = 1, ++ .features[FEAT_1_EDX] = ++ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | ++ CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT | ++ CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | ++ CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | ++ CPUID_EXT_SSE3, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | ++ CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_LAHF_LM, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL, ++ .xlevel = 0x8000000A, ++ .model_id = "Intel Xeon E312xx (Sandy Bridge, IBRS update)", ++ }, ++ { + .name = "Haswell", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, +@@ -1122,6 +1202,41 @@ static X86CPUDefinition builtin_x86_defs + .model_id = "Intel Core Processor (Broadwell)", + }, + { ++ .name = "Haswell-IBRS", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 60, ++ .stepping = 1, ++ .features[FEAT_1_EDX] = ++ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | ++ CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | ++ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | ++ CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | ++ CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | ++ CPUID_EXT_PCID, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX | ++ CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_LAHF_LM, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | ++ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | ++ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | ++ CPUID_7_0_EBX_RTM, ++ .xlevel = 0x8000000A, ++ .model_id = "Intel Core Processor (Haswell, IBRS)", ++ }, ++ { + .name = "Opteron_G1", + .level = 5, + .vendor = CPUID_VENDOR_AMD, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5856.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5856.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5856.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5856.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,65 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 853996 + +From 765a707000e838c30b18d712fe6cb3dd8e0435f3 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Mon, 2 Jan 2017 11:03:33 +0100 +Subject: [PATCH] megasas: fix guest-triggered memory leak + +If the guest sets the sglist size to a value >=2GB, megasas_handle_dcmd +will return MFI_STAT_MEMORY_NOT_AVAILABLE without freeing the memory. +Avoid this by returning only the status from map_dcmd, and loading +cmd->iov_size in the caller. + +Reported-by: Li Qiang <liqiang6-s@360.cn> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/scsi/megasas.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/scsi/megasas.c 2017-04-06 09:58:28.055079302 -0400 ++++ qemu-2.0.0+dfsg/hw/scsi/megasas.c 2017-04-06 09:58:28.051079252 -0400 +@@ -640,14 +640,14 @@ + trace_megasas_dcmd_invalid_sge(cmd->index, + cmd->frame->header.sge_count); + cmd->iov_size = 0; +- return -1; ++ return -EINVAL; + } + iov_pa = megasas_sgl_get_addr(cmd, &cmd->frame->dcmd.sgl); + iov_size = megasas_sgl_get_len(cmd, &cmd->frame->dcmd.sgl); + pci_dma_sglist_init(&cmd->qsg, PCI_DEVICE(s), 1); + qemu_sglist_add(&cmd->qsg, iov_pa, iov_size); + cmd->iov_size = iov_size; +- return cmd->iov_size; ++ return 0; + } + + static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size) +@@ -1449,19 +1449,20 @@ + + static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd) + { +- int opcode, len; ++ int opcode; + int retval = 0; ++ size_t len; + const struct dcmd_cmd_tbl_t *cmdptr = dcmd_cmd_tbl; + + opcode = le32_to_cpu(cmd->frame->dcmd.opcode); + trace_megasas_handle_dcmd(cmd->index, opcode); +- len = megasas_map_dcmd(s, cmd); +- if (len < 0) { ++ if (megasas_map_dcmd(s, cmd) < 0) { + return MFI_STAT_MEMORY_NOT_AVAILABLE; + } + while (cmdptr->opcode != -1 && cmdptr->opcode != opcode) { + cmdptr++; + } ++ len = cmd->iov_size; + if (cmdptr->opcode == -1) { + trace_megasas_dcmd_unhandled(cmd->index, opcode, len); + retval = megasas_dcmd_dummy(s, cmd); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5973.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5973.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5973.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5973.patch 2018-07-26 00:21:11.000000000 +0200 @@ -0,0 +1,99 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855611 + +Backport of: + +From f89b60f6e5fee3923bedf80e82b4e5efc1bb156b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Mon, 6 Feb 2017 13:21:09 +0100 +Subject: [PATCH] xhci: apply limits to loops +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Limits should be big enough that normal guest should not hit it. +Add a tracepoint to log them, just in case. Also, while being +at it, log the existing link trb limit too. + +Reported-by: æ??强 <liqiang6-s@360.cn> +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1486383669-6421-1-git-send-email-kraxel@redhat.com +--- + hw/usb/hcd-xhci.c | 15 ++++++++++++++- + hw/usb/trace-events | 1 + + 2 files changed, 15 insertions(+), 1 deletion(-) + +Index: qemu/hw/usb/hcd-xhci.c +=================================================================== +--- qemu.orig/hw/usb/hcd-xhci.c ++++ qemu/hw/usb/hcd-xhci.c +@@ -53,6 +53,8 @@ + #define ER_FULL_HACK + + #define TRB_LINK_LIMIT 4 ++#define COMMAND_LIMIT 256 ++#define TRANSFER_LIMIT 256 + + #define LEN_CAP 0x40 + #define LEN_OPER (0x400 + 0x10 * MAXPORTS) +@@ -1024,6 +1026,7 @@ static TRBType xhci_ring_fetch(XHCIState + return type; + } else { + if (++link_cnt > TRB_LINK_LIMIT) { ++ trace_usb_xhci_enforced_limit("trb-link"); + return 0; + } + ring->dequeue = xhci_mask64(trb->parameter); +@@ -2093,6 +2096,7 @@ static void xhci_kick_ep(XHCIState *xhci + XHCIRing *ring; + USBEndpoint *ep = NULL; + uint64_t mfindex; ++ unsigned int count = 0; + int length; + int i; + +@@ -2231,6 +2235,10 @@ static void xhci_kick_ep(XHCIState *xhci + epctx->retry = xfer; + break; + } ++ if (count++ > TRANSFER_LIMIT) { ++ trace_usb_xhci_enforced_limit("transfers"); ++ break; ++ } + } + + ep = xhci_epid_to_usbep(xhci, slotid, epid); +@@ -2698,7 +2706,7 @@ static void xhci_process_commands(XHCISt + TRBType type; + XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS}; + dma_addr_t addr; +- unsigned int i, slotid = 0; ++ unsigned int i, slotid = 0, count = 0; + + DPRINTF("xhci_process_commands()\n"); + if (!xhci_running(xhci)) { +@@ -2812,6 +2820,11 @@ static void xhci_process_commands(XHCISt + } + event.slotid = slotid; + xhci_event(xhci, &event, 0); ++ ++ if (count++ > COMMAND_LIMIT) { ++ trace_usb_xhci_enforced_limit("commands"); ++ return; ++ } + } + } + +Index: qemu/trace-events +=================================================================== +--- qemu.orig/trace-events ++++ qemu/trace-events +@@ -394,6 +394,7 @@ usb_xhci_xfer_retry(void *xfer) "%p" + usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d" + usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d" + usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)" ++usb_xhci_enforced_limit(const char *item) "%s" + + # hw/usb/desc.c + usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5987-1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5987-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5987-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5987-1.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,42 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855159 + +From 8b20aefac4ee8874bb9c8826e4b30e1dc8cd7511 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 28 Feb 2017 12:08:14 +0000 +Subject: [PATCH] sd: sdhci: mask transfer mode register value + +In SDHCI protocol, the transfer mode register is defined +to be of 6 bits. Mask its value with '0x0037' so that an +invalid value could not be assigned. + +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> +Message-id: 20170214185225.7994-2-ppandit@redhat.com +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +--- + hw/sd/sdhci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/sd/sdhci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/sd/sdhci.c 2017-04-06 10:00:01.628252853 -0400 ++++ qemu-2.0.0+dfsg/hw/sd/sdhci.c 2017-04-06 10:00:01.628252853 -0400 +@@ -114,6 +114,7 @@ + (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \ + (SDHC_CAPAB_TOCLKFREQ)) + ++#define MASK_TRNMOD 0x0037 + #define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val)) + + static uint8_t sdhci_slotint(SDHCIState *s) +@@ -1016,7 +1017,7 @@ + if (!(s->capareg & SDHC_CAN_DO_DMA)) { + value &= ~SDHC_TRNS_DMA; + } +- MASKED_WRITE(s->trnmod, mask, value); ++ MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD); + MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); + + /* Writing to the upper byte of CMDREG triggers SD command generation */ diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5987-2.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5987-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5987-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5987-2.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,55 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855159 + +From 6e86d90352adf6cb08295255220295cf23c4286e Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 28 Feb 2017 12:08:14 +0000 +Subject: [PATCH] sd: sdhci: check transfer mode register in multi block + transfer + +In the SDHCI protocol, the transfer mode register value +is used during multi block transfer to check if block count +register is enabled and should be updated. Transfer mode +register could be set such that, block count register would +not be updated, thus leading to an infinite loop. Add check +to avoid it. + +Reported-by: Wjjzhang <wjjzhang@tencent.com> +Reported-by: Jiang Xin <jiangxin1@huawei.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 20170214185225.7994-3-ppandit@redhat.com +Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +--- + hw/sd/sdhci.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/sd/sdhci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/sd/sdhci.c 2017-04-06 10:00:09.128346859 -0400 ++++ qemu-2.0.0+dfsg/hw/sd/sdhci.c 2017-04-06 10:00:09.124346809 -0400 +@@ -469,6 +469,11 @@ + uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12); + uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk); + ++ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) { ++ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n"); ++ return; ++ } ++ + /* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for + * possible stop at page boundary if initial address is not page aligned, + * allow them to work properly */ +@@ -777,11 +782,6 @@ + if (s->trnmod & SDHC_TRNS_DMA) { + switch (SDHC_DMA_TYPE(s->hostctl)) { + case SDHC_CTRL_SDMA: +- if ((s->trnmod & SDHC_TRNS_MULTI) && +- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) { +- break; +- } +- + if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) { + k->do_sdma_single(s); + } else { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5987-3.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5987-3.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5987-3.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5987-3.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,39 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855159 + +Backport of: + +From 45ba9f761bde329cc5ef276b571bd4f3c41a044e Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 28 Feb 2017 12:08:14 +0000 +Subject: [PATCH] sd: sdhci: conditionally invoke multi block transfer + +In sdhci_write invoke multi block transfer if it is enabled +in the transfer mode register 's->trnmod'. + +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 20170214185225.7994-4-ppandit@redhat.com +Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +--- + hw/sd/sdhci.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/sd/sdhci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/sd/sdhci.c 2017-04-06 10:00:16.620440758 -0400 ++++ qemu-2.0.0+dfsg/hw/sd/sdhci.c 2017-04-06 10:01:48.933597061 -0400 +@@ -999,7 +999,11 @@ + /* Writing to last byte of sdmasysad might trigger transfer */ + if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt && + s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) { +- SDHCI_GET_CLASS(s)->do_sdma_multi(s); ++ if (s->trnmod & SDHC_TRNS_MULTI) { ++ SDHCI_GET_CLASS(s)->do_sdma_multi(s); ++ } else { ++ SDHCI_GET_CLASS(s)->do_sdma_single(s); ++ } + } + break; + case SDHC_BLKSIZE: diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-5987-4.patch qemu-2.1+dfsg/debian/patches/CVE-2017-5987-4.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-5987-4.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-5987-4.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,46 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 855159 + +From 241999bf4c0dd75d300ceee46f7ad28b3a39fe97 Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Tue, 28 Feb 2017 12:08:15 +0000 +Subject: [PATCH] sd: sdhci: Remove block count enable check in single block + transfers + +In SDHCI protocol, the 'Block count enable' bit of the Transfer +Mode register is relevant only in multi block transfers. We need +not check it in single block transfers. + +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 20170214185225.7994-5-ppandit@redhat.com +Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +--- + hw/sd/sdhci.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/sd/sdhci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/sd/sdhci.c 2017-04-06 10:02:18.973973088 -0400 ++++ qemu-2.0.0+dfsg/hw/sd/sdhci.c 2017-04-06 10:02:18.969973037 -0400 +@@ -552,7 +552,6 @@ + } + + /* single block SDMA transfer */ +- + static void sdhci_sdma_transfer_single_block(SDHCIState *s) + { + int n; +@@ -571,10 +570,7 @@ + sd_write_data(s->card, s->fifo_buffer[n]); + } + } +- +- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) { +- s->blkcnt--; +- } ++ s->blkcnt--; + + SDHCI_GET_CLASS(s)->end_data_transfer(s); + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-6505.patch qemu-2.1+dfsg/debian/patches/CVE-2017-6505.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-6505.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-6505.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,53 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.33 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 856969 + +From 95ed56939eb2eaa4e2f349fe6dcd13ca4edfd8fb Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Tue, 7 Feb 2017 02:23:33 -0800 +Subject: [PATCH] usb: ohci: limit the number of link eds + +The guest may builds an infinite loop with link eds. This patch +limit the number of linked ed to avoid this. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-id: 5899a02e.45ca240a.6c373.93c1@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/usb/hcd-ohci.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/usb/hcd-ohci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/hcd-ohci.c 2017-04-06 10:02:27.030073908 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/hcd-ohci.c 2017-04-06 10:02:27.026073858 -0400 +@@ -49,6 +49,8 @@ + + #define OHCI_MAX_PORTS 15 + ++#define ED_LINK_LIMIT 4 ++ + static int64_t usb_frame_time; + static int64_t usb_bit_time; + +@@ -1190,7 +1192,7 @@ + uint32_t next_ed; + uint32_t cur; + int active; +- ++ uint32_t link_cnt = 0; + active = 0; + + if (head == 0) +@@ -1205,6 +1207,11 @@ + + next_ed = ed.next & OHCI_DPTR_MASK; + ++ if (++link_cnt > ED_LINK_LIMIT) { ++ ohci_die(ohci); ++ return 0; ++ } ++ + if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { + uint32_t addr; + /* Cancel pending packets for ED that have been paused. */ diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7377.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7377.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7377.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7377.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,52 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 859854 + +Backport of: + +From d63fb193e71644a073b77ff5ac6f1216f2f6cf6e Mon Sep 17 00:00:00 2001 +From: Li Qiang <liq3ea@gmail.com> +Date: Mon, 27 Mar 2017 21:13:19 +0200 +Subject: [PATCH] 9pfs: fix file descriptor leak + +The v9fs_create() and v9fs_lcreate() functions are used to create a file +on the backend and to associate it to a fid. The fid shouldn't be already +in-use, otherwise both functions may silently leak a file descriptor or +allocated memory. The current code doesn't check that. + +This patch ensures that the fid isn't already associated to anything +before using it. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +(reworded the changelog, Greg Kurz) +Signed-off-by: Greg Kurz <groug@kaod.org> +--- + hw/9pfs/9p.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/9pfs/virtio-9p.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/9pfs/virtio-9p.c 2017-05-10 15:35:09.642553470 -0400 ++++ qemu-2.0.0+dfsg/hw/9pfs/virtio-9p.c 2017-05-10 15:35:09.626553317 -0400 +@@ -1500,6 +1500,10 @@ static void v9fs_lcreate(void *opaque) + err = -ENOENT; + goto out_nofid; + } ++ if (fidp->fid_type != P9_FID_NONE) { ++ err = -EINVAL; ++ goto out; ++ } + + flags = get_dotl_openflags(pdu->s, flags); + err = v9fs_co_open2(pdu, fidp, &name, gid, +@@ -2092,6 +2096,10 @@ static void v9fs_create(void *opaque) + err = -EINVAL; + goto out_nofid; + } ++ if (fidp->fid_type != P9_FID_NONE) { ++ err = -EINVAL; ++ goto out; ++ } + if (perm & P9_STAT_MODE_DIR) { + err = v9fs_co_mkdir(pdu, fidp, &name, perm & 0777, + fidp->uid, -1, &stbuf); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7471.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7471.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7471.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7471.patch 2018-07-24 16:08:46.000000000 +0200 @@ -0,0 +1,60 @@ +Origin: backported, http://git.qemu-project.org/?p=qemu.git;a=commitdiff;h=9c6b899f7a46893ab3b671e341a2234e9c0c060e +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 860785 + +commit 9c6b899f7a46893ab3b671e341a2234e9c0c060e +Author: Greg Kurz <groug@kaod.org> +Date: Mon Apr 17 10:53:23 2017 +0200 + + 9pfs: local: set the path of the export root to "." + + The local backend was recently converted to using "at*()" syscalls in order + to ensure all accesses happen below the shared directory. This requires that + we only pass relative paths, otherwise the dirfd argument to the "at*()" + syscalls is ignored and the path is treated as an absolute path in the host. + This is actually the case for paths in all fids, with the notable exception + of the root fid, whose path is "/". This causes the following backend ops to + act on the "/" directory of the host instead of the virtfs shared directory + when the export root is involved: + - lstat + - chmod + - chown + - utimensat + + ie, chmod /9p_mount_point in the guest will be converted to chmod / in the + host for example. This could cause security issues with a privileged QEMU. + + All "*at()" syscalls are being passed an open file descriptor. In the case + of the export root, this file descriptor points to the path in the host that + was passed to -fsdev. + + The fix is thus as simple as changing the path of the export root fid to be + "." instead of "/". + + This is CVE-2017-7471. + + Cc: qemu-stable@nongnu.org + Reported-by: Léo Gaspard <leo@gaspard.io> + Signed-off-by: Greg Kurz <groug@kaod.org> + Reviewed-by: Eric Blake <eblake@redhat.com> + Signed-off-by: Peter Maydell <peter.maydell@linaro.org> + +Index: qemu/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-local.c ++++ qemu/hw/9pfs/virtio-9p-local.c +@@ -1094,8 +1094,13 @@ static int local_name_to_path(FsContext + if (dir_path) { + v9fs_string_sprintf((V9fsString *)target, "%s/%s", + dir_path->data, name); +- } else { ++ } else if (strcmp(name, "/")) { + v9fs_string_sprintf((V9fsString *)target, "%s", name); ++ } else { ++ /* We want the path of the export root to be relative, otherwise ++ * "*at()" syscalls would treat it as "/" in the host. ++ */ ++ v9fs_string_sprintf((V9fsString *)target, "%s", "."); + } + /* Bump the size for including terminating NULL */ + target->size++; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7493.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7493.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7493.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7493.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,176 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> + +Backport of: + +From 7a95434e0ca8a037fd8aa1a2e2461f92585eb77b Mon Sep 17 00:00:00 2001 +From: Greg Kurz <groug@kaod.org> +Date: Fri, 5 May 2017 14:48:08 +0200 +Subject: [PATCH] 9pfs: local: forbid client access to metadata (CVE-2017-7493) + +When using the mapped-file security mode, we shouldn't let the client mess +with the metadata. The current code already tries to hide the metadata dir +from the client by skipping it in local_readdir(). But the client can still +access or modify it through several other operations. This can be used to +escalate privileges in the guest. + +Affected backend operations are: +- local_mknod() +- local_mkdir() +- local_open2() +- local_symlink() +- local_link() +- local_unlinkat() +- local_renameat() +- local_rename() +- local_name_to_path() + +Other operations are safe because they are only passed a fid path, which +is computed internally in local_name_to_path(). + +This patch converts all the functions listed above to fail and return +EINVAL when being passed the name of the metadata dir. This may look +like a poor choice for errno, but there's no such thing as an illegal +path name on Linux and I could not think of anything better. + +This fixes CVE-2017-7493. + +Reported-by: Leo Gaspard <leo@gaspard.io> +Signed-off-by: Greg Kurz <groug@kaod.org> +Reviewed-by: Eric Blake <eblake@redhat.com> +--- + hw/9pfs/9p-local.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 56 insertions(+), 2 deletions(-) + +Index: qemu/hw/9pfs/virtio-9p-local.c +=================================================================== +--- qemu.orig/hw/9pfs/virtio-9p-local.c ++++ qemu/hw/9pfs/virtio-9p-local.c +@@ -451,6 +451,11 @@ static off_t local_telldir(FsContext *ct + return telldir(fs->dir); + } + ++static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name) ++{ ++ return !strcmp(name, VIRTFS_META_DIR); ++} ++ + static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, + struct dirent *entry, + struct dirent **result) +@@ -464,8 +469,8 @@ again: + } + else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { + if (!ret && *result != NULL && +- !strcmp(entry->d_name, VIRTFS_META_DIR)) { +- /* skp the meta data directory */ ++ local_is_mapped_file_metadata(ctx, entry->d_name)) { ++ /* skip the meta data directory */ + goto again; + } + entry->d_type = DT_UNKNOWN; +@@ -558,6 +563,12 @@ static int local_mknod(FsContext *fs_ctx + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); + if (dirfd == -1) { + return -1; +@@ -603,6 +614,12 @@ static int local_mkdir(FsContext *fs_ctx + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); + if (dirfd == -1) { + return -1; +@@ -692,6 +709,12 @@ static int local_open2(FsContext *fs_ctx + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + /* + * Mark all the open to not follow symlinks + */ +@@ -750,6 +773,12 @@ static int local_symlink(FsContext *fs_c + int err = -1; + int dirfd; + ++ if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(fs_ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(fs_ctx, dir_path->data); + if (dirfd == -1) { + return -1; +@@ -824,6 +853,12 @@ static int local_link(FsContext *ctx, V9 + int ret = -1; + int odirfd, ndirfd; + ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + odirfd = local_opendir_nofollow(ctx, odirpath); + if (odirfd == -1) { + goto out; +@@ -1091,6 +1126,12 @@ static int local_lremovexattr(FsContext + static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, + const char *name, V9fsPath *target) + { ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + if (dir_path) { + v9fs_string_sprintf((V9fsString *)target, "%s/%s", + dir_path->data, name); +@@ -1114,6 +1155,13 @@ static int local_renameat(FsContext *ctx + int ret; + int odirfd, ndirfd; + ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ (local_is_mapped_file_metadata(ctx, old_name) || ++ local_is_mapped_file_metadata(ctx, new_name))) { ++ errno = EINVAL; ++ return -1; ++ } ++ + odirfd = local_opendir_nofollow(ctx, olddir->data); + if (odirfd == -1) { + return -1; +@@ -1204,6 +1252,12 @@ static int local_unlinkat(FsContext *ctx + int ret; + int dirfd; + ++ if (ctx->export_flags & V9FS_SM_MAPPED_FILE && ++ local_is_mapped_file_metadata(ctx, name)) { ++ errno = EINVAL; ++ return -1; ++ } ++ + dirfd = local_opendir_nofollow(ctx, dir->data); + if (dirfd == -1) { + return -1; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7718.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7718.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7718.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7718.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,51 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From 215902d7b6fb50c6fc216fc74f770858278ed904 Mon Sep 17 00:00:00 2001 +From: hangaohuai <hangaohuai@huawei.com> +Date: Tue, 14 Mar 2017 14:39:19 +0800 +Subject: [PATCH] fix :cirrus_vga fix OOB read case qemu Segmentation fault + +check the validity of parameters in cirrus_bitblt_rop_fwd_transp_xxx +and cirrus_bitblt_rop_fwd_xxx to avoid the OOB read which causes qemu Segmentation fault. + +After the fix, we will touch the assert in +cirrus_invalidate_region: +assert(off_cur_end >= off_cur); + +Signed-off-by: fangying <fangying1@huawei.com> +Signed-off-by: hangaohuai <hangaohuai@huawei.com> +Message-id: 20170314063919.16200-1-hangaohuai@huawei.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/display/cirrus_vga_rop.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga_rop.h 2017-05-10 15:35:19.158644318 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop.h 2017-05-10 15:35:19.154644279 -0400 +@@ -98,6 +98,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, + uint8_t p; + dstpitch -= bltwidth; + srcpitch -= bltwidth; ++ ++ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { ++ return; ++ } ++ + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; +@@ -144,6 +149,11 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, + uint8_t p1, p2; + dstpitch -= bltwidth; + srcpitch -= bltwidth; ++ ++ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { ++ return; ++ } ++ + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *dst; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-1-CVE-2017-18030.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-1-CVE-2017-18030.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-1-CVE-2017-18030.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-1-CVE-2017-18030.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,50 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From f153b563f8cf121aebf5a2fff5f0110faf58ccb3 Mon Sep 17 00:00:00 2001 +From: Wolfgang Bumiller <w.bumiller@proxmox.com> +Date: Wed, 25 Jan 2017 14:48:57 +0100 +Subject: [PATCH] cirrus: handle negative pitch in cirrus_invalidate_region() + +cirrus_invalidate_region() calls memory_region_set_dirty() +on a per-line basis, always ranging from off_begin to +off_begin+bytesperline. With a negative pitch off_begin +marks the top most used address and thus we need to do an +initial shift backwards by a line for negative pitches of +backward blits, otherwise the first iteration covers the +line going from the start offset forwards instead of +backwards. +Additionally since the start address is inclusive, if we +shift by a full `bytesperline` we move to the first address +*not* included in the blit, so we only shift by one less +than bytesperline. + +Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> +Message-id: 1485352137-29367-1-git-send-email-w.bumiller@proxmox.com + +[ kraxel: codestyle fixes ] + +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/display/cirrus_vga.c | 5 +++++ + 1 file changed, 5 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:47:48.281796009 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:47:48.277795970 -0400 +@@ -655,9 +655,14 @@ static void cirrus_invalidate_region(Cir + int off_cur; + int off_cur_end; + ++ if (off_pitch < 0) { ++ off_begin -= bytesperline - 1; ++ } ++ + for (y = 0; y < lines; y++) { + off_cur = off_begin; + off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; ++ assert(off_cur_end >= off_cur); + memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); + off_begin += off_pitch; + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-2.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-2.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,102 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From 5858dd1801883309bdd208d72ddb81c4e9fee30c Mon Sep 17 00:00:00 2001 +From: Wolfgang Bumiller <w.bumiller@proxmox.com> +Date: Tue, 24 Jan 2017 16:35:38 +0100 +Subject: [PATCH] cirrus: allow zero source pitch in pattern fill rops + +The rops used by cirrus_bitblt_common_patterncopy only use +the destination pitch, so the source pitch shoul allowed to +be zero and the blit with used for the range check around the +source address. + +Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> +Message-id: 1485272138-23249-1-git-send-email-w.bumiller@proxmox.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/display/cirrus_vga.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:47:55.761867419 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:47:55.757867381 -0400 +@@ -267,9 +267,6 @@ static void cirrus_update_memory_access( + static bool blit_region_is_unsafe(struct CirrusVGAState *s, + int32_t pitch, int32_t addr) + { +- if (!pitch) { +- return true; +- } + if (pitch < 0) { + int64_t min = addr + + ((int64_t)s->cirrus_blt_height - 1) * pitch +@@ -288,8 +285,11 @@ static bool blit_region_is_unsafe(struct + return false; + } + +-static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only) ++static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only, ++ bool zero_src_pitch_ok) + { ++ int32_t check_pitch; ++ + /* should be the case, see cirrus_bitblt_start */ + assert(s->cirrus_blt_width > 0); + assert(s->cirrus_blt_height > 0); +@@ -298,6 +298,10 @@ static bool blit_is_unsafe(struct Cirrus + return true; + } + ++ if (!s->cirrus_blt_dstpitch) { ++ return true; ++ } ++ + if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch, + s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) { + return true; +@@ -305,7 +309,13 @@ static bool blit_is_unsafe(struct Cirrus + if (dst_only) { + return false; + } +- if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch, ++ ++ check_pitch = s->cirrus_blt_srcpitch; ++ if (!zero_src_pitch_ok && !check_pitch) { ++ check_pitch = s->cirrus_blt_width; ++ } ++ ++ if (blit_region_is_unsafe(s, check_pitch, + s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) { + return true; + } +@@ -675,8 +685,9 @@ static int cirrus_bitblt_common_patternc + + dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); + +- if (blit_is_unsafe(s, false)) ++ if (blit_is_unsafe(s, false, true)) { + return 0; ++ } + + (*s->cirrus_rop) (s, dst, src, + s->cirrus_blt_dstpitch, 0, +@@ -693,7 +704,7 @@ static int cirrus_bitblt_solidfill(Cirru + { + cirrus_fill_t rop_func; + +- if (blit_is_unsafe(s, true)) { ++ if (blit_is_unsafe(s, true, true)) { + return 0; + } + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; +@@ -791,7 +802,7 @@ static int cirrus_do_copy(CirrusVGAState + + static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) + { +- if (blit_is_unsafe(s, false)) ++ if (blit_is_unsafe(s, false, false)) + return 0; + + return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-3.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-3.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-3.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-3.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,104 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From 60cd23e85151525ab26591394c4e7e06fa07d216 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Wed, 25 Jan 2017 11:09:56 +0100 +Subject: [PATCH] cirrus: fix blit address mask handling + +Apply the cirrus_addr_mask to cirrus_blt_dstaddr and cirrus_blt_srcaddr +right after assigning them, in cirrus_bitblt_start(), instead of having +this all over the place in the cirrus code, and missing a few places. + +Reported-by: Wolfgang Bumiller <w.bumiller@proxmox.com> +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1485338996-17095-1-git-send-email-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:48:00.989917330 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:48:00.985917292 -0400 +@@ -303,7 +303,7 @@ static bool blit_is_unsafe(struct Cirrus + } + + if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch, +- s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) { ++ s->cirrus_blt_dstaddr)) { + return true; + } + if (dst_only) { +@@ -316,7 +316,7 @@ static bool blit_is_unsafe(struct Cirrus + } + + if (blit_region_is_unsafe(s, check_pitch, +- s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) { ++ s->cirrus_blt_srcaddr)) { + return true; + } + +@@ -683,7 +683,7 @@ static int cirrus_bitblt_common_patternc + { + uint8_t *dst; + +- dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); ++ dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr; + + if (blit_is_unsafe(s, false, true)) { + return 0; +@@ -708,7 +708,7 @@ static int cirrus_bitblt_solidfill(Cirru + return 0; + } + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; +- rop_func(s, s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), ++ rop_func(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, +@@ -726,9 +726,8 @@ static int cirrus_bitblt_solidfill(Cirru + + static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) + { +- return cirrus_bitblt_common_patterncopy(s, +- s->vga.vram_ptr + ((s->cirrus_blt_srcaddr & ~7) & +- s->cirrus_addr_mask)); ++ return cirrus_bitblt_common_patterncopy(s, s->vga.vram_ptr + ++ (s->cirrus_blt_srcaddr & ~7)); + } + + static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) +@@ -777,10 +776,8 @@ static int cirrus_do_copy(CirrusVGAState + } + } + +- (*s->cirrus_rop) (s, s->vga.vram_ptr + +- (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), +- s->vga.vram_ptr + +- (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), ++ (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, ++ s->vga.vram_ptr + s->cirrus_blt_srcaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + +@@ -830,8 +827,7 @@ static void cirrus_bitblt_cputovideo_nex + } else { + /* at least one scan line */ + do { +- (*s->cirrus_rop)(s, s->vga.vram_ptr + +- (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), ++ (*s->cirrus_rop)(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, + s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, + s->cirrus_blt_width, 1); +@@ -958,6 +954,9 @@ static void cirrus_bitblt_start(CirrusVG + s->cirrus_blt_modeext = s->vga.gr[0x33]; + blt_rop = s->vga.gr[0x32]; + ++ s->cirrus_blt_dstaddr &= s->cirrus_addr_mask; ++ s->cirrus_blt_srcaddr &= s->cirrus_addr_mask; ++ + #ifdef DEBUG_BITBLT + printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", + blt_rop, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-4.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-4.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-4.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-4.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,104 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From 95280c31cda79bb1d0968afc7b19a220b3a9d986 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Thu, 9 Feb 2017 14:02:20 +0100 +Subject: [PATCH] cirrus: fix patterncopy checks + +The blit_region_is_unsafe checks don't work correctly for the +patterncopy source. It's a fixed-sized region, which doesn't +depend on cirrus_blt_{width,height}. So go do the check in +cirrus_bitblt_common_patterncopy instead, then tell blit_is_unsafe that +it doesn't need to verify the source. Also handle the case where we +blit from cirrus_bitbuf correctly. + +This patch replaces 5858dd1801883309bdd208d72ddb81c4e9fee30c. + +Security impact: I think for the most part error on the safe side this +time, refusing blits which should have been allowed. + +Only exception is placing the blit source at the end of the video ram, +so cirrus_blt_srcaddr + 256 goes beyond the end of video memory. But +even in that case I'm not fully sure this actually allows read access to +host memory. To trick the commit 5858dd18 security checks one has to +pick very small cirrus_blt_{width,height} values, which in turn implies +only a fraction of the blit source will actually be used. + +Cc: Wolfgang Bumiller <w.bumiller@proxmox.com> +Cc: Dr. David Alan Gilbert <dgilbert@redhat.com> +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> +Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com> +Reviewed-by: Laurent Vivier <lvivier@redhat.com> +Message-id: 1486645341-5010-1-git-send-email-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:48:06.709971937 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:48:06.709971937 -0400 +@@ -678,14 +678,39 @@ static void cirrus_invalidate_region(Cir + } + } + +-static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, +- const uint8_t * src) ++static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) + { ++ uint32_t patternsize; + uint8_t *dst; ++ uint8_t *src; + + dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr; + +- if (blit_is_unsafe(s, false, true)) { ++ if (videosrc) { ++ switch (s->vga.get_bpp(&s->vga)) { ++ case 8: ++ patternsize = 64; ++ break; ++ case 15: ++ case 16: ++ patternsize = 128; ++ break; ++ case 24: ++ case 32: ++ default: ++ patternsize = 256; ++ break; ++ } ++ s->cirrus_blt_srcaddr &= ~(patternsize - 1); ++ if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) { ++ return 0; ++ } ++ src = s->vga.vram_ptr + s->cirrus_blt_srcaddr; ++ } else { ++ src = s->cirrus_bltbuf; ++ } ++ ++ if (blit_is_unsafe(s, true, true)) { + return 0; + } + +@@ -726,8 +751,7 @@ static int cirrus_bitblt_solidfill(Cirru + + static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) + { +- return cirrus_bitblt_common_patterncopy(s, s->vga.vram_ptr + +- (s->cirrus_blt_srcaddr & ~7)); ++ return cirrus_bitblt_common_patterncopy(s, true); + } + + static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) +@@ -820,7 +844,7 @@ static void cirrus_bitblt_cputovideo_nex + + if (s->cirrus_srccounter > 0) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { +- cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); ++ cirrus_bitblt_common_patterncopy(s, false); + the_end: + s->cirrus_srccounter = 0; + cirrus_bitblt_reset(s); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-5.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-5.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-5.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-5.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,103 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From 12e97ec39931e5321645fd483ab761319d48bf16 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Thu, 9 Feb 2017 14:02:21 +0100 +Subject: [PATCH] Revert "cirrus: allow zero source pitch in pattern fill rops" + +This reverts commit 5858dd1801883309bdd208d72ddb81c4e9fee30c. + +Conflicts: + hw/display/cirrus_vga.c + +Cc: Wolfgang Bumiller <w.bumiller@proxmox.com> +Cc: Dr. David Alan Gilbert <dgilbert@redhat.com> +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> +Reviewed-by: Laurent Vivier <lvivier@redhat.com> +Message-id: 1486645341-5010-2-git-send-email-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 26 ++++++++------------------ + 1 file changed, 8 insertions(+), 18 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:48:14.878049916 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:48:14.874049878 -0400 +@@ -267,6 +267,9 @@ static void cirrus_update_memory_access( + static bool blit_region_is_unsafe(struct CirrusVGAState *s, + int32_t pitch, int32_t addr) + { ++ if (!pitch) { ++ return true; ++ } + if (pitch < 0) { + int64_t min = addr + + ((int64_t)s->cirrus_blt_height - 1) * pitch +@@ -285,11 +288,8 @@ static bool blit_region_is_unsafe(struct + return false; + } + +-static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only, +- bool zero_src_pitch_ok) ++static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only) + { +- int32_t check_pitch; +- + /* should be the case, see cirrus_bitblt_start */ + assert(s->cirrus_blt_width > 0); + assert(s->cirrus_blt_height > 0); +@@ -298,10 +298,6 @@ static bool blit_is_unsafe(struct Cirrus + return true; + } + +- if (!s->cirrus_blt_dstpitch) { +- return true; +- } +- + if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch, + s->cirrus_blt_dstaddr)) { + return true; +@@ -309,13 +305,7 @@ static bool blit_is_unsafe(struct Cirrus + if (dst_only) { + return false; + } +- +- check_pitch = s->cirrus_blt_srcpitch; +- if (!zero_src_pitch_ok && !check_pitch) { +- check_pitch = s->cirrus_blt_width; +- } +- +- if (blit_region_is_unsafe(s, check_pitch, ++ if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch, + s->cirrus_blt_srcaddr)) { + return true; + } +@@ -710,7 +700,7 @@ static int cirrus_bitblt_common_patternc + src = s->cirrus_bltbuf; + } + +- if (blit_is_unsafe(s, true, true)) { ++ if (blit_is_unsafe(s, true)) { + return 0; + } + +@@ -729,7 +719,7 @@ static int cirrus_bitblt_solidfill(Cirru + { + cirrus_fill_t rop_func; + +- if (blit_is_unsafe(s, true, true)) { ++ if (blit_is_unsafe(s, true)) { + return 0; + } + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; +@@ -823,7 +813,7 @@ static int cirrus_do_copy(CirrusVGAState + + static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) + { +- if (blit_is_unsafe(s, false, false)) ++ if (blit_is_unsafe(s, false)) + return 0; + + return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-6.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-6.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-6.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-6.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,619 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From 026aeffcb4752054830ba203020ed6eb05bcaba8 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Wed, 15 Mar 2017 11:47:52 +0100 +Subject: [PATCH] cirrus: stop passing around dst pointers in the blitter + +Instead pass around the address (aka offset into vga memory). Calculate +the pointer in the rop_* functions, after applying the mask to the +address, to make sure the address stays within the valid range. + +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1489574872-8679-1-git-send-email-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 20 +++--- + hw/display/cirrus_vga_rop.h | 161 +++++++++++++++++++++++++------------------ + hw/display/cirrus_vga_rop2.h | 97 +++++++++++++------------- + 3 files changed, 153 insertions(+), 125 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:48:20.602104562 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:48:20.594104486 -0400 +@@ -174,11 +174,12 @@ + + struct CirrusVGAState; + typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, +- uint8_t * dst, const uint8_t * src, ++ uint32_t dstaddr, const uint8_t *src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight); + typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, +- uint8_t *dst, int dst_pitch, int width, int height); ++ uint32_t dstaddr, int dst_pitch, ++ int width, int height); + + typedef struct CirrusVGAState { + VGACommonState vga; +@@ -314,14 +315,14 @@ static bool blit_is_unsafe(struct Cirrus + } + + static void cirrus_bitblt_rop_nop(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, ++ uint32_t dstaddr, const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) + { + } + + static void cirrus_bitblt_fill_nop(CirrusVGAState *s, +- uint8_t *dst, ++ uint32_t dstaddr, + int dstpitch, int bltwidth,int bltheight) + { + } +@@ -671,11 +672,8 @@ static void cirrus_invalidate_region(Cir + static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) + { + uint32_t patternsize; +- uint8_t *dst; + uint8_t *src; + +- dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr; +- + if (videosrc) { + switch (s->vga.get_bpp(&s->vga)) { + case 8: +@@ -704,7 +702,7 @@ static int cirrus_bitblt_common_patternc + return 0; + } + +- (*s->cirrus_rop) (s, dst, src, ++ (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, src, + s->cirrus_blt_dstpitch, 0, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, +@@ -723,7 +721,7 @@ static int cirrus_bitblt_solidfill(Cirru + return 0; + } + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; +- rop_func(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, ++ rop_func(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, +@@ -790,7 +788,7 @@ static int cirrus_do_copy(CirrusVGAState + } + } + +- (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, ++ (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, + s->vga.vram_ptr + s->cirrus_blt_srcaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, + s->cirrus_blt_width, s->cirrus_blt_height); +@@ -841,7 +839,7 @@ static void cirrus_bitblt_cputovideo_nex + } else { + /* at least one scan line */ + do { +- (*s->cirrus_rop)(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, ++ (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr, + s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, + s->cirrus_blt_width, 1); +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga_rop.h 2017-05-10 15:48:20.602104562 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop.h 2017-05-10 15:48:20.598104524 -0400 +@@ -22,31 +22,65 @@ + * THE SOFTWARE. + */ + +-static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) ++static inline void glue(rop_8_, ROP_NAME)(CirrusVGAState *s, ++ uint32_t dstaddr, uint8_t src) + { ++ uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask]; + *dst = ROP_FN(*dst, src); + } + +-static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) ++static inline void glue(rop_tr_8_, ROP_NAME)(CirrusVGAState *s, ++ uint32_t dstaddr, uint8_t src, ++ uint8_t transp) + { ++ uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask]; ++ uint8_t pixel = ROP_FN(*dst, src); ++ if (pixel != transp) { ++ *dst = pixel; ++ } ++} ++ ++static inline void glue(rop_16_, ROP_NAME)(CirrusVGAState *s, ++ uint32_t dstaddr, uint16_t src) ++{ ++ uint16_t *dst = (uint16_t *) ++ (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]); + *dst = ROP_FN(*dst, src); + } + +-static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) ++static inline void glue(rop_tr_16_, ROP_NAME)(CirrusVGAState *s, ++ uint32_t dstaddr, uint16_t src, ++ uint16_t transp) ++{ ++ uint16_t *dst = (uint16_t *) ++ (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]); ++ uint16_t pixel = ROP_FN(*dst, src); ++ if (pixel != transp) { ++ *dst = pixel; ++ } ++} ++ ++static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s, ++ uint32_t dstaddr, uint32_t src) + { ++ uint32_t *dst = (uint32_t *) ++ (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~3]); + *dst = ROP_FN(*dst, src); + } + +-#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) +-#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) +-#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) ++#define ROP_OP(st, d, s) glue(rop_8_, ROP_NAME)(st, d, s) ++#define ROP_OP_TR(st, d, s, t) glue(rop_tr_8_, ROP_NAME)(st, d, s, t) ++#define ROP_OP_16(st, d, s) glue(rop_16_, ROP_NAME)(st, d, s) ++#define ROP_OP_TR_16(st, d, s, t) glue(rop_tr_16_, ROP_NAME)(st, d, s, t) ++#define ROP_OP_32(st, d, s) glue(rop_32_, ROP_NAME)(st, d, s) + #undef ROP_FN + + static void + glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, +- int dstpitch,int srcpitch, +- int bltwidth,int bltheight) ++ uint32_t dstaddr, ++ const uint8_t *src, ++ int dstpitch, int srcpitch, ++ int bltwidth, int bltheight) + { + int x,y; + dstpitch -= bltwidth; +@@ -59,43 +93,47 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(C + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- ROP_OP(dst, *src); +- dst++; ++ ROP_OP(s, dstaddr, *src); ++ dstaddr++; + src++; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + src += srcpitch; + } + } + + static void + glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, +- int dstpitch,int srcpitch, +- int bltwidth,int bltheight) ++ uint32_t dstaddr, ++ const uint8_t *src, ++ int dstpitch, int srcpitch, ++ int bltwidth, int bltheight) + { + int x,y; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- ROP_OP(dst, *src); +- dst--; ++ ROP_OP(s, dstaddr, *src); ++ dstaddr--; + src--; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + src += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, +- int dstpitch,int srcpitch, +- int bltwidth,int bltheight) ++ uint32_t dstaddr, ++ const uint8_t *src, ++ int dstpitch, ++ int srcpitch, ++ int bltwidth, ++ int bltheight) + { + int x,y; +- uint8_t p; ++ uint8_t transp = s->vga.gr[0x34]; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + +@@ -105,48 +143,50 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- p = *dst; +- ROP_OP(&p, *src); +- if (p != s->vga.gr[0x34]) *dst = p; +- dst++; ++ ROP_OP_TR(s, dstaddr, *src, transp); ++ dstaddr++; + src++; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + src += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, +- int dstpitch,int srcpitch, +- int bltwidth,int bltheight) ++ uint32_t dstaddr, ++ const uint8_t *src, ++ int dstpitch, ++ int srcpitch, ++ int bltwidth, ++ int bltheight) + { + int x,y; +- uint8_t p; ++ uint8_t transp = s->vga.gr[0x34]; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- p = *dst; +- ROP_OP(&p, *src); +- if (p != s->vga.gr[0x34]) *dst = p; +- dst--; ++ ROP_OP_TR(s, dstaddr, *src, transp); ++ dstaddr--; + src--; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + src += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, +- int dstpitch,int srcpitch, +- int bltwidth,int bltheight) ++ uint32_t dstaddr, ++ const uint8_t *src, ++ int dstpitch, ++ int srcpitch, ++ int bltwidth, ++ int bltheight) + { + int x,y; +- uint8_t p1, p2; ++ uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + +@@ -156,46 +196,35 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { +- p1 = *dst; +- p2 = *(dst+1); +- ROP_OP(&p1, *src); +- ROP_OP(&p2, *(src + 1)); +- if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { +- *dst = p1; +- *(dst+1) = p2; +- } +- dst+=2; +- src+=2; ++ ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp); ++ dstaddr += 2; ++ src += 2; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + src += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, +- uint8_t *dst,const uint8_t *src, +- int dstpitch,int srcpitch, +- int bltwidth,int bltheight) ++ uint32_t dstaddr, ++ const uint8_t *src, ++ int dstpitch, ++ int srcpitch, ++ int bltwidth, ++ int bltheight) + { + int x,y; +- uint8_t p1, p2; ++ uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { +- p1 = *(dst-1); +- p2 = *dst; +- ROP_OP(&p1, *(src - 1)); +- ROP_OP(&p2, *src); +- if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { +- *(dst-1) = p1; +- *dst = p2; +- } +- dst-=2; +- src-=2; ++ ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp); ++ dstaddr -= 2; ++ src -= 2; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + src += srcpitch; + } + } +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop2.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga_rop2.h 2017-05-10 15:48:20.602104562 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop2.h 2017-05-10 15:48:20.598104524 -0400 +@@ -23,27 +23,29 @@ + */ + + #if DEPTH == 8 +-#define PUTPIXEL() ROP_OP(&d[0], col) ++#define PUTPIXEL(s, a, c) ROP_OP(s, a, c) + #elif DEPTH == 16 +-#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) ++#define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c) + #elif DEPTH == 24 +-#define PUTPIXEL() ROP_OP(&d[0], col); \ +- ROP_OP(&d[1], (col >> 8)); \ +- ROP_OP(&d[2], (col >> 16)) ++#define PUTPIXEL(s, a, c) do { \ ++ ROP_OP(s, a, c); \ ++ ROP_OP(s, a + 1, (col >> 8)); \ ++ ROP_OP(s, a + 2, (col >> 16)); \ ++ } while (0) + #elif DEPTH == 32 +-#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) ++#define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c) + #else + #error unsupported DEPTH + #endif + + static void + glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) +- (CirrusVGAState * s, uint8_t * dst, +- const uint8_t * src, ++ (CirrusVGAState *s, uint32_t dstaddr, ++ const uint8_t *src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +- uint8_t *d; ++ uint32_t addr; + int x, y, pattern_y, pattern_pitch, pattern_x; + unsigned int col; + const uint8_t *src1; +@@ -63,7 +65,7 @@ glue(glue(glue(cirrus_patternfill_, ROP_ + pattern_y = s->cirrus_blt_srcaddr & 7; + for(y = 0; y < bltheight; y++) { + pattern_x = skipleft; +- d = dst + skipleft; ++ addr = dstaddr + skipleft; + src1 = src + pattern_y * pattern_pitch; + for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { + #if DEPTH == 8 +@@ -82,23 +84,23 @@ glue(glue(glue(cirrus_patternfill_, ROP_ + col = ((uint32_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 4) & 31; + #endif +- PUTPIXEL(); +- d += (DEPTH / 8); ++ PUTPIXEL(s, addr, col); ++ addr += (DEPTH / 8); + } + pattern_y = (pattern_y + 1) & 7; +- dst += dstpitch; ++ dstaddr += dstpitch; + } + } + + /* NOTE: srcpitch is ignored */ + static void + glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) +- (CirrusVGAState * s, uint8_t * dst, +- const uint8_t * src, ++ (CirrusVGAState *s, uint32_t dstaddr, ++ const uint8_t *src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +- uint8_t *d; ++ uint32_t addr; + int x, y; + unsigned bits, bits_xor; + unsigned int col; +@@ -123,7 +125,7 @@ glue(glue(glue(cirrus_colorexpand_transp + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++ ^ bits_xor; +- d = dst + dstskipleft; ++ addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; +@@ -131,24 +133,24 @@ glue(glue(glue(cirrus_colorexpand_transp + } + index = (bits & bitmask); + if (index) { +- PUTPIXEL(); ++ PUTPIXEL(s, addr, col); + } +- d += (DEPTH / 8); ++ addr += (DEPTH / 8); + bitmask >>= 1; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + } + } + + static void + glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) +- (CirrusVGAState * s, uint8_t * dst, +- const uint8_t * src, ++ (CirrusVGAState *s, uint32_t dstaddr, ++ const uint8_t *src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { + uint32_t colors[2]; +- uint8_t *d; ++ uint32_t addr; + int x, y; + unsigned bits; + unsigned int col; +@@ -161,29 +163,29 @@ glue(glue(glue(cirrus_colorexpand_, ROP_ + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++; +- d = dst + dstskipleft; ++ addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++; + } + col = colors[!!(bits & bitmask)]; +- PUTPIXEL(); +- d += (DEPTH / 8); ++ PUTPIXEL(s, addr, col); ++ addr += (DEPTH / 8); + bitmask >>= 1; + } +- dst += dstpitch; ++ dstaddr += dstpitch; + } + } + + static void + glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) +- (CirrusVGAState * s, uint8_t * dst, +- const uint8_t * src, ++ (CirrusVGAState *s, uint32_t dstaddr, ++ const uint8_t *src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +- uint8_t *d; ++ uint32_t addr; + int x, y, bitpos, pattern_y; + unsigned int bits, bits_xor; + unsigned int col; +@@ -207,28 +209,28 @@ glue(glue(glue(cirrus_colorexpand_patter + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y] ^ bits_xor; + bitpos = 7 - srcskipleft; +- d = dst + dstskipleft; ++ addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bits >> bitpos) & 1) { +- PUTPIXEL(); ++ PUTPIXEL(s, addr, col); + } +- d += (DEPTH / 8); ++ addr += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; +- dst += dstpitch; ++ dstaddr += dstpitch; + } + } + + static void + glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) +- (CirrusVGAState * s, uint8_t * dst, +- const uint8_t * src, ++ (CirrusVGAState *s, uint32_t dstaddr, ++ const uint8_t *src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { + uint32_t colors[2]; +- uint8_t *d; ++ uint32_t addr; + int x, y, bitpos, pattern_y; + unsigned int bits; + unsigned int col; +@@ -242,38 +244,37 @@ glue(glue(glue(cirrus_colorexpand_patter + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y]; + bitpos = 7 - srcskipleft; +- d = dst + dstskipleft; ++ addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + col = colors[(bits >> bitpos) & 1]; +- PUTPIXEL(); +- d += (DEPTH / 8); ++ PUTPIXEL(s, addr, col); ++ addr += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; +- dst += dstpitch; ++ dstaddr += dstpitch; + } + } + + static void + glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, +- uint8_t *dst, int dst_pitch, ++ uint32_t dstaddr, int dst_pitch, + int width, int height) + { +- uint8_t *d, *d1; ++ uint32_t addr; + uint32_t col; + int x, y; + + col = s->cirrus_blt_fgcol; + +- d1 = dst; + for(y = 0; y < height; y++) { +- d = d1; ++ addr = dstaddr; + for(x = 0; x < width; x += (DEPTH / 8)) { +- PUTPIXEL(); +- d += (DEPTH / 8); ++ PUTPIXEL(s, addr, col); ++ addr += (DEPTH / 8); + } +- d1 += dst_pitch; ++ dstaddr += dst_pitch; + } + } + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-7980-7.patch qemu-2.1+dfsg/debian/patches/CVE-2017-7980-7.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-7980-7.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-7980-7.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,444 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> + +From ffaf857778286ca54e3804432a2369a279e73aa7 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Wed, 15 Mar 2017 14:28:07 +0100 +Subject: [PATCH] cirrus: stop passing around src pointers in the blitter + +Does basically the same as "cirrus: stop passing around dst pointers in +the blitter", just for the src pointer instead of the dst pointer. + +For the src we have to care about cputovideo blits though and fetch the +data from s->cirrus_bltbuf instead of vga memory. The cirrus_src*() +helper functions handle that. + +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 1489584487-3489-1-git-send-email-kraxel@redhat.com +--- + hw/display/cirrus_vga.c | 61 +++++++++++++++++++++++++++++++++++--------- + hw/display/cirrus_vga_rop.h | 48 +++++++++++++++++----------------- + hw/display/cirrus_vga_rop2.h | 38 ++++++++++++++------------- + 3 files changed, 93 insertions(+), 54 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga.c 2017-05-10 15:48:25.734153557 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga.c 2017-05-10 15:48:25.730153519 -0400 +@@ -174,7 +174,7 @@ + + struct CirrusVGAState; + typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, +- uint32_t dstaddr, const uint8_t *src, ++ uint32_t dstaddr, uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight); + typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, +@@ -315,7 +315,7 @@ static bool blit_is_unsafe(struct Cirrus + } + + static void cirrus_bitblt_rop_nop(CirrusVGAState *s, +- uint32_t dstaddr, const uint8_t *src, ++ uint32_t dstaddr, uint32_t srcaddr, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) + { +@@ -327,6 +327,45 @@ static void cirrus_bitblt_fill_nop(Cirru + { + } + ++static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr) ++{ ++ if (s->cirrus_srccounter) { ++ /* cputovideo */ ++ return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)]; ++ } else { ++ /* videotovideo */ ++ return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask]; ++ } ++} ++ ++static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr) ++{ ++ uint16_t *src; ++ ++ if (s->cirrus_srccounter) { ++ /* cputovideo */ ++ src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1]; ++ } else { ++ /* videotovideo */ ++ src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1]; ++ } ++ return *src; ++} ++ ++static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr) ++{ ++ uint32_t *src; ++ ++ if (s->cirrus_srccounter) { ++ /* cputovideo */ ++ src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3]; ++ } else { ++ /* videotovideo */ ++ src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3]; ++ } ++ return *src; ++} ++ + #define ROP_NAME 0 + #define ROP_FN(d, s) 0 + #include "cirrus_vga_rop.h" +@@ -669,10 +708,10 @@ static void cirrus_invalidate_region(Cir + } + } + +-static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) ++static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s) + { + uint32_t patternsize; +- uint8_t *src; ++ bool videosrc = !s->cirrus_srccounter; + + if (videosrc) { + switch (s->vga.get_bpp(&s->vga)) { +@@ -693,16 +732,14 @@ static int cirrus_bitblt_common_patternc + if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) { + return 0; + } +- src = s->vga.vram_ptr + s->cirrus_blt_srcaddr; +- } else { +- src = s->cirrus_bltbuf; + } + + if (blit_is_unsafe(s, true)) { + return 0; + } + +- (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, src, ++ (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, ++ videosrc ? s->cirrus_blt_srcaddr : 0, + s->cirrus_blt_dstpitch, 0, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, +@@ -739,7 +776,7 @@ static int cirrus_bitblt_solidfill(Cirru + + static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) + { +- return cirrus_bitblt_common_patterncopy(s, true); ++ return cirrus_bitblt_common_patterncopy(s); + } + + static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) +@@ -789,7 +826,7 @@ static int cirrus_do_copy(CirrusVGAState + } + + (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, +- s->vga.vram_ptr + s->cirrus_blt_srcaddr, ++ s->cirrus_blt_srcaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + +@@ -832,7 +869,7 @@ static void cirrus_bitblt_cputovideo_nex + + if (s->cirrus_srccounter > 0) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { +- cirrus_bitblt_common_patterncopy(s, false); ++ cirrus_bitblt_common_patterncopy(s); + the_end: + s->cirrus_srccounter = 0; + cirrus_bitblt_reset(s); +@@ -840,7 +877,7 @@ static void cirrus_bitblt_cputovideo_nex + /* at least one scan line */ + do { + (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr, +- s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); ++ 0, 0, 0, s->cirrus_blt_width, 1); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, + s->cirrus_blt_width, 1); + s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga_rop.h 2017-05-10 15:48:25.734153557 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop.h 2017-05-10 15:48:25.734153557 -0400 +@@ -78,7 +78,7 @@ static inline void glue(rop_32_, ROP_NAM + static void + glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +@@ -93,19 +93,19 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(C + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- ROP_OP(s, dstaddr, *src); ++ ROP_OP(s, dstaddr, cirrus_src(s, srcaddr)); + dstaddr++; +- src++; ++ srcaddr++; + } + dstaddr += dstpitch; +- src += srcpitch; ++ srcaddr += srcpitch; + } + } + + static void + glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +@@ -114,19 +114,19 @@ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)( + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- ROP_OP(s, dstaddr, *src); ++ ROP_OP(s, dstaddr, cirrus_src(s, srcaddr)); + dstaddr--; +- src--; ++ srcaddr--; + } + dstaddr += dstpitch; +- src += srcpitch; ++ srcaddr += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, + uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, +@@ -143,19 +143,19 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- ROP_OP_TR(s, dstaddr, *src, transp); ++ ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp); + dstaddr++; +- src++; ++ srcaddr++; + } + dstaddr += dstpitch; +- src += srcpitch; ++ srcaddr += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, + uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, +@@ -167,19 +167,19 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_ + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { +- ROP_OP_TR(s, dstaddr, *src, transp); ++ ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp); + dstaddr--; +- src--; ++ srcaddr--; + } + dstaddr += dstpitch; +- src += srcpitch; ++ srcaddr += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, + uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, +@@ -196,19 +196,19 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { +- ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp); ++ ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp); + dstaddr += 2; +- src += 2; ++ srcaddr += 2; + } + dstaddr += dstpitch; +- src += srcpitch; ++ srcaddr += srcpitch; + } + } + + static void + glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, + uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, +@@ -220,12 +220,12 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_ + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { +- ROP_OP_TR_16(s, dstaddr, *(uint16_t *)src, transp); ++ ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp); + dstaddr -= 2; +- src -= 2; ++ srcaddr -= 2; + } + dstaddr += dstpitch; +- src += srcpitch; ++ srcaddr += srcpitch; + } + } + +Index: qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop2.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/display/cirrus_vga_rop2.h 2017-05-10 15:48:25.734153557 -0400 ++++ qemu-2.0.0+dfsg/hw/display/cirrus_vga_rop2.h 2017-05-10 15:48:25.734153557 -0400 +@@ -41,14 +41,14 @@ + static void + glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { + uint32_t addr; + int x, y, pattern_y, pattern_pitch, pattern_x; + unsigned int col; +- const uint8_t *src1; ++ uint32_t src1addr; + #if DEPTH == 24 + int skipleft = s->vga.gr[0x2f] & 0x1f; + #else +@@ -66,22 +66,24 @@ glue(glue(glue(cirrus_patternfill_, ROP_ + for(y = 0; y < bltheight; y++) { + pattern_x = skipleft; + addr = dstaddr + skipleft; +- src1 = src + pattern_y * pattern_pitch; ++ src1addr = srcaddr + pattern_y * pattern_pitch; + for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { + #if DEPTH == 8 +- col = src1[pattern_x]; ++ col = cirrus_src(s, src1addr + pattern_x); + pattern_x = (pattern_x + 1) & 7; + #elif DEPTH == 16 +- col = ((uint16_t *)(src1 + pattern_x))[0]; ++ col = cirrus_src16(s, src1addr + pattern_x); + pattern_x = (pattern_x + 2) & 15; + #elif DEPTH == 24 + { +- const uint8_t *src2 = src1 + pattern_x * 3; +- col = src2[0] | (src2[1] << 8) | (src2[2] << 16); ++ uint32_t src2addr = src1addr + pattern_x * 3; ++ col = cirrus_src(s, src2addr) | ++ (cirrus_src(s, src2addr + 1) << 8) | ++ (cirrus_src(s, src2addr + 2) << 16); + pattern_x = (pattern_x + 1) & 7; + } + #else +- col = ((uint32_t *)(src1 + pattern_x))[0]; ++ col = cirrus_src32(s, src1addr + pattern_x); + pattern_x = (pattern_x + 4) & 31; + #endif + PUTPIXEL(s, addr, col); +@@ -96,7 +98,7 @@ glue(glue(glue(cirrus_patternfill_, ROP_ + static void + glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +@@ -124,12 +126,12 @@ glue(glue(glue(cirrus_colorexpand_transp + + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; +- bits = *src++ ^ bits_xor; ++ bits = cirrus_src(s, srcaddr++) ^ bits_xor; + addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; +- bits = *src++ ^ bits_xor; ++ bits = cirrus_src(s, srcaddr++) ^ bits_xor; + } + index = (bits & bitmask); + if (index) { +@@ -145,7 +147,7 @@ glue(glue(glue(cirrus_colorexpand_transp + static void + glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +@@ -162,12 +164,12 @@ glue(glue(glue(cirrus_colorexpand_, ROP_ + colors[1] = s->cirrus_blt_fgcol; + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; +- bits = *src++; ++ bits = cirrus_src(s, srcaddr++); + addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; +- bits = *src++; ++ bits = cirrus_src(s, srcaddr++); + } + col = colors[!!(bits & bitmask)]; + PUTPIXEL(s, addr, col); +@@ -181,7 +183,7 @@ glue(glue(glue(cirrus_colorexpand_, ROP_ + static void + glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +@@ -207,7 +209,7 @@ glue(glue(glue(cirrus_colorexpand_patter + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { +- bits = src[pattern_y] ^ bits_xor; ++ bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor; + bitpos = 7 - srcskipleft; + addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { +@@ -225,7 +227,7 @@ glue(glue(glue(cirrus_colorexpand_patter + static void + glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, uint32_t dstaddr, +- const uint8_t *src, ++ uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) + { +@@ -242,7 +244,7 @@ glue(glue(glue(cirrus_colorexpand_patter + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { +- bits = src[pattern_y]; ++ bits = cirrus_src(s, srcaddr + pattern_y); + bitpos = 7 - srcskipleft; + addr = dstaddr + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-8086.patch qemu-2.1+dfsg/debian/patches/CVE-2017-8086.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-8086.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-8086.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,34 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.34 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 861348 + +Backport of: + +From 4ffcdef4277a91af15a3c09f7d16af072c29f3f2 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liq3ea@gmail.com> +Date: Fri, 7 Apr 2017 03:48:52 -0700 +Subject: [PATCH] 9pfs: xattr: fix memory leak in v9fs_list_xattr + +Free 'orig_value' in error path. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Signed-off-by: Greg Kurz <groug@kaod.org> +--- + hw/9pfs/9p-xattr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c +index eec160b..d05c1a1 100644 +--- a/hw/9pfs/virtio-9p-xattr.c ++++ b/hw/9pfs/virtio-9p-xattr.c +@@ -108,6 +108,7 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, + g_free(name); + close_preserve_errno(dirfd); + if (xattr_len < 0) { ++ g_free(orig_value); + return -1; + } + +-- +1.8.3.1 + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-8112.patch qemu-2.1+dfsg/debian/patches/CVE-2017-8112.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-8112.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-8112.patch 2018-07-26 16:49:17.000000000 +0200 @@ -0,0 +1,35 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 861351 + +From f68826989cd4d1217797251339579c57b3c0934e Mon Sep 17 00:00:00 2001 +From: P J P <ppandit@redhat.com> +Date: Tue, 25 Apr 2017 18:36:23 +0530 +Subject: [PATCH] vmw_pvscsi: check message ring page count at initialisation + +A guest could set the message ring page count to zero, resulting in +infinite loop. Add check to avoid it. + +Reported-by: YY Z <bigbird475958471@gmail.com> +Signed-off-by: P J P <ppandit@redhat.com> +Message-Id: <20170425130623.3649-1-ppandit@redhat.com> +Reviewed-by: Dmitry Fleytman <dmitry@daynix.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/vmw_pvscsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu/hw/scsi/vmw_pvscsi.c +=================================================================== +--- qemu.orig/hw/scsi/vmw_pvscsi.c ++++ qemu/hw/scsi/vmw_pvscsi.c +@@ -174,6 +174,9 @@ pvscsi_ring_init_msg(PVSCSIRingInfo *m, + uint32_t len_log2; + uint32_t ring_size; + ++ if (!ri->numPages || ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) { ++ return -1; ++ } + ring_size = ri->numPages * PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE; + len_log2 = pvscsi_log2(ring_size - 1); + diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-8309-audio-release-capture-buffers.patch qemu-2.1+dfsg/debian/patches/CVE-2017-8309-audio-release-capture-buffers.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-8309-audio-release-capture-buffers.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-8309-audio-release-capture-buffers.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,32 @@ +Origin: debian, 1.1.2+dfsg-6+deb7u23 +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 862280 + +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Fri, 28 Apr 2017 09:56:12 +0200 +Subject: CVE-2017-8309: audio: release capture buffers + +AUD_add_capture() allocates two buffers which are never released. +Add the missing calls to AUD_del_capture(). + +Impact: Allows vnc clients to exhaust host memory by repeatedly +starting and stopping audio capture. + +Upstream-Commit: 3268a845f41253fb55852a8429c32b50f36f349a +--- + audio/audio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/audio/audio.c b/audio/audio.c +index 583ee51..cf9c80d 100644 +--- a/audio/audio.c ++++ b/audio/audio.c +@@ -2052,6 +2052,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) + sw = sw1; + } + QLIST_REMOVE (cap, entries); ++ g_free (cap->hw.mix_buf); ++ g_free (cap->buf); + g_free (cap); + } + return; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-8379-1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-8379-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-8379-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-8379-1.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,91 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/1:2.5+dfsg-5ubuntu10.31 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 862289 + +From fa18f36a461984eae50ab957e47ec78dae3c14fc Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann <kraxel@redhat.com> +Date: Fri, 28 Apr 2017 10:42:37 +0200 +Subject: [PATCH] input: limit kbd queue depth + +Apply a limit to the number of items we accept into the keyboard queue. + +Impact: Without this limit vnc clients can exhaust host memory by +sending keyboard events faster than qemu feeds them to the guest. + +Fixes: CVE-2017-8379 +Cc: P J P <ppandit@redhat.com> +Cc: Huawei PSIRT <PSIRT@huawei.com> +Reported-by: jiangxin1@huawei.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +Message-id: 20170428084237.23960-1-kraxel@redhat.com +--- + ui/input.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +Index: qemu/ui/input.c +=================================================================== +--- qemu.orig/ui/input.c ++++ qemu/ui/input.c +@@ -38,6 +38,8 @@ static QTAILQ_HEAD(QemuInputEventQueueHe + QTAILQ_HEAD_INITIALIZER(kbd_queue); + static QEMUTimer *kbd_timer; + static uint32_t kbd_default_delay_ms = 10; ++static uint32_t queue_count; ++static uint32_t queue_limit = 1024; + + QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev, + QemuInputHandler *handler) +@@ -218,6 +220,7 @@ static void qemu_input_queue_process(voi + break; + } + QTAILQ_REMOVE(queue, item, node); ++ queue_count--; + g_free(item); + } + } +@@ -232,6 +235,7 @@ static void qemu_input_queue_delay(struc + item->delay_ms = delay_ms; + item->timer = timer; + QTAILQ_INSERT_TAIL(queue, item, node); ++ queue_count++; + + if (start_timer) { + timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +@@ -248,6 +252,7 @@ static void qemu_input_queue_event(struc + item->src = src; + item->evt = evt; + QTAILQ_INSERT_TAIL(queue, item, node); ++ queue_count++; + } + + static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue) +@@ -256,6 +261,7 @@ static void qemu_input_queue_sync(struct + + item->type = QEMU_INPUT_QUEUE_SYNC; + QTAILQ_INSERT_TAIL(queue, item, node); ++ queue_count++; + } + + void qemu_input_event_send(QemuConsole *src, InputEvent *evt) +@@ -321,7 +327,7 @@ void qemu_input_event_send_key(QemuConso + qemu_input_event_send(src, evt); + qemu_input_event_sync(); + qapi_free_InputEvent(evt); +- } else { ++ } else if (queue_count < queue_limit) { + qemu_input_queue_event(&kbd_queue, src, evt); + qemu_input_queue_sync(&kbd_queue); + } +@@ -349,8 +355,10 @@ void qemu_input_event_send_key_delay(uin + kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process, + &kbd_queue); + } +- qemu_input_queue_delay(&kbd_queue, kbd_timer, +- delay_ms ? delay_ms : kbd_default_delay_ms); ++ if (queue_count < queue_limit) { ++ qemu_input_queue_delay(&kbd_queue, kbd_timer, ++ delay_ms ? delay_ms : kbd_default_delay_ms); ++ } + } + + InputEvent *qemu_input_event_new_btn(InputButton btn, bool down) diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-8379-2.patch qemu-2.1+dfsg/debian/patches/CVE-2017-8379-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-8379-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-8379-2.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,51 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/1:2.5+dfsg-5ubuntu10.31 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 862289 + +From 05c6638b203fd7d8bbfa88ac6e6198e32ed0506f Mon Sep 17 00:00:00 2001 +From: =?utf8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com> +Date: Tue, 25 Apr 2017 17:05:20 +0400 +Subject: [PATCH] input: don't queue delay if paused +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +qemu_input_event_send() discards key event when the guest is paused, +but not the delay. + +The delay ends up in the input queue, and qemu_input_event_send_key() +will further fill the queue with upcoming events. + +VNC uses qemu_input_event_send_key_delay(), not SPICE, which results +in a different input behaviour on pause: VNC will queue the events +(except the first that is discarded), SPICE will discard all events. + +Don't queue delay if paused, and provide same behaviour on SPICE and +VNC clients on resume (and potentially avoid over-allocating the +buffer queue) + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=1444326 + +Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> +Message-id: 20170425130520.31819-1-marcandre.lureau@redhat.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + ui/input.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Index: qemu-2.5+dfsg/ui/input.c +=================================================================== +--- qemu-2.5+dfsg.orig/ui/input.c 2017-05-10 10:08:03.231185049 -0400 ++++ qemu-2.5+dfsg/ui/input.c 2017-05-10 10:08:03.211184858 -0400 +@@ -404,6 +404,10 @@ void qemu_input_event_send_key_qcode(Qem + + void qemu_input_event_send_key_delay(uint32_t delay_ms) + { ++ if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { ++ return; ++ } ++ + if (!kbd_timer) { + kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process, + &kbd_queue); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9330.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9330.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9330.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9330.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,34 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 863943 + +Backport of: + +From 26f670a244982335cc08943fb1ec099a2c81e42d Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Tue, 7 Feb 2017 03:15:03 -0800 +Subject: [PATCH] usb: ohci: fix error return code in servicing iso td + +It should return 1 if an error occurs when reading iso td. +This will avoid an infinite loop issue in ohci_service_ed_list. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-id: 5899ac3e.1033240a.944d5.9a2d@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/usb/hcd-ohci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-2.0.0+dfsg/hw/usb/hcd-ohci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/hcd-ohci.c 2017-08-22 10:19:26.528462419 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/hcd-ohci.c 2017-08-22 10:19:26.500462418 -0400 +@@ -727,7 +727,7 @@ static int ohci_service_iso_td(OHCIState + if (ohci_read_iso_td(ohci, addr, &iso_td)) { + printf("usb-ohci: ISO_TD read error at %x\n", addr); + ohci_die(ohci); +- return 0; ++ return 1; + } + + starting_frame = OHCI_BM(iso_td.flags, TD_SF); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9373-1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9373-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9373-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9373-1.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,54 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 864216 + +Backport of: + +From c9f086418a255f386e1c4d2c1418c032eb349537 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liq3ea@gmail.com> +Date: Wed, 15 Mar 2017 20:50:14 -0400 +Subject: [PATCH] ide: core: add cleanup function + +As the pci ahci can be hotplug and unplug, in the ahci unrealize +function it should free all the resource once allocated in the +realized function. This patch add ide_exit to free the resource. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-id: 1488449293-80280-3-git-send-email-liqiang6-s@360.cn +Signed-off-by: John Snow <jsnow@redhat.com> +--- + hw/ide/core.c | 8 ++++++++ + include/hw/ide/internal.h | 1 + + 2 files changed, 9 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/ide/core.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/ide/core.c 2017-08-22 10:19:58.548463912 -0400 ++++ qemu-2.0.0+dfsg/hw/ide/core.c 2017-08-22 10:19:58.528463911 -0400 +@@ -2246,6 +2246,14 @@ void ide_init2(IDEBus *bus, qemu_irq irq + bus->dma = &ide_dma_nop; + } + ++void ide_exit(IDEState *s) ++{ ++ timer_del(s->sector_write_timer); ++ timer_free(s->sector_write_timer); ++ qemu_vfree(s->smart_selftest_data); ++ qemu_vfree(s->io_buffer); ++} ++ + static const MemoryRegionPortio ide_portio_list[] = { + { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, + { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew }, +Index: qemu-2.0.0+dfsg/hw/ide/internal.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/ide/internal.h 2017-08-22 10:19:58.548463912 -0400 ++++ qemu-2.0.0+dfsg/hw/ide/internal.h 2017-08-22 10:19:58.532463911 -0400 +@@ -554,6 +554,7 @@ int ide_init_drive(IDEState *s, BlockDri + uint32_t cylinders, uint32_t heads, uint32_t secs, + int chs_trans); + void ide_init2(IDEBus *bus, qemu_irq irq); ++void ide_exit(IDEState *s); + void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); + + void ide_exec_cmd(IDEBus *bus, uint32_t val); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9373-2.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9373-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9373-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9373-2.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,43 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 864216 + +Backport of: + +From d68f0f778e7f4fbd674627274267f269e40f0b04 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liq3ea@gmail.com> +Date: Wed, 15 Mar 2017 20:50:14 -0400 +Subject: [PATCH] ide: ahci: call cleanup function in ahci unit + +This can avoid memory leak when hotunplug the ahci device. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-id: 1488449293-80280-4-git-send-email-liqiang6-s@360.cn +Signed-off-by: John Snow <jsnow@redhat.com> +--- + hw/ide/ahci.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/ide/ahci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/ide/ahci.c 2017-08-22 10:20:33.300465533 -0400 ++++ qemu-2.0.0+dfsg/hw/ide/ahci.c 2017-08-22 10:21:18.236467628 -0400 +@@ -1211,6 +1211,18 @@ void ahci_init(AHCIState *s, DeviceState + + void ahci_uninit(AHCIState *s) + { ++ int i, j; ++ ++ for (i = 0; i < s->ports; i++) { ++ AHCIDevice *ad = &s->dev[i]; ++ ++ for (j = 0; j < 2; j++) { ++ IDEState *s = &ad->port.ifs[j]; ++ ++ ide_exit(s); ++ } ++ } ++ + memory_region_destroy(&s->mem); + memory_region_destroy(&s->idp); + g_free(s->dev); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9374.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9374.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9374.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9374.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,81 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 864568 + +Backport of: + +From d710e1e7bd3d5bfc26b631f02ae87901ebe646b0 Mon Sep 17 00:00:00 2001 +From: Li Qiang <liqiang6-s@360.cn> +Date: Tue, 7 Feb 2017 18:42:55 -0800 +Subject: [PATCH] usb: ehci: fix memory leak in ehci + +In usb_ehci_init function, it initializes 's->ipacket', but there +is no corresponding function to free this. As the ehci can be hotplug +and unplug, this will leak host memory leak. In order to make the +hierarchy clean, we should add a ehci pci finalize function, then call +the clean function in ehci device. + +Signed-off-by: Li Qiang <liqiang6-s@360.cn> +Message-id: 589a85b8.3c2b9d0a.b8e6.1434@mx.google.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> +--- + hw/usb/hcd-ehci-pci.c | 9 +++++++++ + hw/usb/hcd-ehci.c | 5 +++++ + hw/usb/hcd-ehci.h | 1 + + 3 files changed, 15 insertions(+) + +Index: qemu-2.0.0+dfsg/hw/usb/hcd-ehci-pci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/hcd-ehci-pci.c 2017-08-22 10:22:04.788469799 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/hcd-ehci-pci.c 2017-08-22 10:22:42.276471547 -0400 +@@ -84,6 +84,14 @@ static void usb_ehci_pci_init(Object *ob + usb_ehci_init(s, DEVICE(obj)); + } + ++static void usb_ehci_pci_finalize(Object *obj) ++{ ++ EHCIPCIState *i = PCI_EHCI(obj); ++ EHCIState *s = &i->ehci; ++ ++ usb_ehci_finalize(s); ++} ++ + static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr, + uint32_t val, int l) + { +@@ -133,6 +141,7 @@ static const TypeInfo ehci_pci_type_info + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(EHCIPCIState), + .instance_init = usb_ehci_pci_init, ++ .instance_finalize = usb_ehci_pci_finalize, + .abstract = true, + .class_init = ehci_class_init, + }; +Index: qemu-2.0.0+dfsg/hw/usb/hcd-ehci.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/hcd-ehci.c 2017-08-22 10:22:04.788469799 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/hcd-ehci.c 2017-08-22 10:22:04.768469798 -0400 +@@ -2593,6 +2593,11 @@ void usb_ehci_init(EHCIState *s, DeviceS + &s->mem_ports); + } + ++void usb_ehci_finalize(EHCIState *s) ++{ ++ usb_packet_cleanup(&s->ipacket); ++} ++ + /* + * vim: expandtab ts=4 + */ +Index: qemu-2.0.0+dfsg/hw/usb/hcd-ehci.h +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/usb/hcd-ehci.h 2017-08-22 10:22:04.788469799 -0400 ++++ qemu-2.0.0+dfsg/hw/usb/hcd-ehci.h 2017-08-22 10:22:04.768469798 -0400 +@@ -321,6 +321,7 @@ struct EHCIState { + extern const VMStateDescription vmstate_ehci; + + void usb_ehci_init(EHCIState *s, DeviceState *dev); ++void usb_ehci_finalize(EHCIState *s); + void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp); + + #define TYPE_PCI_EHCI "pci-ehci-usb" diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-1.patch 2018-07-26 19:10:42.000000000 +0200 @@ -0,0 +1,102 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +Backport of: + +From 660174fc1b346803b3f1d7c260e2a36329b66435 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 16:45:16 +0200 +Subject: [PATCH] megasas: add qtest + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + tests/Makefile.include | 3 +++ + tests/megasas-test.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 54 insertions(+) + create mode 100644 tests/megasas-test.c + +Index: qemu/tests/Makefile +=================================================================== +--- qemu.orig/tests/Makefile ++++ qemu/tests/Makefile +@@ -121,12 +121,14 @@ check-qtest-pci-y += tests/tpci200-test$ + gcov-files-pci-y += hw/ipack/tpci200.c + check-qtest-pci-y += $(check-qtest-ipack-y) + gcov-files-pci-y += $(gcov-files-ipack-y) ++check-qtest-pci-y += tests/megasas-test$(EXESUF) ++gcov-files-pci-y += hw/scsi/megasas.c + check-qtest-pci-y += tests/display-vga-test$(EXESUF) + gcov-files-pci-y += hw/display/vga.c + gcov-files-pci-y += hw/display/cirrus_vga.c + gcov-files-pci-y += hw/display/vga-pci.c + check-qtest-pci-y += tests/intel-hda-test$(EXESUF) +-gcov-files-pci-y += hw/audio/intel-hda.c hw/audio/hda-codec.c ++GCOV-files-pci-y += hw/audio/intel-hda.c hw/audio/hda-codec.c + + check-qtest-i386-y = tests/endianness-test$(EXESUF) + check-qtest-i386-y += tests/fdc-test$(EXESUF) +@@ -339,6 +341,7 @@ tests/usb-hcd-ehci-test$(EXESUF): tests/ + tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) + tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o + tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a ++tests/megasas-test$(EXESUF): tests/megasas-test.o $(libqos-spapr-obj-y) $(libqos-pc-obj-y) + + ifeq ($(CONFIG_POSIX),y) + LIBS += -lutil +Index: qemu/tests/megasas-test.c +=================================================================== +--- /dev/null ++++ qemu/tests/megasas-test.c +@@ -0,0 +1,51 @@ ++/* ++ * QTest testcase for LSI MegaRAID ++ * ++ * Copyright (c) 2017 Red Hat Inc. ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#include "qemu/osdep.h" ++#include "libqtest.h" ++#include "qemu/bswap.h" ++#include "libqos/libqos-pc.h" ++#include "libqos/libqos-spapr.h" ++ ++static QOSState *qmegasas_start(const char *extra_opts) ++{ ++ const char *arch = qtest_get_arch(); ++ const char *cmd = "-drive id=hd0,if=none,file=null-co://,format=raw " ++ "-device megasas,id=scsi0,addr=04.0 " ++ "-device scsi-hd,bus=scsi0.0,drive=hd0 %s"; ++ ++ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { ++ return qtest_pc_boot(cmd, extra_opts ? : ""); ++ } ++ ++ g_printerr("virtio-scsi tests are only available on x86 or ppc64\n"); ++ exit(EXIT_FAILURE); ++} ++ ++static void qmegasas_stop(QOSState *qs) ++{ ++ qtest_shutdown(qs); ++} ++ ++/* Tests only initialization so far. TODO: Replace with functional tests */ ++static void pci_nop(void) ++{ ++ QOSState *qs; ++ ++ qs = qmegasas_start(NULL); ++ qmegasas_stop(qs); ++} ++ ++int main(int argc, char **argv) ++{ ++ g_test_init(&argc, &argv, NULL); ++ qtest_add_func("/megasas/pci/nop", pci_nop); ++ ++ return g_test_run(); ++} diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-2.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-2.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-2.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,34 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +From 134550bf81a026e18cf58b81e2c2cceaf516f92e Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 17:18:39 +0200 +Subject: [PATCH] megasas: do not read sense length more than once from frame + +Avoid TOC-TOU bugs depending on how the compiler behaves. + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +Index: qemu/hw/scsi/megasas.c +=================================================================== +--- qemu.orig/hw/scsi/megasas.c ++++ qemu/hw/scsi/megasas.c +@@ -297,9 +297,11 @@ static int megasas_build_sense(MegasasCm + PCIDevice *pcid = PCI_DEVICE(cmd->state); + uint32_t pa_hi = 0, pa_lo; + hwaddr pa; ++ int frame_sense_len; + +- if (sense_len > cmd->frame->header.sense_len) { +- sense_len = cmd->frame->header.sense_len; ++ frame_sense_len = cmd->frame->header.sense_len; ++ if (sense_len > frame_sense_len) { ++ sense_len = frame_sense_len; + } + if (sense_len) { + pa_lo = le32_to_cpu(cmd->frame->pass.sense_addr_lo); diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-3.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-3.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-3.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-3.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,41 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +From 24c0c77af515acbf0f9705e8096f33ef24d37430 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 17:18:57 +0200 +Subject: [PATCH] megasas: do not read iovec count more than once from frame + +Avoid TOC-TOU bugs depending on how the compiler behaves. + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/scsi/megasas.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/scsi/megasas.c 2017-08-22 12:28:37.844823873 -0400 ++++ qemu-2.0.0+dfsg/hw/scsi/megasas.c 2017-08-22 12:28:37.844823873 -0400 +@@ -632,15 +632,16 @@ out: + static int megasas_map_dcmd(MegasasState *s, MegasasCmd *cmd) + { + dma_addr_t iov_pa, iov_size; ++ int iov_count; + + cmd->flags = le16_to_cpu(cmd->frame->header.flags); +- if (!cmd->frame->header.sge_count) { ++ iov_count = cmd->frame->header.sge_count; ++ if (!iov_count) { + trace_megasas_dcmd_zero_sge(cmd->index); + cmd->iov_size = 0; + return 0; +- } else if (cmd->frame->header.sge_count > 1) { +- trace_megasas_dcmd_invalid_sge(cmd->index, +- cmd->frame->header.sge_count); ++ } else if (iov_count > 1) { ++ trace_megasas_dcmd_invalid_sge(cmd->index, iov_count); + cmd->iov_size = 0; + return -EINVAL; + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-4.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-4.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-4.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-4.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,119 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +Backport of: + +From 5104fac8539eaf155fc6de93e164be43e1e62242 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 17:18:23 +0200 +Subject: [PATCH] megasas: do not read DCMD opcode more than once from frame + +Avoid TOC-TOU bugs by storing the DCMD opcode in the MegasasCmd + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 25 +++++++++++-------------- + 1 file changed, 11 insertions(+), 14 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/scsi/megasas.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/scsi/megasas.c 2017-08-22 12:28:43.408824132 -0400 ++++ qemu-2.0.0+dfsg/hw/scsi/megasas.c 2017-08-22 12:28:43.408824132 -0400 +@@ -60,6 +60,7 @@ typedef struct MegasasCmd { + + hwaddr pa; + hwaddr pa_size; ++ uint32_t dcmd_opcode; + union mfi_frame *frame; + SCSIRequest *req; + QEMUSGList qsg; +@@ -496,6 +497,7 @@ static MegasasCmd *megasas_enqueue_frame + } + } + cmd->count = count; ++ cmd->dcmd_opcode = -1; + s->busy++; + + trace_megasas_qf_enqueue(cmd->index, cmd->count, cmd->context, +@@ -1461,22 +1463,21 @@ static const struct dcmd_cmd_tbl_t { + + static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd) + { +- int opcode; + int retval = 0; + size_t len; + const struct dcmd_cmd_tbl_t *cmdptr = dcmd_cmd_tbl; + +- opcode = le32_to_cpu(cmd->frame->dcmd.opcode); +- trace_megasas_handle_dcmd(cmd->index, opcode); ++ cmd->dcmd_opcode = le32_to_cpu(cmd->frame->dcmd.opcode); ++ trace_megasas_handle_dcmd(cmd->index, cmd->dcmd_opcode); + if (megasas_map_dcmd(s, cmd) < 0) { + return MFI_STAT_MEMORY_NOT_AVAILABLE; + } +- while (cmdptr->opcode != -1 && cmdptr->opcode != opcode) { ++ while (cmdptr->opcode != -1 && cmdptr->opcode != cmd->dcmd_opcode) { + cmdptr++; + } + len = cmd->iov_size; + if (cmdptr->opcode == -1) { +- trace_megasas_dcmd_unhandled(cmd->index, opcode, len); ++ trace_megasas_dcmd_unhandled(cmd->index, cmd->dcmd_opcode, len); + retval = megasas_dcmd_dummy(s, cmd); + } else { + trace_megasas_dcmd_enter(cmd->index, cmdptr->desc, len); +@@ -1491,14 +1492,13 @@ static int megasas_handle_dcmd(MegasasSt + static int megasas_finish_internal_dcmd(MegasasCmd *cmd, + SCSIRequest *req) + { +- int opcode; + int retval = MFI_STAT_OK; + int lun = req->lun; + +- opcode = le32_to_cpu(cmd->frame->dcmd.opcode); + scsi_req_unref(req); +- trace_megasas_dcmd_internal_finish(cmd->index, opcode, lun); +- switch (opcode) { ++ ++ trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun); ++ switch (cmd->dcmd_opcode) { + case MFI_DCMD_PD_GET_INFO: + retval = megasas_pd_get_info_submit(req->dev, lun, cmd); + break; +@@ -1506,7 +1506,7 @@ static int megasas_finish_internal_dcmd( + retval = megasas_ld_get_info_submit(req->dev, lun, cmd); + break; + default: +- trace_megasas_dcmd_internal_invalid(cmd->index, opcode); ++ trace_megasas_dcmd_internal_invalid(cmd->index, cmd->dcmd_opcode); + retval = MFI_STAT_INVALID_DCMD; + break; + } +@@ -1728,7 +1728,6 @@ static void megasas_xfer_complete(SCSIRe + { + MegasasCmd *cmd = req->hba_private; + uint8_t *buf; +- uint32_t opcode; + + trace_megasas_io_complete(cmd->index, len); + +@@ -1738,8 +1737,7 @@ static void megasas_xfer_complete(SCSIRe + } + + buf = scsi_req_get_buf(req); +- opcode = le32_to_cpu(cmd->frame->dcmd.opcode); +- if (opcode == MFI_DCMD_PD_GET_INFO && cmd->iov_buf) { ++ if (cmd->dcmd_opcode == MFI_DCMD_PD_GET_INFO && cmd->iov_buf) { + struct mfi_pd_info *info = cmd->iov_buf; + + if (info->inquiry_data[0] == 0x7f) { +@@ -1750,7 +1748,7 @@ static void megasas_xfer_complete(SCSIRe + memcpy(info->vpd_page83, buf, len); + } + scsi_req_continue(req); +- } else if (opcode == MFI_DCMD_LD_GET_INFO) { ++ } else if (cmd->dcmd_opcode == MFI_DCMD_LD_GET_INFO) { + struct mfi_ld_info *info = cmd->iov_buf; + + if (cmd->iov_buf) { diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-5.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-5.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-5.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-5.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,227 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +Backport of: + +From 36c327a69d723571f02a7691631667cdb1865ee1 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 17:23:13 +0200 +Subject: [PATCH] megasas: do not read command more than once from frame + +Avoid TOC-TOU bugs by passing the frame_cmd down, and checking +cmd->dcmd_opcode instead of cmd->frame->header.frame_cmd. + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 60 +++++++++++++++++++++++-------------------------------- + 1 file changed, 25 insertions(+), 35 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/scsi/megasas.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/scsi/megasas.c 2017-08-22 12:28:54.104824631 -0400 ++++ qemu-2.0.0+dfsg/hw/scsi/megasas.c 2017-08-22 12:29:16.792825689 -0400 +@@ -1490,7 +1490,7 @@ static int megasas_handle_dcmd(MegasasSt + } + + static int megasas_finish_internal_dcmd(MegasasCmd *cmd, +- SCSIRequest *req) ++ SCSIRequest *req, size_t resid) + { + int retval = MFI_STAT_OK; + int lun = req->lun; +@@ -1498,6 +1498,7 @@ static int megasas_finish_internal_dcmd( + scsi_req_unref(req); + + trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun); ++ cmd->iov_size -= resid; + switch (cmd->dcmd_opcode) { + case MFI_DCMD_PD_GET_INFO: + retval = megasas_pd_get_info_submit(req->dev, lun, cmd); +@@ -1550,12 +1551,13 @@ static int megasas_enqueue_req(MegasasCm + } + + static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd, +- bool is_logical) ++ int frame_cmd) + { + uint8_t *cdb; + int len; + bool is_write; + struct SCSIDevice *sdev = NULL; ++ bool is_logical = (frame_cmd == MFI_CMD_LD_SCSI_IO); + + cdb = cmd->frame->pass.cdb; + +@@ -1563,7 +1565,7 @@ static int megasas_handle_scsi(MegasasSt + if (cmd->frame->header.target_id >= MFI_MAX_LD || + cmd->frame->header.lun_id != 0) { + trace_megasas_scsi_target_not_present( +- mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical, ++ mfi_frame_desc[frame_cmd], is_logical, + cmd->frame->header.target_id, cmd->frame->header.lun_id); + return MFI_STAT_DEVICE_NOT_FOUND; + } +@@ -1573,19 +1575,20 @@ static int megasas_handle_scsi(MegasasSt + + cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len); + trace_megasas_handle_scsi(mfi_frame_desc[cmd->frame->header.frame_cmd], +- is_logical, cmd->frame->header.target_id, ++ trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical, ++ cmd->frame->header.target_id, + cmd->frame->header.lun_id, sdev, cmd->iov_size); + + if (!sdev || (megasas_is_jbod(s) && is_logical)) { + trace_megasas_scsi_target_not_present( +- mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical, ++ mfi_frame_desc[frame_cmd], is_logical, + cmd->frame->header.target_id, cmd->frame->header.lun_id); + return MFI_STAT_DEVICE_NOT_FOUND; + } + + if (cmd->frame->header.cdb_len > 16) { + trace_megasas_scsi_invalid_cdb_len( +- mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical, ++ mfi_frame_desc[frame_cmd], is_logical, + cmd->frame->header.target_id, cmd->frame->header.lun_id, + cmd->frame->header.cdb_len); + megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); +@@ -1605,7 +1608,7 @@ static int megasas_handle_scsi(MegasasSt + cmd->frame->header.lun_id, cdb, cmd); + if (!cmd->req) { + trace_megasas_scsi_req_alloc_failed( +- mfi_frame_desc[cmd->frame->header.frame_cmd], ++ mfi_frame_desc[frame_cmd], + cmd->frame->header.target_id, cmd->frame->header.lun_id); + megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); + cmd->frame->header.scsi_status = BUSY; +@@ -1627,11 +1630,11 @@ static int megasas_handle_scsi(MegasasSt + return MFI_STAT_INVALID_STATUS; + } + +-static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd) ++static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd) + { + uint32_t lba_count, lba_start_hi, lba_start_lo; + uint64_t lba_start; +- bool is_write = (cmd->frame->header.frame_cmd == MFI_CMD_LD_WRITE); ++ bool is_write = (frame_cmd == MFI_CMD_LD_WRITE); + uint8_t cdb[16]; + int len; + struct SCSIDevice *sdev = NULL; +@@ -1648,20 +1651,20 @@ static int megasas_handle_io(MegasasStat + } + + trace_megasas_handle_io(cmd->index, +- mfi_frame_desc[cmd->frame->header.frame_cmd], ++ mfi_frame_desc[frame_cmd], + cmd->frame->header.target_id, + cmd->frame->header.lun_id, + (unsigned long)lba_start, (unsigned long)lba_count); + if (!sdev) { + trace_megasas_io_target_not_present(cmd->index, +- mfi_frame_desc[cmd->frame->header.frame_cmd], ++ mfi_frame_desc[frame_cmd], + cmd->frame->header.target_id, cmd->frame->header.lun_id); + return MFI_STAT_DEVICE_NOT_FOUND; + } + + if (cmd->frame->header.cdb_len > 16) { + trace_megasas_scsi_invalid_cdb_len( +- mfi_frame_desc[cmd->frame->header.frame_cmd], 1, ++ mfi_frame_desc[frame_cmd], 1, + cmd->frame->header.target_id, cmd->frame->header.lun_id, + cmd->frame->header.cdb_len); + megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); +@@ -1683,7 +1686,7 @@ static int megasas_handle_io(MegasasStat + cmd->frame->header.lun_id, cdb, cmd); + if (!cmd->req) { + trace_megasas_scsi_req_alloc_failed( +- mfi_frame_desc[cmd->frame->header.frame_cmd], ++ mfi_frame_desc[frame_cmd], + cmd->frame->header.target_id, cmd->frame->header.lun_id); + megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); + cmd->frame->header.scsi_status = BUSY; +@@ -1701,23 +1704,11 @@ static int megasas_handle_io(MegasasStat + return MFI_STAT_INVALID_STATUS; + } + +-static int megasas_finish_internal_command(MegasasCmd *cmd, +- SCSIRequest *req, size_t resid) +-{ +- int retval = MFI_STAT_INVALID_CMD; +- +- if (cmd->frame->header.frame_cmd == MFI_CMD_DCMD) { +- cmd->iov_size -= resid; +- retval = megasas_finish_internal_dcmd(cmd, req); +- } +- return retval; +-} +- + static QEMUSGList *megasas_get_sg_list(SCSIRequest *req) + { + MegasasCmd *cmd = req->hba_private; + +- if (cmd->frame->header.frame_cmd == MFI_CMD_DCMD) { ++ if (cmd->dcmd_opcode != -1) { + return NULL; + } else { + return &cmd->qsg; +@@ -1731,7 +1722,7 @@ static void megasas_xfer_complete(SCSIRe + + trace_megasas_io_complete(cmd->index, len); + +- if (cmd->frame->header.frame_cmd != MFI_CMD_DCMD) { ++ if (cmd->dcmd_opcode != -1) { + scsi_req_continue(req); + return; + } +@@ -1770,7 +1761,7 @@ static void megasas_command_complete(SCS + /* + * Internal command complete + */ +- cmd_status = megasas_finish_internal_command(cmd, req, resid); ++ cmd_status = megasas_finish_internal_dcmd(cmd, req, resid); + if (cmd_status == MFI_STAT_INVALID_STATUS) { + return; + } +@@ -1844,6 +1835,7 @@ static void megasas_handle_frame(Megasas + { + uint8_t frame_status = MFI_STAT_INVALID_CMD; + uint64_t frame_context; ++ int frame_cmd; + MegasasCmd *cmd; + + /* +@@ -1862,7 +1854,8 @@ static void megasas_handle_frame(Megasas + s->event_count++; + return; + } +- switch (cmd->frame->header.frame_cmd) { ++ frame_cmd = cmd->frame->header.frame_cmd; ++ switch (frame_cmd) { + case MFI_CMD_INIT: + frame_status = megasas_init_firmware(s, cmd); + break; +@@ -1873,18 +1866,15 @@ static void megasas_handle_frame(Megasas + frame_status = megasas_handle_abort(s, cmd); + break; + case MFI_CMD_PD_SCSI_IO: +- frame_status = megasas_handle_scsi(s, cmd, 0); +- break; + case MFI_CMD_LD_SCSI_IO: +- frame_status = megasas_handle_scsi(s, cmd, 1); ++ frame_status = megasas_handle_scsi(s, cmd, frame_cmd); + break; + case MFI_CMD_LD_READ: + case MFI_CMD_LD_WRITE: +- frame_status = megasas_handle_io(s, cmd); ++ frame_status = megasas_handle_io(s, cmd, frame_cmd); + break; + default: +- trace_megasas_unhandled_frame_cmd(cmd->index, +- cmd->frame->header.frame_cmd); ++ trace_megasas_unhandled_frame_cmd(cmd->index, frame_cmd); + s->event_count++; + break; + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-6.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-6.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-6.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-6.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,152 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +Backport of: + +From b356807fcdfc45583c437f761fc579ab2a8eab11 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 17:25:03 +0200 +Subject: [PATCH] megasas: do not read SCSI req parameters more than once from + frame + +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 60 ++++++++++++++++++++++++------------------------------- + 1 file changed, 26 insertions(+), 34 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/scsi/megasas.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/scsi/megasas.c 2017-08-22 12:29:33.436826465 -0400 ++++ qemu-2.0.0+dfsg/hw/scsi/megasas.c 2017-08-22 12:31:24.856831661 -0400 +@@ -1554,43 +1554,40 @@ static int megasas_handle_scsi(MegasasSt + int frame_cmd) + { + uint8_t *cdb; ++ int target_id, lun_id, cdb_len; + int len; + bool is_write; + struct SCSIDevice *sdev = NULL; + bool is_logical = (frame_cmd == MFI_CMD_LD_SCSI_IO); + + cdb = cmd->frame->pass.cdb; ++ target_id = cmd->frame->header.target_id; ++ lun_id = cmd->frame->header.lun_id; ++ cdb_len = cmd->frame->header.cdb_len; + + if (is_logical) { +- if (cmd->frame->header.target_id >= MFI_MAX_LD || +- cmd->frame->header.lun_id != 0) { ++ if (target_id >= MFI_MAX_LD || lun_id != 0) { + trace_megasas_scsi_target_not_present( +- mfi_frame_desc[frame_cmd], is_logical, +- cmd->frame->header.target_id, cmd->frame->header.lun_id); ++ mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id); + return MFI_STAT_DEVICE_NOT_FOUND; + } + } +- sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id, +- cmd->frame->header.lun_id); ++ sdev = scsi_device_find(&s->bus, 0, target_id, lun_id); + + cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len); +- trace_megasas_handle_scsi(mfi_frame_desc[cmd->frame->header.frame_cmd], + trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical, +- cmd->frame->header.target_id, +- cmd->frame->header.lun_id, sdev, cmd->iov_size); ++ target_id, lun_id, sdev, cmd->iov_size); + + if (!sdev || (megasas_is_jbod(s) && is_logical)) { + trace_megasas_scsi_target_not_present( +- mfi_frame_desc[frame_cmd], is_logical, +- cmd->frame->header.target_id, cmd->frame->header.lun_id); ++ mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id); + return MFI_STAT_DEVICE_NOT_FOUND; + } + +- if (cmd->frame->header.cdb_len > 16) { ++ if (cdb_len > 16) { + trace_megasas_scsi_invalid_cdb_len( + mfi_frame_desc[frame_cmd], is_logical, +- cmd->frame->header.target_id, cmd->frame->header.lun_id, +- cmd->frame->header.cdb_len); ++ target_id, lun_id, cdb_len); + megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); + cmd->frame->header.scsi_status = CHECK_CONDITION; + s->event_count++; +@@ -1604,12 +1601,10 @@ static int megasas_handle_scsi(MegasasSt + return MFI_STAT_SCSI_DONE_WITH_ERROR; + } + +- cmd->req = scsi_req_new(sdev, cmd->index, +- cmd->frame->header.lun_id, cdb, cmd); ++ cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd); + if (!cmd->req) { + trace_megasas_scsi_req_alloc_failed( +- mfi_frame_desc[frame_cmd], +- cmd->frame->header.target_id, cmd->frame->header.lun_id); ++ mfi_frame_desc[frame_cmd], target_id, lun_id); + megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); + cmd->frame->header.scsi_status = BUSY; + s->event_count++; +@@ -1638,35 +1633,33 @@ static int megasas_handle_io(MegasasStat + uint8_t cdb[16]; + int len; + struct SCSIDevice *sdev = NULL; ++ int target_id, lun_id, cdb_len; + + lba_count = le32_to_cpu(cmd->frame->io.header.data_len); + lba_start_lo = le32_to_cpu(cmd->frame->io.lba_lo); + lba_start_hi = le32_to_cpu(cmd->frame->io.lba_hi); + lba_start = ((uint64_t)lba_start_hi << 32) | lba_start_lo; + +- if (cmd->frame->header.target_id < MFI_MAX_LD && +- cmd->frame->header.lun_id == 0) { +- sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id, +- cmd->frame->header.lun_id); ++ target_id = cmd->frame->header.target_id; ++ lun_id = cmd->frame->header.lun_id; ++ cdb_len = cmd->frame->header.cdb_len; ++ ++ if (target_id < MFI_MAX_LD && lun_id == 0) { ++ sdev = scsi_device_find(&s->bus, 0, target_id, lun_id); + } + + trace_megasas_handle_io(cmd->index, +- mfi_frame_desc[frame_cmd], +- cmd->frame->header.target_id, +- cmd->frame->header.lun_id, ++ mfi_frame_desc[frame_cmd], target_id, lun_id, + (unsigned long)lba_start, (unsigned long)lba_count); + if (!sdev) { + trace_megasas_io_target_not_present(cmd->index, +- mfi_frame_desc[frame_cmd], +- cmd->frame->header.target_id, cmd->frame->header.lun_id); ++ mfi_frame_desc[frame_cmd], target_id, lun_id); + return MFI_STAT_DEVICE_NOT_FOUND; + } + +- if (cmd->frame->header.cdb_len > 16) { ++ if (cdb_len > 16) { + trace_megasas_scsi_invalid_cdb_len( +- mfi_frame_desc[frame_cmd], 1, +- cmd->frame->header.target_id, cmd->frame->header.lun_id, +- cmd->frame->header.cdb_len); ++ mfi_frame_desc[frame_cmd], 1, target_id, lun_id, cdb_len); + megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); + cmd->frame->header.scsi_status = CHECK_CONDITION; + s->event_count++; +@@ -1683,11 +1676,10 @@ static int megasas_handle_io(MegasasStat + + megasas_encode_lba(cdb, lba_start, lba_count, is_write); + cmd->req = scsi_req_new(sdev, cmd->index, +- cmd->frame->header.lun_id, cdb, cmd); ++ lun_id, cdb, cmd); + if (!cmd->req) { + trace_megasas_scsi_req_alloc_failed( +- mfi_frame_desc[frame_cmd], +- cmd->frame->header.target_id, cmd->frame->header.lun_id); ++ mfi_frame_desc[frame_cmd], target_id, lun_id); + megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); + cmd->frame->header.scsi_status = BUSY; + s->event_count++; diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-7.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-7.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-7.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-7.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,179 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +Backport of: + +From 87e459a810d7b1ec1638085b5a80ea3d9b43119a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Thu, 1 Jun 2017 17:26:14 +0200 +Subject: [PATCH] megasas: always store SCSIRequest* into MegasasCmd + +This ensures that the request is unref'ed properly, and avoids a +segmentation fault in the new qtest testcase that is added. +This is CVE-2017-9503. + +Reported-by: Zhangyanyu <zyy4013@stu.ouc.edu.cn> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 31 ++++++++++++++++--------------- + tests/megasas-test.c | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 15 deletions(-) + +Index: qemu-2.0.0+dfsg/hw/scsi/megasas.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/hw/scsi/megasas.c 2017-08-22 12:32:06.408833598 -0400 ++++ qemu-2.0.0+dfsg/hw/scsi/megasas.c 2017-08-22 12:32:06.404833598 -0400 +@@ -569,6 +569,9 @@ static void megasas_reset_frames(Megasas + + static void megasas_abort_command(MegasasCmd *cmd) + { ++ if (cmd->dcmd_opcode != -1) { ++ return; ++ } + if (cmd->req) { + scsi_req_cancel(cmd->req); + cmd->req = NULL; +@@ -976,7 +979,6 @@ static int megasas_pd_get_info_submit(SC + uint64_t pd_size; + uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); + uint8_t cmdbuf[6]; +- SCSIRequest *req; + size_t len, resid; + + if (!cmd->iov_buf) { +@@ -986,8 +988,8 @@ static int megasas_pd_get_info_submit(SC + info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */ + info->vpd_page83[0] = 0x7f; + megasas_setup_inquiry(cmdbuf, 0, sizeof(info->inquiry_data)); +- req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd); +- if (!req) { ++ cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd); ++ if (!cmd->req) { + trace_megasas_dcmd_req_alloc_failed(cmd->index, + "PD get info std inquiry"); + g_free(cmd->iov_buf); +@@ -996,26 +998,26 @@ static int megasas_pd_get_info_submit(SC + } + trace_megasas_dcmd_internal_submit(cmd->index, + "PD get info std inquiry", lun); +- len = scsi_req_enqueue(req); ++ len = scsi_req_enqueue(cmd->req); + if (len > 0) { + cmd->iov_size = len; +- scsi_req_continue(req); ++ scsi_req_continue(cmd->req); + } + return MFI_STAT_INVALID_STATUS; + } else if (info->inquiry_data[0] != 0x7f && info->vpd_page83[0] == 0x7f) { + megasas_setup_inquiry(cmdbuf, 0x83, sizeof(info->vpd_page83)); +- req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd); +- if (!req) { ++ cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd); ++ if (!cmd->req) { + trace_megasas_dcmd_req_alloc_failed(cmd->index, + "PD get info vpd inquiry"); + return MFI_STAT_FLASH_ALLOC_FAIL; + } + trace_megasas_dcmd_internal_submit(cmd->index, + "PD get info vpd inquiry", lun); +- len = scsi_req_enqueue(req); ++ len = scsi_req_enqueue(cmd->req); + if (len > 0) { + cmd->iov_size = len; +- scsi_req_continue(req); ++ scsi_req_continue(cmd->req); + } + return MFI_STAT_INVALID_STATUS; + } +@@ -1129,7 +1131,6 @@ static int megasas_ld_get_info_submit(SC + struct mfi_ld_info *info = cmd->iov_buf; + size_t dcmd_size = sizeof(struct mfi_ld_info); + uint8_t cdb[6]; +- SCSIRequest *req; + ssize_t len, resid; + BlockConf *conf = &sdev->conf; + uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); +@@ -1140,8 +1141,8 @@ static int megasas_ld_get_info_submit(SC + memset(cmd->iov_buf, 0x0, dcmd_size); + info = cmd->iov_buf; + megasas_setup_inquiry(cdb, 0x83, sizeof(info->vpd_page83)); +- req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd); +- if (!req) { ++ cmd->req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd); ++ if (!cmd->req) { + trace_megasas_dcmd_req_alloc_failed(cmd->index, + "LD get info vpd inquiry"); + g_free(cmd->iov_buf); +@@ -1150,10 +1151,10 @@ static int megasas_ld_get_info_submit(SC + } + trace_megasas_dcmd_internal_submit(cmd->index, + "LD get info vpd inquiry", lun); +- len = scsi_req_enqueue(req); ++ len = scsi_req_enqueue(cmd->req); + if (len > 0) { + cmd->iov_size = len; +- scsi_req_continue(req); ++ scsi_req_continue(cmd->req); + } + return MFI_STAT_INVALID_STATUS; + } +@@ -1749,7 +1750,7 @@ static void megasas_command_complete(SCS + + trace_megasas_command_complete(cmd->index, status, resid); + +- if (cmd->req != req) { ++ if (cmd->dcmd_opcode != -1) { + /* + * Internal command complete + */ +Index: qemu-2.0.0+dfsg/tests/megasas-test.c +=================================================================== +--- qemu-2.0.0+dfsg.orig/tests/megasas-test.c 2017-08-22 12:32:06.408833598 -0400 ++++ qemu-2.0.0+dfsg/tests/megasas-test.c 2017-08-22 12:32:06.404833598 -0400 +@@ -42,10 +42,45 @@ static void pci_nop(void) + qmegasas_stop(qs); + } + ++/* This used to cause a NULL pointer dereference. */ ++static void megasas_pd_get_info_fuzz(void) ++{ ++ QPCIDevice *dev; ++ QOSState *qs; ++ QPCIBar bar; ++ uint32_t context[256]; ++ uint64_t context_pa; ++ int i; ++ ++ qs = qmegasas_start(NULL); ++ dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0)); ++ g_assert(dev != NULL); ++ ++ qpci_device_enable(dev); ++ bar = qpci_iomap(dev, 0, NULL); ++ ++ memset(context, 0, sizeof(context)); ++ context[0] = cpu_to_le32(0x05050505); ++ context[1] = cpu_to_le32(0x01010101); ++ for (i = 2; i < ARRAY_SIZE(context); i++) { ++ context[i] = cpu_to_le32(0x41414141); ++ } ++ context[6] = cpu_to_le32(0x02020000); ++ context[7] = cpu_to_le32(0); ++ ++ context_pa = qmalloc(qs, sizeof(context)); ++ memwrite(context_pa, context, sizeof(context)); ++ qpci_io_writel(dev, bar, 0x40, context_pa); ++ ++ g_free(dev); ++ qmegasas_stop(qs); ++} ++ + int main(int argc, char **argv) + { + g_test_init(&argc, &argv, NULL); + qtest_add_func("/megasas/pci/nop", pci_nop); ++ qtest_add_func("/megasas/dcmd/pd-get-info/fuzz", megasas_pd_get_info_fuzz); + + return g_test_run(); + } diff -Nru qemu-2.1+dfsg/debian/patches/CVE-2017-9503-pre1.patch qemu-2.1+dfsg/debian/patches/CVE-2017-9503-pre1.patch --- qemu-2.1+dfsg/debian/patches/CVE-2017-9503-pre1.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/CVE-2017-9503-pre1.patch 2018-07-29 15:33:43.000000000 +0200 @@ -0,0 +1,283 @@ +Origin: ubuntu, https://launchpad.net/ubuntu/+source/qemu/2.0.0+dfsg-2ubuntu1.35 +Reviewed-by Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 865754 + +Backport of: + +From 3f2cd4dd47719497540fb0e0aa0635e127f2838f Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke <hare@suse.de> +Date: Wed, 29 Oct 2014 13:00:07 +0100 +Subject: [PATCH] megasas: fixup device mapping + +Logical drives can only be addressed with the 'target_id' number; +LUN numbers cannot be selected. +Physical drives can be selected with both, target and LUN id. + +So we should disallow LUN numbers not equal to 0 when in +RAID mode. + +Signed-off-by: Hannes Reinecke <hare@suse.de> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +--- + hw/scsi/megasas.c | 95 +++++++++++++++++++++++++++++++++++-------------------- + hw/scsi/mfi.h | 2 +- + 2 files changed, 61 insertions(+), 36 deletions(-) + +Index: qemu/hw/scsi/megasas.c +=================================================================== +--- qemu.orig/hw/scsi/megasas.c ++++ qemu/hw/scsi/megasas.c +@@ -688,8 +688,7 @@ static int megasas_ctrl_get_info(Megasas + struct mfi_ctrl_info info; + size_t dcmd_size = sizeof(info); + BusChild *kid; +- int num_ld_disks = 0; +- uint16_t sdev_id; ++ int num_pd_disks = 0; + + memset(&info, 0x0, dcmd_size); + if (cmd->iov_size < dcmd_size) { +@@ -718,13 +717,14 @@ static int megasas_ctrl_get_info(Megasas + info.device.port_count = 8; + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); ++ uint16_t pd_id; + +- if (num_ld_disks < 8) { +- sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF); +- info.device.port_addr[num_ld_disks] = +- cpu_to_le64(megasas_get_sata_addr(sdev_id)); ++ if (num_pd_disks < 8) { ++ pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF); ++ info.device.port_addr[num_pd_disks] = ++ cpu_to_le64(megasas_get_sata_addr(pd_id)); + } +- num_ld_disks++; ++ num_pd_disks++; + } + + memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20); +@@ -750,13 +750,14 @@ static int megasas_ctrl_get_info(Megasas + info.max_arms = 32; + info.max_spans = 8; + info.max_arrays = MEGASAS_MAX_ARRAYS; +- info.max_lds = s->fw_luns; ++ info.max_lds = MFI_MAX_LD; + info.max_cmds = cpu_to_le16(s->fw_cmds); + info.max_sg_elements = cpu_to_le16(s->fw_sge); + info.max_request_size = cpu_to_le32(MEGASAS_MAX_SECTORS); +- info.lds_present = cpu_to_le16(num_ld_disks); +- info.pd_present = cpu_to_le16(num_ld_disks); +- info.pd_disks_present = cpu_to_le16(num_ld_disks); ++ if (!megasas_is_jbod(s)) ++ info.lds_present = cpu_to_le16(num_pd_disks); ++ info.pd_present = cpu_to_le16(num_pd_disks); ++ info.pd_disks_present = cpu_to_le16(num_pd_disks); + info.hw_present = cpu_to_le32(MFI_INFO_HW_NVRAM | + MFI_INFO_HW_MEM | + MFI_INFO_HW_FLASH); +@@ -915,7 +916,6 @@ static int megasas_dcmd_pd_get_list(Mega + size_t dcmd_size = sizeof(info); + BusChild *kid; + uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks; +- uint16_t sdev_id; + + memset(&info, 0, dcmd_size); + offset = 8; +@@ -927,22 +927,25 @@ static int megasas_dcmd_pd_get_list(Mega + } + + max_pd_disks = (cmd->iov_size - offset) / sizeof(struct mfi_pd_address); +- if (max_pd_disks > s->fw_luns) { +- max_pd_disks = s->fw_luns; ++ if (max_pd_disks > MFI_MAX_SYS_PDS) { ++ max_pd_disks = MFI_MAX_SYS_PDS; + } +- + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); ++ uint16_t pd_id; ++ ++ if (num_pd_disks >= max_pd_disks) ++ break; + +- sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF); +- info.addr[num_pd_disks].device_id = cpu_to_le16(sdev_id); ++ pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF); ++ info.addr[num_pd_disks].device_id = cpu_to_le16(pd_id); + info.addr[num_pd_disks].encl_device_id = 0xFFFF; + info.addr[num_pd_disks].encl_index = 0; +- info.addr[num_pd_disks].slot_number = (sdev->id & 0xFF); ++ info.addr[num_pd_disks].slot_number = sdev->id & 0xFF; + info.addr[num_pd_disks].scsi_dev_type = sdev->type; + info.addr[num_pd_disks].connect_port_bitmap = 0x1; + info.addr[num_pd_disks].sas_addr[0] = +- cpu_to_le64(megasas_get_sata_addr(sdev_id)); ++ cpu_to_le64(megasas_get_sata_addr(pd_id)); + num_pd_disks++; + offset += sizeof(struct mfi_pd_address); + } +@@ -978,7 +981,7 @@ static int megasas_pd_get_info_submit(SC + size_t dcmd_size = sizeof(struct mfi_pd_info); + BlockConf *conf = &sdev->conf; + uint64_t pd_size; +- uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF); ++ uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); + uint8_t cmdbuf[6]; + SCSIRequest *req; + size_t len, resid; +@@ -1034,7 +1037,7 @@ static int megasas_pd_get_info_submit(SC + info->fw_state = cpu_to_le16(MFI_PD_STATE_OFFLINE); + } + +- info->ref.v.device_id = cpu_to_le16(sdev_id); ++ info->ref.v.device_id = cpu_to_le16(pd_id); + info->state.ddf.pd_type = cpu_to_le16(MFI_PD_DDF_TYPE_IN_VD| + MFI_PD_DDF_TYPE_INTF_SAS); + bdrv_get_geometry(conf->bs, &pd_size); +@@ -1045,7 +1048,7 @@ static int megasas_pd_get_info_submit(SC + info->slot_number = (sdev->id & 0xFF); + info->path_info.count = 1; + info->path_info.sas_addr[0] = +- cpu_to_le64(megasas_get_sata_addr(sdev_id)); ++ cpu_to_le64(megasas_get_sata_addr(pd_id)); + info->connected_port_bitmap = 0x1; + info->device_speed = 1; + info->link_speed = 1; +@@ -1060,6 +1063,7 @@ static int megasas_dcmd_pd_get_info(Mega + { + size_t dcmd_size = sizeof(struct mfi_pd_info); + uint16_t pd_id; ++ uint8_t target_id, lun_id; + SCSIDevice *sdev = NULL; + int retval = MFI_STAT_DEVICE_NOT_FOUND; + +@@ -1069,7 +1073,9 @@ static int megasas_dcmd_pd_get_info(Mega + + /* mbox0 has the ID */ + pd_id = le16_to_cpu(cmd->frame->dcmd.mbox[0]); +- sdev = scsi_device_find(&s->bus, 0, pd_id, 0); ++ target_id = (pd_id >> 8) & 0xFF; ++ lun_id = pd_id & 0xFF; ++ sdev = scsi_device_find(&s->bus, 0, target_id, lun_id); + trace_megasas_dcmd_pd_get_info(cmd->index, pd_id); + + if (sdev) { +@@ -1084,7 +1090,7 @@ static int megasas_dcmd_ld_get_list(Mega + { + struct mfi_ld_list info; + size_t dcmd_size = sizeof(info), resid; +- uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns; ++ uint32_t num_ld_disks = 0, max_ld_disks; + uint64_t ld_size; + BusChild *kid; + +@@ -1095,9 +1101,13 @@ static int megasas_dcmd_ld_get_list(Mega + return MFI_STAT_INVALID_PARAMETER; + } + ++ max_ld_disks = (cmd->iov_size - 8) / 16; + if (megasas_is_jbod(s)) { + max_ld_disks = 0; + } ++ if (max_ld_disks > MFI_MAX_LD) { ++ max_ld_disks = MFI_MAX_LD; ++ } + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); + BlockConf *conf = &sdev->conf; +@@ -1108,7 +1118,6 @@ static int megasas_dcmd_ld_get_list(Mega + /* Logical device size is in blocks */ + bdrv_get_geometry(conf->bs, &ld_size); + info.ld_list[num_ld_disks].ld.v.target_id = sdev->id; +- info.ld_list[num_ld_disks].ld.v.lun_id = sdev->lun; + info.ld_list[num_ld_disks].state = MFI_LD_STATE_OPTIMAL; + info.ld_list[num_ld_disks].size = cpu_to_le64(ld_size); + num_ld_disks++; +@@ -1145,7 +1154,7 @@ static int megasas_ld_get_info_submit(SC + SCSIRequest *req; + ssize_t len, resid; + BlockConf *conf = &sdev->conf; +- uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF); ++ uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); + uint64_t ld_size; + + if (!cmd->iov_buf) { +@@ -1262,7 +1271,7 @@ static int megasas_dcmd_cfg_read(Megasas + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); + BlockConf *conf = &sdev->conf; +- uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF); ++ uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF); + struct mfi_array *array; + struct mfi_ld_config *ld; + uint64_t pd_size; +@@ -1288,7 +1297,7 @@ static int megasas_dcmd_cfg_read(Megasas + array_offset += sizeof(struct mfi_array); + ld = (struct mfi_ld_config *)(data + ld_offset); + memset(ld, 0, sizeof(struct mfi_ld_config)); +- ld->properties.ld.v.target_id = (sdev->id & 0xFF); ++ ld->properties.ld.v.target_id = sdev->id; + ld->properties.default_cache_policy = MR_LD_CACHE_READ_AHEAD | + MR_LD_CACHE_READ_ADAPTIVE; + ld->properties.current_cache_policy = MR_LD_CACHE_READ_AHEAD | +@@ -1576,10 +1585,18 @@ static int megasas_handle_scsi(MegasasSt + + cdb = cmd->frame->pass.cdb; + +- if (cmd->frame->header.target_id < s->fw_luns) { +- sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id, +- cmd->frame->header.lun_id); ++ if (is_logical) { ++ if (cmd->frame->header.target_id >= MFI_MAX_LD || ++ cmd->frame->header.lun_id != 0) { ++ trace_megasas_scsi_target_not_present( ++ mfi_frame_desc[cmd->frame->header.frame_cmd], is_logical, ++ cmd->frame->header.target_id, cmd->frame->header.lun_id); ++ return MFI_STAT_DEVICE_NOT_FOUND; ++ } + } ++ sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id, ++ cmd->frame->header.lun_id); ++ + cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len); + trace_megasas_handle_scsi(mfi_frame_desc[cmd->frame->header.frame_cmd], + is_logical, cmd->frame->header.target_id, +@@ -1650,7 +1667,8 @@ static int megasas_handle_io(MegasasStat + lba_start_hi = le32_to_cpu(cmd->frame->io.lba_hi); + lba_start = ((uint64_t)lba_start_hi << 32) | lba_start_lo; + +- if (cmd->frame->header.target_id < s->fw_luns) { ++ if (cmd->frame->header.target_id < MFI_MAX_LD && ++ cmd->frame->header.lun_id == 0) { + sdev = scsi_device_find(&s->bus, 0, cmd->frame->header.target_id, + cmd->frame->header.lun_id); + } +@@ -2209,8 +2227,12 @@ static int megasas_scsi_init(PCIDevice * + } + trace_megasas_init(s->fw_sge, s->fw_cmds, + megasas_is_jbod(s) ? "jbod" : "raid"); +- s->fw_luns = (MFI_MAX_LD > MAX_SCSI_DEVS) ? +- MAX_SCSI_DEVS : MFI_MAX_LD; ++ ++ if (megasas_is_jbod(s)) { ++ s->fw_luns = MFI_MAX_SYS_PDS; ++ } else { ++ s->fw_luns = MFI_MAX_LD; ++ } + s->producer_pa = 0; + s->consumer_pa = 0; + for (i = 0; i < s->fw_cmds; i++) { +Index: qemu/hw/scsi/mfi.h +=================================================================== +--- qemu.orig/hw/scsi/mfi.h ++++ qemu/hw/scsi/mfi.h +@@ -1094,7 +1094,7 @@ struct mfi_pd_list { + union mfi_ld_ref { + struct { + uint8_t target_id; +- uint8_t lun_id; ++ uint8_t reserved; + uint16_t seq; + } v; + uint32_t ref; diff -Nru qemu-2.1+dfsg/debian/patches/series qemu-2.1+dfsg/debian/patches/series --- qemu-2.1+dfsg/debian/patches/series 2016-05-08 15:35:16.000000000 +0200 +++ qemu-2.1+dfsg/debian/patches/series 2018-07-29 15:33:43.000000000 +0200 @@ -102,3 +102,108 @@ vga-factor-out-vga-register-setup.patch vga-update-vga-register-setup-on-vbe-changes.patch vga-make-sure-vga-register-setup-for-vbe-stays-intac.patch + +CVE-2016-2198-usb-ehci-add-capability-mmio-write-function.patch +CVE-2016-6833-vmxnet3-check-for-device_active-before-write.patch +CVE-2016-6835-net-vmxnet-check-IP-header-length.patch +CVE-2016-8576-fix-infinite-loop.patch +CVE-2016-8667.patch +CVE-2016-8669.patch +CVE-2016-9602-1.patch +CVE-2016-9602-2.patch +CVE-2016-9602-3.patch +CVE-2016-9602-4.patch +CVE-2016-9602-5.patch +CVE-2016-9602-6.patch +CVE-2016-9602-7.patch +CVE-2016-9602-8.patch +CVE-2016-9602-9.patch +CVE-2016-9602-10.patch +CVE-2016-9602-11.patch +CVE-2016-9602-12.patch +CVE-2016-9602-13.patch +CVE-2016-9602-14.patch +CVE-2016-9602-15.patch +CVE-2016-9602-16.patch +CVE-2016-9602-17.patch +CVE-2016-9602-18.patch +CVE-2016-9602-19.patch +CVE-2016-9602-20.patch +CVE-2016-9602-21.patch +CVE-2016-9602-22.patch +CVE-2016-9602-23.patch +CVE-2016-9602-24.patch +CVE-2016-9602-25.patch +CVE-2016-9602-26.patch +CVE-2016-9602-27.patch +CVE-2016-9602-28.patch +CVE-2016-9602-29.patch +CVE-2016-9602-pre.patch +CVE-2016-9603-cirrus-vnc-zap-bitblit-support-from-console-code.patch +#display-cirrus-ignore-source-pitch-value-as-needed-in-bli.patch +CVE-2017-7471.patch +CVE-2016-9776.patch +CVE-2016-9907.patch +CVE-2016-9911.patch +CVE-2016-9914-1.patch +CVE-2016-9914-2.patch +CVE-2016-9915.patch +CVE-2016-9916.patch +CVE-2016-9921-9922.patch +CVE-2016-10155.patch +CVE-2017-2620-pre.patch +CVE-2017-2620-cirrus-add-blit_is_unsafe-call-to-cirrus_bi.patch +0001-cirrus-fix-oob-access-issue-CVE-2017-2615.patch +CVE-2017-5525.patch +CVE-2017-5526.patch +CVE-2017-5579.patch +CVE-2017-5667.patch +CVE-2017-5715-1.patch +CVE-2017-5715-2.patch +CVE-2017-5715-3pre1.patch +CVE-2017-5715-3.patch +CVE-2017-5715-4.patch +CVE-2017-5715-5.patch +CVE-2017-5856.patch +CVE-2017-5987-1.patch +CVE-2017-5987-2.patch +CVE-2017-5987-3.patch +CVE-2017-5987-4.patch +CVE-2017-5973.patch +CVE-2017-6505.patch +CVE-2017-7377.patch +CVE-2017-7493.patch +CVE-2017-7718.patch +CVE-2017-7980-1-CVE-2017-18030.patch +CVE-2017-7980-2.patch +CVE-2017-7980-3.patch +CVE-2017-7980-4.patch +CVE-2017-7980-5.patch +CVE-2017-7980-6.patch +CVE-2017-7980-7.patch +CVE-2017-8086.patch +CVE-2017-8112.patch +CVE-2017-8309-audio-release-capture-buffers.patch +CVE-2017-8379-1.patch +CVE-2017-8379-2.patch +CVE-2017-9330.patch +CVE-2017-9373-1.patch +CVE-2017-9373-2.patch +CVE-2017-9374.patch +CVE-2017-9503-pre1.patch +CVE-2017-9503-1.patch +CVE-2017-9503-2.patch +CVE-2017-9503-3.patch +CVE-2017-9503-4.patch +CVE-2017-9503-5.patch +CVE-2017-9503-6.patch +CVE-2017-9503-7.patch +CVE-2017-10664-Ignore-SIGPIPE.patch +CVE-2017-10806.patch +xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch +CVE-2017-11434-slirp-check-len-against-dhcp-options-array.patch +CVE-2017-14167-multiboot-validate-multiboot-header-addres.patch +CVE-2017-15038-9pfs-use-g_malloc0-to-allocate-space-for-x.patch +CVE-2017-15289.patch +CVE-2017-16845.patch +CVE-2017-18043.patch diff -Nru qemu-2.1+dfsg/debian/patches/xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch qemu-2.1+dfsg/debian/patches/xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch --- qemu-2.1+dfsg/debian/patches/xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch 1970-01-01 01:00:00.000000000 +0100 +++ qemu-2.1+dfsg/debian/patches/xen-disk-don-t-leak-stack-data-via-response-ring-CVE-2017-10911.patch 2018-07-26 19:12:18.000000000 +0200 @@ -0,0 +1,73 @@ +Origin: backported, https://salsa.debian.org/qemu-team/qemu/commit/c1863320f25f3e3a5d3d3b0fec793ae983a9ea5c +Reviewed-by: Santiago R.R. <santiagorr@riseup.net> +Bug-Debian: 869706 + +From: Stefano Stabellini <sstabellini@kernel.org> +Date: Tue, 27 Jun 2017 14:45:34 -0700 +Subject: xen/disk: don't leak stack data via response ring +Commit-Id: b0ac694fdb9113b973048ebe5619927e74965f61 +Bug: https://xenbits.xen.org/xsa/advisory-216.html + +Rather than constructing a local structure instance on the stack, fill +the fields directly on the shared ring, just like other (Linux) +backends do. Build on the fact that all response structure flavors are +actually identical (aside from alignment and padding at the end). + +This is XSA-216. + +Reported by: Anthony Perard <anthony.perard@citrix.com> +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Signed-off-by: Stefano Stabellini <sstabellini@kernel.org> +Acked-by: Anthony PERARD <anthony.perard@citrix.com> +--- + hw/block/xen_disk.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +Index: qemu/hw/block/xen_disk.c +=================================================================== +--- qemu.orig/hw/block/xen_disk.c ++++ qemu/hw/block/xen_disk.c +@@ -609,30 +609,30 @@ static int blk_send_response_one(struct + struct XenBlkDev *blkdev = ioreq->blkdev; + int send_notify = 0; + int have_requests = 0; +- blkif_response_t resp; +- void *dst; +- +- resp.id = ioreq->req.id; +- resp.operation = ioreq->req.operation; +- resp.status = ioreq->status; ++ blkif_response_t *resp; + + /* Place on the response ring for the relevant domain. */ + switch (blkdev->protocol) { + case BLKIF_PROTOCOL_NATIVE: +- dst = RING_GET_RESPONSE(&blkdev->rings.native, blkdev->rings.native.rsp_prod_pvt); ++ resp = (blkif_response_t *) RING_GET_RESPONSE(&blkdev->rings.native, ++ blkdev->rings.native.rsp_prod_pvt); + break; + case BLKIF_PROTOCOL_X86_32: +- dst = RING_GET_RESPONSE(&blkdev->rings.x86_32_part, +- blkdev->rings.x86_32_part.rsp_prod_pvt); ++ resp = (blkif_response_t *) RING_GET_RESPONSE(&blkdev->rings.x86_32_part, ++ blkdev->rings.x86_32_part.rsp_prod_pvt); + break; + case BLKIF_PROTOCOL_X86_64: +- dst = RING_GET_RESPONSE(&blkdev->rings.x86_64_part, +- blkdev->rings.x86_64_part.rsp_prod_pvt); ++ resp = (blkif_response_t *) RING_GET_RESPONSE(&blkdev->rings.x86_64_part, ++ blkdev->rings.x86_64_part.rsp_prod_pvt); + break; + default: +- dst = NULL; ++ return 0; + } +- memcpy(dst, &resp, sizeof(resp)); ++ ++ resp->id = ioreq->req.id; ++ resp->operation = ioreq->req.operation; ++ resp->status = ioreq->status; ++ + blkdev->rings.common.rsp_prod_pvt++; + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blkdev->rings.common, send_notify);
Attachment:
signature.asc
Description: PGP signature