# also update debian/changelog
-KVMVER=2.9.0
-KVMPKGREL=5
+KVMVER=2.9.1
+KVMPKGREL=1
KVMPACKAGE = pve-qemu-kvm
KVMSRC = qemu
+pve-qemu-kvm (2.9.1-1) stable; urgency=medium
+
+ * update to 2.9.1
+
+ * fix CVE-2017-14167: i386: multiboot OOB access while loading guest kernel image
+
+ * fix CVE-2017-13673: vga: reachable assert failure during during display update
+
+ * fix CVE-2017-13672: vga: OOB read access during display update
+
+ * fix CVE-2017-13711: Slirp: use-after-free when sending response
+
+ * fix CVE-2017-12809: ide: flushing of empty CDROM drives leads to NULL dereference
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 08 Sep 2017 09:31:33 +0200
+
pve-qemu-kvm (2.9.0-5) stable; urgency=medium
* Fix #1420: fix stop mode backups with virtio-blk
-From 3949cb837593d29db5c06cef51f405ee3250c4c1 Mon Sep 17 00:00:00 2001
+From b143eba39dd462833093ee1c9660bb157e72ce54 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Mon, 4 Jul 2016 15:02:26 +0200
-Subject: [PATCH 01/23] Revert "target-i386: disable LINT0 after reset"
+Subject: [PATCH 01/13] Revert "target-i386: disable LINT0 after reset"
This reverts commit b8eb5512fd8a115f164edbbe897cdf8884920ccb.
---
1 file changed, 9 insertions(+)
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
-index c3829e31b5..d4411a2fd4 100644
+index 1ef56f8d10..31fb73e9fb 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -257,6 +257,15 @@ static void apic_reset_common(DeviceState *dev)
+++ /dev/null
-From e340d6c3321d3eb4e6f7854550cfdc94aa1c8143 Mon Sep 17 00:00:00 2001
-From: Anton Nefedov <anton.nefedov@virtuozzo.com>
-Date: Wed, 26 Apr 2017 11:33:15 +0300
-Subject: [PATCH 02/23] qemu-img: wait for convert coroutines to complete
-
-On error path (like i/o error in one of the coroutines), it's required to
- - wait for coroutines completion before cleaning the common structures
- - reenter dependent coroutines so they ever finish
-
-Introduced in 2d9187bc65.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
-Reviewed-by: Peter Lieven <pl@kamp.de>
-Signed-off-by: Kevin Wolf <kwolf@redhat.com>
----
- qemu-img.c | 26 +++++++++++---------------
- 1 file changed, 11 insertions(+), 15 deletions(-)
-
-diff --git a/qemu-img.c b/qemu-img.c
-index b9d1ef7bb8..59f4f7f22a 100644
---- a/qemu-img.c
-+++ b/qemu-img.c
-@@ -1761,13 +1761,13 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
- qemu_co_mutex_lock(&s->lock);
- if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) {
- qemu_co_mutex_unlock(&s->lock);
-- goto out;
-+ break;
- }
- n = convert_iteration_sectors(s, s->sector_num);
- if (n < 0) {
- qemu_co_mutex_unlock(&s->lock);
- s->ret = n;
-- goto out;
-+ break;
- }
- /* save current sector and allocation status to local variables */
- sector_num = s->sector_num;
-@@ -1792,7 +1792,6 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
- error_report("error while reading sector %" PRId64
- ": %s", sector_num, strerror(-ret));
- s->ret = ret;
-- goto out;
- }
- } else if (!s->min_sparse && status == BLK_ZERO) {
- status = BLK_DATA;
-@@ -1801,22 +1800,20 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
-
- if (s->wr_in_order) {
- /* keep writes in order */
-- while (s->wr_offs != sector_num) {
-- if (s->ret != -EINPROGRESS) {
-- goto out;
-- }
-+ while (s->wr_offs != sector_num && s->ret == -EINPROGRESS) {
- s->wait_sector_num[index] = sector_num;
- qemu_coroutine_yield();
- }
- s->wait_sector_num[index] = -1;
- }
-
-- ret = convert_co_write(s, sector_num, n, buf, status);
-- if (ret < 0) {
-- error_report("error while writing sector %" PRId64
-- ": %s", sector_num, strerror(-ret));
-- s->ret = ret;
-- goto out;
-+ if (s->ret == -EINPROGRESS) {
-+ ret = convert_co_write(s, sector_num, n, buf, status);
-+ if (ret < 0) {
-+ error_report("error while writing sector %" PRId64
-+ ": %s", sector_num, strerror(-ret));
-+ s->ret = ret;
-+ }
- }
-
- if (s->wr_in_order) {
-@@ -1837,7 +1834,6 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
- }
- }
-
--out:
- qemu_vfree(buf);
- s->co[index] = NULL;
- s->running_coroutines--;
-@@ -1899,7 +1895,7 @@ static int convert_do_copy(ImgConvertState *s)
- qemu_coroutine_enter(s->co[i]);
- }
-
-- while (s->ret == -EINPROGRESS) {
-+ while (s->running_coroutines) {
- main_loop_wait(false);
- }
-
---
-2.11.0
-
--- /dev/null
+From aec6bba73f7d7692de2c4196ee80e4d753b45604 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Fri, 2 Jun 2017 10:54:24 +0100
+Subject: [PATCH 02/13] virtio-serial: fix segfault on disconnect
+
+Since commit d4c19cdeeb2f1e474bc426a6da261f1d7346eb5b ("virtio-serial:
+add missing virtio_detach_element() call") the following commands may
+cause QEMU to segfault:
+
+ $ qemu -M accel=kvm -cpu host -m 1G \
+ -drive if=virtio,file=test.img,format=raw \
+ -device virtio-serial-pci,id=virtio-serial0 \
+ -chardev socket,id=channel1,path=/tmp/chardev.sock,server,nowait \
+ -device virtserialport,chardev=channel1,bus=virtio-serial0.0,id=port1
+ $ nc -U /tmp/chardev.sock
+ ^C
+
+ (guest)$ cat /dev/zero >/dev/vport0p1
+
+The segfault is non-deterministic: if the event loop notices the socket
+has been closed then there is no crash. The disconnect has to happen
+right before QEMU attempts to write data to the socket.
+
+The backtrace is as follows:
+
+ Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
+ 0x00005555557e0698 in do_flush_queued_data (port=0x5555582cedf0, vq=0x7fffcc854290, vdev=0x55555807b1d0) at hw/char/virtio-serial-bus.c:180
+ 180 for (i = port->iov_idx; i < port->elem->out_num; i++) {
+ #1 0x000055555580d363 in virtio_queue_notify_vq (vq=0x7fffcc854290) at hw/virtio/virtio.c:1524
+ #2 0x000055555580d363 in virtio_queue_host_notifier_read (n=0x7fffcc8542f8) at hw/virtio/virtio.c:2430
+ #3 0x0000555555b3482c in aio_dispatch_handlers (ctx=ctx@entry=0x5555566b8c80) at util/aio-posix.c:399
+ #4 0x0000555555b350d8 in aio_dispatch (ctx=0x5555566b8c80) at util/aio-posix.c:430
+ #5 0x0000555555b3212e in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:261
+ #6 0x00007fffde71de52 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
+ #7 0x0000555555b34353 in glib_pollfds_poll () at util/main-loop.c:213
+ #8 0x0000555555b34353 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:261
+ #9 0x0000555555b34353 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:517
+ #10 0x0000555555773207 in main_loop () at vl.c:1917
+ #11 0x0000555555773207 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4751
+
+The do_flush_queued_data() function does not anticipate chardev close
+events during vsc->have_data(). It expects port->elem to remain
+non-NULL for the duration its for loop.
+
+The fix is simply to return from do_flush_queued_data() if the port
+closes because the close event already frees port->elem and drains the
+virtqueue - there is nothing left for do_flush_queued_data() to do.
+
+Reported-by: Sitong Liu <siliu@redhat.com>
+Reported-by: Min Deng <mdeng@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+---
+ hw/char/virtio-serial-bus.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
+index aa9c11ae92..f5bc173844 100644
+--- a/hw/char/virtio-serial-bus.c
++++ b/hw/char/virtio-serial-bus.c
+@@ -186,6 +186,9 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
+ port->elem->out_sg[i].iov_base
+ + port->iov_offset,
+ buf_size);
++ if (!port->elem) { /* bail if we got disconnected */
++ return;
++ }
+ if (port->throttled) {
+ port->iov_idx = i;
+ if (ret > 0) {
+--
+2.11.0
+
+++ /dev/null
-From 80a3ed331899e4710b33c4b2a88f1b7b888d6497 Mon Sep 17 00:00:00 2001
-From: Max Reitz <mreitz@redhat.com>
-Date: Thu, 13 Apr 2017 17:43:34 +0200
-Subject: [PATCH 03/23] block: Do not unref bs->file on error in BD's open
-
-The block layer takes care of removing the bs->file child if the block
-driver's bdrv_open()/bdrv_file_open() implementation fails. The block
-driver therefore does not need to do so, and indeed should not unless it
-sets bs->file to NULL afterwards -- because if this is not done, the
-bdrv_unref_child() in bdrv_open_inherit() will dereference the freed
-memory block at bs->file afterwards, which is not good.
-
-We can now decide whether to add a "bs->file = NULL;" after each of the
-offending bdrv_unref_child() invocations, or just drop them altogether.
-The latter is simpler, so let's do that.
-
-Cc: qemu-stable <qemu-stable@nongnu.org>
-Signed-off-by: Max Reitz <mreitz@redhat.com>
-Reviewed-by: Eric Blake <eblake@redhat.com>
-Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
-Signed-off-by: Kevin Wolf <kwolf@redhat.com>
----
- block/blkdebug.c | 4 +---
- block/blkreplay.c | 3 ---
- block/blkverify.c | 3 ---
- 3 files changed, 1 insertion(+), 9 deletions(-)
-
-diff --git a/block/blkdebug.c b/block/blkdebug.c
-index 67e8024e36..cc4a146e84 100644
---- a/block/blkdebug.c
-+++ b/block/blkdebug.c
-@@ -389,14 +389,12 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
- } else if (align) {
- error_setg(errp, "Invalid alignment");
- ret = -EINVAL;
-- goto fail_unref;
-+ goto out;
- }
-
- ret = 0;
- goto out;
-
--fail_unref:
-- bdrv_unref_child(bs, bs->file);
- out:
- if (ret < 0) {
- g_free(s->config_file);
-diff --git a/block/blkreplay.c b/block/blkreplay.c
-index e1102119fb..6aa5fd4156 100755
---- a/block/blkreplay.c
-+++ b/block/blkreplay.c
-@@ -37,9 +37,6 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
-
- ret = 0;
- fail:
-- if (ret < 0) {
-- bdrv_unref_child(bs, bs->file);
-- }
- return ret;
- }
-
-diff --git a/block/blkverify.c b/block/blkverify.c
-index 9a1e21c6ad..af23281669 100644
---- a/block/blkverify.c
-+++ b/block/blkverify.c
-@@ -142,9 +142,6 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
-
- ret = 0;
- fail:
-- if (ret < 0) {
-- bdrv_unref_child(bs, bs->file);
-- }
- qemu_opts_del(opts);
- return ret;
- }
---
-2.11.0
-
--- /dev/null
+From 3884a6e250302f5f3d002ed03c20fb9678ea85e7 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Thu, 1 Jun 2017 17:26:14 +0200
+Subject: [PATCH 03/13] 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 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
+index 135662df31..734fdaef90 100644
+--- a/hw/scsi/megasas.c
++++ b/hw/scsi/megasas.c
+@@ -609,6 +609,9 @@ static void megasas_reset_frames(MegasasState *s)
+ static void megasas_abort_command(MegasasCmd *cmd)
+ {
+ /* Never abort internal commands. */
++ if (cmd->dcmd_opcode != -1) {
++ return;
++ }
+ if (cmd->req != NULL) {
+ scsi_req_cancel(cmd->req);
+ }
+@@ -1017,7 +1020,6 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
+ 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) {
+@@ -1026,8 +1028,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
+ 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);
+@@ -1036,26 +1038,26 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
+ }
+ 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;
+ }
+@@ -1217,7 +1219,6 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
+ 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;
+ uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
+ uint64_t ld_size;
+@@ -1226,8 +1227,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
+ cmd->iov_buf = g_malloc0(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);
+@@ -1236,10 +1237,10 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
+ }
+ 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;
+ }
+@@ -1851,7 +1852,7 @@ static void megasas_command_complete(SCSIRequest *req, uint32_t status,
+ return;
+ }
+
+- if (cmd->req == NULL) {
++ if (cmd->dcmd_opcode != -1) {
+ /*
+ * Internal command complete
+ */
+--
+2.11.0
+
+++ /dev/null
-From 952bdc64b03ffc3bdf3529b22f291ad26ef94d1b Mon Sep 17 00:00:00 2001
-From: Greg Kurz <groug@kaod.org>
-Date: Thu, 25 May 2017 10:30:13 +0200
-Subject: [PATCH 04/23] 9pfs: local: fix unlink of alien files in mapped-file
- mode
-
-When trying to remove a file from a directory, both created in non-mapped
-mode, the file remains and EBADF is returned to the guest.
-
-This is a regression introduced by commit "df4938a6651b 9pfs: local:
-unlinkat: don't follow symlinks" when fixing CVE-2016-9602. It changed the
-way we unlink the metadata file from
-
- ret = remove("$dir/.virtfs_metadata/$name");
- if (ret < 0 && errno != ENOENT) {
- /* Error out */
- }
- /* Ignore absence of metadata */
-
-to
-
- fd = openat("$dir/.virtfs_metadata")
- unlinkat(fd, "$name")
- if (ret < 0 && errno != ENOENT) {
- /* Error out */
- }
- /* Ignore absence of metadata */
-
-If $dir was created in non-mapped mode, openat() fails with ENOENT and
-we pass -1 to unlinkat(), which fails in turn with EBADF.
-
-We just need to check the return of openat() and ignore ENOENT, in order
-to restore the behaviour we had with remove().
-
-Signed-off-by: Greg Kurz <groug@kaod.org>
-Reviewed-by: Eric Blake <eblake@redhat.com>
-[groug: rewrote the comments as suggested by Eric]
----
- hw/9pfs/9p-local.c | 34 +++++++++++++++-------------------
- 1 file changed, 15 insertions(+), 19 deletions(-)
-
-diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
-index f3ebca4f7a..7a0c383e7e 100644
---- a/hw/9pfs/9p-local.c
-+++ b/hw/9pfs/9p-local.c
-@@ -957,6 +957,14 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
- if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- int map_dirfd;
-
-+ /* We need to remove the metadata as well:
-+ * - the metadata directory if we're removing a directory
-+ * - the metadata file in the parent's metadata directory
-+ *
-+ * If any of these are missing (ie, ENOENT) then we're probably
-+ * trying to remove something that wasn't created in mapped-file
-+ * mode. We just ignore the error.
-+ */
- if (flags == AT_REMOVEDIR) {
- int fd;
-
-@@ -964,32 +972,20 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
- 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.
-- */
-+ if (map_dirfd != -1) {
-+ ret = unlinkat(map_dirfd, name, 0);
-+ close_preserve_errno(map_dirfd);
-+ if (ret < 0 && errno != ENOENT) {
-+ goto err_out;
-+ }
-+ } else if (errno != ENOENT) {
- goto err_out;
- }
- }
---
-2.11.0
-
--- /dev/null
+From 918e23903f5712274830bb20e2d5603bf5794af7 Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp@fedoraproject.org>
+Date: Mon, 17 Jul 2017 17:33:26 +0530
+Subject: [PATCH 04/13] 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>
+---
+ slirp/bootp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/slirp/bootp.c b/slirp/bootp.c
+index 5a4646c182..5dd1a415b5 100644
+--- a/slirp/bootp.c
++++ b/slirp/bootp.c
+@@ -123,6 +123,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) {
+--
+2.11.0
+
--- /dev/null
+From f635d03bc56b8d56589f8f962f893de1e8126c06 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 9 Aug 2017 17:02:11 +0100
+Subject: [PATCH 05/13] IDE: Do not flush empty CDROM drives
+
+The block backend changed in a way that flushing empty CDROM drives now
+crashes. Amend IDE to avoid doing so until the root problem can be
+addressed for 2.11.
+
+Original patch by John Snow <jsnow@redhat.com>.
+
+Reported-by: Kieron Shorrock <kshorrock@paloaltonetworks.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Message-id: 20170809160212.29976-2-stefanha@redhat.com
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/ide/core.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 0b48b64d3a..bea39536b0 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -1063,7 +1063,15 @@ static void ide_flush_cache(IDEState *s)
+ s->status |= BUSY_STAT;
+ ide_set_retry(s);
+ block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
+- s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
++
++ if (blk_bs(s->blk)) {
++ s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
++ } else {
++ /* XXX blk_aio_flush() crashes when blk_bs(blk) is NULL, remove this
++ * temporary workaround when blk_aio_*() functions handle NULL blk_bs.
++ */
++ ide_flush_cb(s, 0);
++ }
+ }
+
+ static void ide_cfata_metadata_inquiry(IDEState *s)
+--
+2.11.0
+
+++ /dev/null
-From 0720bbba9f7ebac6f4f0ae7a65cd687ac6f3c452 Mon Sep 17 00:00:00 2001
-From: John Snow <jsnow@redhat.com>
-Date: Wed, 10 May 2017 13:39:45 -0400
-Subject: [PATCH 05/23] blockdev: use drained_begin/end for qmp_block_resize
-
-Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1447551
-
-If one tries to issue a block_resize while a guest is busy
-accessing the disk, it is possible that qemu may deadlock
-when invoking aio_poll from both the main loop and the iothread.
-
-Replace another instance of bdrv_drain_all that doesn't
-quite belong.
-
-Cc: qemu-stable@nongnu.org
-Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
-Signed-off-by: John Snow <jsnow@redhat.com>
-Reviewed-by: Eric Blake <eblake@redhat.com>
-Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
-Signed-off-by: Kevin Wolf <kwolf@redhat.com>
----
- blockdev.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/blockdev.c b/blockdev.c
-index 1eeffb0571..1dca232781 100644
---- a/blockdev.c
-+++ b/blockdev.c
-@@ -2929,10 +2929,9 @@ void qmp_block_resize(bool has_device, const char *device,
- goto out;
- }
-
-- /* complete all in-flight operations before resizing the device */
-- bdrv_drain_all();
--
-+ bdrv_drained_begin(bs);
- ret = blk_truncate(blk, size);
-+ bdrv_drained_end(bs);
- switch (ret) {
- case 0:
- break;
---
-2.11.0
-
+++ /dev/null
-From 28a204390093e5dfa0b4a2e94c06e807fe777c5f Mon Sep 17 00:00:00 2001
-From: Stefan Hajnoczi <stefanha@redhat.com>
-Date: Mon, 8 May 2017 14:07:05 -0400
-Subject: [PATCH 06/23] aio: add missing aio_notify() to aio_enable_external()
-
-The main loop uses aio_disable_external()/aio_enable_external() to
-temporarily disable processing of external AioContext clients like
-device emulation.
-
-This allows monitor commands to quiesce I/O and prevent the guest from
-submitting new requests while a monitor command is in progress.
-
-The aio_enable_external() API is currently broken when an IOThread is in
-aio_poll() waiting for fd activity when the main loop re-enables
-external clients. Incrementing ctx->external_disable_cnt does not wake
-the IOThread from ppoll(2) so fd processing remains suspended and leads
-to unresponsive emulated devices.
-
-This patch adds an aio_notify() call to aio_enable_external() so the
-IOThread is kicked out of ppoll(2) and will re-arm the file descriptors.
-
-The bug can be reproduced as follows:
-
- $ qemu -M accel=kvm -m 1024 \
- -object iothread,id=iothread0 \
- -device virtio-scsi-pci,iothread=iothread0,id=virtio-scsi-pci0 \
- -drive if=none,id=drive0,aio=native,cache=none,format=raw,file=test.img \
- -device scsi-hd,id=scsi-hd0,drive=drive0 \
- -qmp tcp::5555,server,nowait
-
- $ scripts/qmp/qmp-shell localhost:5555
- (qemu) blockdev-snapshot-sync device=drive0 snapshot-file=sn1.qcow2
- mode=absolute-paths format=qcow2
-
-After blockdev-snapshot-sync completes the SCSI disk will be
-unresponsive. This leads to request timeouts inside the guest.
-
-Reported-by: Qianqian Zhu <qizhu@redhat.com>
-Reviewed-by: Fam Zheng <famz@redhat.com>
-Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-Message-id: 20170508180705.20609-1-stefanha@redhat.com
-Suggested-by: Fam Zheng <famz@redhat.com>
-Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
----
- include/block/aio.h | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/include/block/aio.h b/include/block/aio.h
-index 406e32305a..e9aeeaec94 100644
---- a/include/block/aio.h
-+++ b/include/block/aio.h
-@@ -454,8 +454,14 @@ static inline void aio_disable_external(AioContext *ctx)
- */
- static inline void aio_enable_external(AioContext *ctx)
- {
-- assert(ctx->external_disable_cnt > 0);
-- atomic_dec(&ctx->external_disable_cnt);
-+ int old;
-+
-+ old = atomic_fetch_dec(&ctx->external_disable_cnt);
-+ assert(old > 0);
-+ if (old == 1) {
-+ /* Kick event loop so it re-arms file descriptors */
-+ aio_notify(ctx);
-+ }
- }
-
- /**
---
-2.11.0
-
--- /dev/null
+From 9d6486413e60b1d973f7ec2ac006fc9b8e210ddd Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 21 Apr 2017 11:16:24 +0200
+Subject: [PATCH 06/13] bitmap: add bitmap_copy_and_clear_atomic
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170421091632.30900-2-kraxel@redhat.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ include/qemu/bitmap.h | 2 ++
+ util/bitmap.c | 11 +++++++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
+index 63ea2d0b1e..c318da12d7 100644
+--- a/include/qemu/bitmap.h
++++ b/include/qemu/bitmap.h
+@@ -220,6 +220,8 @@ void bitmap_set(unsigned long *map, long i, long len);
+ void bitmap_set_atomic(unsigned long *map, long i, long len);
+ void bitmap_clear(unsigned long *map, long start, long nr);
+ bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr);
++void bitmap_copy_and_clear_atomic(unsigned long *dst, unsigned long *src,
++ long nr);
+ unsigned long bitmap_find_next_zero_area(unsigned long *map,
+ unsigned long size,
+ unsigned long start,
+diff --git a/util/bitmap.c b/util/bitmap.c
+index c1a84ca5e3..efced9a7d8 100644
+--- a/util/bitmap.c
++++ b/util/bitmap.c
+@@ -287,6 +287,17 @@ bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr)
+ return dirty != 0;
+ }
+
++void bitmap_copy_and_clear_atomic(unsigned long *dst, unsigned long *src,
++ long nr)
++{
++ while (nr > 0) {
++ *dst = atomic_xchg(src, 0);
++ dst++;
++ src++;
++ nr -= BITS_PER_LONG;
++ }
++}
++
+ #define ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+
+ /**
+--
+2.11.0
+
--- /dev/null
+From a89da93a2d3ffd3ba9516da89ecfbb0dd5fd51ad Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 21 Apr 2017 11:16:25 +0200
+Subject: [PATCH 07/13] memory: add support getting and using a dirty bitmap
+ copy.
+
+This patch adds support for getting and using a local copy of the dirty
+bitmap.
+
+memory_region_snapshot_and_clear_dirty() will create a snapshot of the
+dirty bitmap for the specified range, clear the dirty bitmap and return
+the copy. The returned bitmap can be a bit larger than requested, the
+range is expanded so the code can copy unsigned longs from the bitmap
+and avoid atomic bit update operations.
+
+memory_region_snapshot_get_dirty() will return the dirty status of
+pages, pretty much like memory_region_get_dirty(), but using the copy
+returned by memory_region_copy_and_clear_dirty().
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170421091632.30900-3-kraxel@redhat.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ exec.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++
+ include/exec/memory.h | 47 +++++++++++++++++++++++++++++++
+ include/exec/ram_addr.h | 7 +++++
+ include/qemu/typedefs.h | 1 +
+ memory.c | 17 +++++++++++
+ 5 files changed, 147 insertions(+)
+
+diff --git a/exec.c b/exec.c
+index fcb5b16131..07c2c8ea88 100644
+--- a/exec.c
++++ b/exec.c
+@@ -223,6 +223,12 @@ struct CPUAddressSpace {
+ MemoryListener tcg_as_listener;
+ };
+
++struct DirtyBitmapSnapshot {
++ ram_addr_t start;
++ ram_addr_t end;
++ unsigned long dirty[];
++};
++
+ #endif
+
+ #if !defined(CONFIG_USER_ONLY)
+@@ -1061,6 +1067,75 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start,
+ return dirty;
+ }
+
++DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty
++ (ram_addr_t start, ram_addr_t length, unsigned client)
++{
++ DirtyMemoryBlocks *blocks;
++ unsigned long align = 1UL << (TARGET_PAGE_BITS + BITS_PER_LEVEL);
++ ram_addr_t first = QEMU_ALIGN_DOWN(start, align);
++ ram_addr_t last = QEMU_ALIGN_UP(start + length, align);
++ DirtyBitmapSnapshot *snap;
++ unsigned long page, end, dest;
++
++ snap = g_malloc0(sizeof(*snap) +
++ ((last - first) >> (TARGET_PAGE_BITS + 3)));
++ snap->start = first;
++ snap->end = last;
++
++ page = first >> TARGET_PAGE_BITS;
++ end = last >> TARGET_PAGE_BITS;
++ dest = 0;
++
++ rcu_read_lock();
++
++ blocks = atomic_rcu_read(&ram_list.dirty_memory[client]);
++
++ while (page < end) {
++ unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE;
++ unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE;
++ unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset);
++
++ assert(QEMU_IS_ALIGNED(offset, (1 << BITS_PER_LEVEL)));
++ assert(QEMU_IS_ALIGNED(num, (1 << BITS_PER_LEVEL)));
++ offset >>= BITS_PER_LEVEL;
++
++ bitmap_copy_and_clear_atomic(snap->dirty + dest,
++ blocks->blocks[idx] + offset,
++ num);
++ page += num;
++ dest += num >> BITS_PER_LEVEL;
++ }
++
++ rcu_read_unlock();
++
++ if (tcg_enabled()) {
++ tlb_reset_dirty_range_all(start, length);
++ }
++
++ return snap;
++}
++
++bool cpu_physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap,
++ ram_addr_t start,
++ ram_addr_t length)
++{
++ unsigned long page, end;
++
++ assert(start >= snap->start);
++ assert(start + length <= snap->end);
++
++ end = TARGET_PAGE_ALIGN(start + length - snap->start) >> TARGET_PAGE_BITS;
++ page = (start - snap->start) >> TARGET_PAGE_BITS;
++
++ while (page < end) {
++ if (test_bit(page, snap->dirty)) {
++ return true;
++ }
++ page++;
++ }
++ return false;
++}
++
+ /* Called from RCU critical section */
+ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
+ MemoryRegionSection *section,
+diff --git a/include/exec/memory.h b/include/exec/memory.h
+index f20b191793..1e15e79d00 100644
+--- a/include/exec/memory.h
++++ b/include/exec/memory.h
+@@ -871,6 +871,53 @@ void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
+ */
+ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
+ hwaddr size, unsigned client);
++
++/**
++ * memory_region_snapshot_and_clear_dirty: Get a snapshot of the dirty
++ * bitmap and clear it.
++ *
++ * Creates a snapshot of the dirty bitmap, clears the dirty bitmap and
++ * returns the snapshot. The snapshot can then be used to query dirty
++ * status, using memory_region_snapshot_get_dirty. Unlike
++ * memory_region_test_and_clear_dirty this allows to query the same
++ * page multiple times, which is especially useful for display updates
++ * where the scanlines often are not page aligned.
++ *
++ * The dirty bitmap region which gets copyed into the snapshot (and
++ * cleared afterwards) can be larger than requested. The boundaries
++ * are rounded up/down so complete bitmap longs (covering 64 pages on
++ * 64bit hosts) can be copied over into the bitmap snapshot. Which
++ * isn't a problem for display updates as the extra pages are outside
++ * the visible area, and in case the visible area changes a full
++ * display redraw is due anyway. Should other use cases for this
++ * function emerge we might have to revisit this implementation
++ * detail.
++ *
++ * Use g_free to release DirtyBitmapSnapshot.
++ *
++ * @mr: the memory region being queried.
++ * @addr: the address (relative to the start of the region) being queried.
++ * @size: the size of the range being queried.
++ * @client: the user of the logging information; typically %DIRTY_MEMORY_VGA.
++ */
++DirtyBitmapSnapshot *memory_region_snapshot_and_clear_dirty(MemoryRegion *mr,
++ hwaddr addr,
++ hwaddr size,
++ unsigned client);
++
++/**
++ * memory_region_snapshot_get_dirty: Check whether a range of bytes is dirty
++ * in the specified dirty bitmap snapshot.
++ *
++ * @mr: the memory region being queried.
++ * @snap: the dirty bitmap snapshot
++ * @addr: the address (relative to the start of the region) being queried.
++ * @size: the size of the range being queried.
++ */
++bool memory_region_snapshot_get_dirty(MemoryRegion *mr,
++ DirtyBitmapSnapshot *snap,
++ hwaddr addr, hwaddr size);
++
+ /**
+ * memory_region_sync_dirty_bitmap: Synchronize a region's dirty bitmap with
+ * any external TLBs (e.g. kvm)
+diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
+index b05dc84ab9..2b63d7f59e 100644
+--- a/include/exec/ram_addr.h
++++ b/include/exec/ram_addr.h
+@@ -343,6 +343,13 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start,
+ ram_addr_t length,
+ unsigned client);
+
++DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty
++ (ram_addr_t start, ram_addr_t length, unsigned client);
++
++bool cpu_physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap,
++ ram_addr_t start,
++ ram_addr_t length);
++
+ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
+ ram_addr_t length)
+ {
+diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
+index e95f28cfec..f08d327aec 100644
+--- a/include/qemu/typedefs.h
++++ b/include/qemu/typedefs.h
+@@ -23,6 +23,7 @@ typedef struct CPUAddressSpace CPUAddressSpace;
+ typedef struct CPUState CPUState;
+ typedef struct DeviceListener DeviceListener;
+ typedef struct DeviceState DeviceState;
++typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
+ typedef struct DisplayChangeListener DisplayChangeListener;
+ typedef struct DisplayState DisplayState;
+ typedef struct DisplaySurface DisplaySurface;
+diff --git a/memory.c b/memory.c
+index 4c95aaf39c..8a0648551f 100644
+--- a/memory.c
++++ b/memory.c
+@@ -1716,6 +1716,23 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
+ memory_region_get_ram_addr(mr) + addr, size, client);
+ }
+
++DirtyBitmapSnapshot *memory_region_snapshot_and_clear_dirty(MemoryRegion *mr,
++ hwaddr addr,
++ hwaddr size,
++ unsigned client)
++{
++ assert(mr->ram_block);
++ return cpu_physical_memory_snapshot_and_clear_dirty(
++ memory_region_get_ram_addr(mr) + addr, size, client);
++}
++
++bool memory_region_snapshot_get_dirty(MemoryRegion *mr, DirtyBitmapSnapshot *snap,
++ hwaddr addr, hwaddr size)
++{
++ assert(mr->ram_block);
++ return cpu_physical_memory_snapshot_get_dirty(snap,
++ memory_region_get_ram_addr(mr) + addr, size);
++}
+
+ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
+ {
+--
+2.11.0
+
+++ /dev/null
-From 691689ab216143f5fefd8e229ffd91086b9a261e Mon Sep 17 00:00:00 2001
-From: Ladi Prosek <lprosek@redhat.com>
-Date: Tue, 30 May 2017 10:59:43 +0200
-Subject: [PATCH 07/23] virtio-serial-bus: Unset hotplug handler when unrealize
-
-Virtio serial device controls the lifetime of virtio-serial-bus and
-virtio-serial-bus links back to the device via its hotplug-handler
-property. This extra ref-count prevents the device from getting
-finalized, leaving the VirtIODevice memory listener registered and
-leading to use-after-free later on.
-
-This patch addresses the same issue as Fam Zheng's
-"virtio-scsi: Unset hotplug handler when unrealize"
-only for a different virtio device.
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Ladi Prosek <lprosek@redhat.com>
-Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
-Reviewed-by: Fam Zheng <famz@redhat.com>
----
- hw/char/virtio-serial-bus.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
-index d797a6796e..aa9c11ae92 100644
---- a/hw/char/virtio-serial-bus.c
-+++ b/hw/char/virtio-serial-bus.c
-@@ -1121,6 +1121,9 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
- timer_free(vser->post_load->timer);
- g_free(vser->post_load);
- }
-+
-+ qbus_set_hotplug_handler(BUS(&vser->bus), NULL, errp);
-+
- virtio_cleanup(vdev);
- }
-
---
-2.11.0
-
--- /dev/null
+From cef8fb2b8ea711b6686032f86b1caf1815786aaa Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 21 Apr 2017 11:16:26 +0200
+Subject: [PATCH 08/13] vga: add vga_scanline_invalidated helper
+
+Add vga_scanline_invalidated helper to check whenever a scanline was
+invalidated. Add a sanity check to fix OOB read access for display
+heights larger than 2048.
+
+Only cirrus uses this, for hardware cursor rendering, so having this
+work properly for the first 2048 scanlines only shouldn't be a problem
+as the cirrus can't handle large resolutions anyway. Also changing the
+invalidated_y_table size would break live migration.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170421091632.30900-4-kraxel@redhat.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/display/vga.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index 69c3e1d674..3991b88aac 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1434,6 +1434,14 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
+ }
+ }
+
++static bool vga_scanline_invalidated(VGACommonState *s, int y)
++{
++ if (y >= VGA_MAX_HEIGHT) {
++ return false;
++ }
++ return s->invalidated_y_table[y >> 5] & (1 << (y & 0x1f));
++}
++
+ void vga_sync_dirty_bitmap(VGACommonState *s)
+ {
+ memory_region_sync_dirty_bitmap(&s->vram);
+@@ -1638,8 +1646,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ page1 = addr + bwidth - 1;
+ update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
+ DIRTY_MEMORY_VGA);
+- /* explicit invalidation for the hardware cursor */
+- update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
++ /* explicit invalidation for the hardware cursor (cirrus only) */
++ update |= vga_scanline_invalidated(s, y);
+ if (update) {
+ if (y_start < 0)
+ y_start = y;
+@@ -1686,7 +1694,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ page_max - page_min,
+ DIRTY_MEMORY_VGA);
+ }
+- memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
++ memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
+ }
+
+ static void vga_draw_blank(VGACommonState *s, int full_update)
+--
+2.11.0
+
+++ /dev/null
-From 1b7f7a21084578b528c6a3faac29f46c5dbd6408 Mon Sep 17 00:00:00 2001
-From: Stefan Hajnoczi <stefanha@redhat.com>
-Date: Fri, 2 Jun 2017 10:54:24 +0100
-Subject: [PATCH 08/23] virtio-serial: fix segfault on disconnect
-
-Since commit d4c19cdeeb2f1e474bc426a6da261f1d7346eb5b ("virtio-serial:
-add missing virtio_detach_element() call") the following commands may
-cause QEMU to segfault:
-
- $ qemu -M accel=kvm -cpu host -m 1G \
- -drive if=virtio,file=test.img,format=raw \
- -device virtio-serial-pci,id=virtio-serial0 \
- -chardev socket,id=channel1,path=/tmp/chardev.sock,server,nowait \
- -device virtserialport,chardev=channel1,bus=virtio-serial0.0,id=port1
- $ nc -U /tmp/chardev.sock
- ^C
-
- (guest)$ cat /dev/zero >/dev/vport0p1
-
-The segfault is non-deterministic: if the event loop notices the socket
-has been closed then there is no crash. The disconnect has to happen
-right before QEMU attempts to write data to the socket.
-
-The backtrace is as follows:
-
- Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
- 0x00005555557e0698 in do_flush_queued_data (port=0x5555582cedf0, vq=0x7fffcc854290, vdev=0x55555807b1d0) at hw/char/virtio-serial-bus.c:180
- 180 for (i = port->iov_idx; i < port->elem->out_num; i++) {
- #1 0x000055555580d363 in virtio_queue_notify_vq (vq=0x7fffcc854290) at hw/virtio/virtio.c:1524
- #2 0x000055555580d363 in virtio_queue_host_notifier_read (n=0x7fffcc8542f8) at hw/virtio/virtio.c:2430
- #3 0x0000555555b3482c in aio_dispatch_handlers (ctx=ctx@entry=0x5555566b8c80) at util/aio-posix.c:399
- #4 0x0000555555b350d8 in aio_dispatch (ctx=0x5555566b8c80) at util/aio-posix.c:430
- #5 0x0000555555b3212e in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:261
- #6 0x00007fffde71de52 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
- #7 0x0000555555b34353 in glib_pollfds_poll () at util/main-loop.c:213
- #8 0x0000555555b34353 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:261
- #9 0x0000555555b34353 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:517
- #10 0x0000555555773207 in main_loop () at vl.c:1917
- #11 0x0000555555773207 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4751
-
-The do_flush_queued_data() function does not anticipate chardev close
-events during vsc->have_data(). It expects port->elem to remain
-non-NULL for the duration its for loop.
-
-The fix is simply to return from do_flush_queued_data() if the port
-closes because the close event already frees port->elem and drains the
-virtqueue - there is nothing left for do_flush_queued_data() to do.
-
-Reported-by: Sitong Liu <siliu@redhat.com>
-Reported-by: Min Deng <mdeng@redhat.com>
-Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
----
- hw/char/virtio-serial-bus.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
-index aa9c11ae92..f5bc173844 100644
---- a/hw/char/virtio-serial-bus.c
-+++ b/hw/char/virtio-serial-bus.c
-@@ -186,6 +186,9 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
- port->elem->out_sg[i].iov_base
- + port->iov_offset,
- buf_size);
-+ if (!port->elem) { /* bail if we got disconnected */
-+ return;
-+ }
- if (port->throttled) {
- port->iov_idx = i;
- if (ret > 0) {
---
-2.11.0
-
+++ /dev/null
-From 02b34affd75f205f50445217ad28ef28002e0bf0 Mon Sep 17 00:00:00 2001
-From: Sameeh Jubran <sameeh@daynix.com>
-Date: Mon, 22 May 2017 14:26:22 +0300
-Subject: [PATCH 09/23] e1000e: Fix ICR "Other" causes clear logic
-
-This commit fixes a bug which causes the guest to hang. The bug was
-observed upon a "receive overrun" (bit #6 of the ICR register)
-interrupt which could be triggered post migration in a heavy traffic
-environment. Even though the "receive overrun" bit (#6) is masked out
-by the IMS register (refer to the log below) the driver still receives
-an interrupt as the "receive overrun" bit (#6) causes the "Other" -
-bit #24 of the ICR register - bit to be set as documented below. The
-driver handles the interrupt and clears the "Other" bit (#24) but
-doesn't clear the "receive overrun" bit (#6) which leads to an
-infinite loop. Apparently the Windows driver expects that the "receive
-overrun" bit and other ones - documented below - to be cleared when
-the "Other" bit (#24) is cleared.
-
-So to sum that up:
-1. Bit #6 of the ICR register is set by heavy traffic
-2. As a results of setting bit #6, bit #24 is set
-3. The driver receives an interrupt for bit 24 (it doesn't receieve an
- interrupt for bit #6 as it is masked out by IMS)
-4. The driver handles and clears the interrupt of bit #24
-5. Bit #6 is still set.
-6. 2 happens all over again
-
-The Interrupt Cause Read - ICR register:
-
-The ICR has the "Other" bit - bit #24 - that is set when one or more
-of the following ICR register's bits are set:
-
-LSC - bit #2, RXO - bit #6, MDAC - bit #9, SRPD - bit #16, ACK - bit
-#17, MNG - bit #18
-
-This bug can occur with any of these bits depending on the driver's
-behaviour and the way it configures the device. However, trying to
-reproduce it with any bit other than RX0 is challenging and came to
-failure as the drivers don't implement most of these bits, trying to
-reproduce it with LSC (Link Status Change - bit #2) bit didn't succeed
-too as it seems that Windows handles this bit differently.
-
-Log sample of the storm:
-
-27563@1494850819.411877:e1000e_irq_pending_interrupts ICR PENDING: 0x1000000 (ICR: 0x815000c2, IMS: 0x1a00004)
-27563@1494850819.411900:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
-27563@1494850819.411915:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
-27563@1494850819.412380:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
-27563@1494850819.412395:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
-27563@1494850819.412436:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
-27563@1494850819.412441:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
-27563@1494850819.412998:e1000e_irq_pending_interrupts ICR PENDING: 0x1000000 (ICR: 0x815000c2, IMS: 0x1a00004)
-
-* This bug behaviour wasn't observed with the Linux driver.
-
-This commit solves:
-https://bugzilla.redhat.com/show_bug.cgi?id=1447935
-https://bugzilla.redhat.com/show_bug.cgi?id=1449490
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
-Signed-off-by: Jason Wang <jasowang@redhat.com>
----
- hw/net/e1000e_core.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
-index 28c5be1506..81405640f0 100644
---- a/hw/net/e1000e_core.c
-+++ b/hw/net/e1000e_core.c
-@@ -2454,14 +2454,20 @@ e1000e_set_ics(E1000ECore *core, int index, uint32_t val)
- static void
- e1000e_set_icr(E1000ECore *core, int index, uint32_t val)
- {
-+ uint32_t icr = 0;
- if ((core->mac[ICR] & E1000_ICR_ASSERTED) &&
- (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
- trace_e1000e_irq_icr_process_iame();
- e1000e_clear_ims_bits(core, core->mac[IAM]);
- }
-
-- trace_e1000e_irq_icr_write(val, core->mac[ICR], core->mac[ICR] & ~val);
-- core->mac[ICR] &= ~val;
-+ icr = core->mac[ICR] & ~val;
-+ /* Windows driver expects that the "receive overrun" bit and other
-+ * ones to be cleared when the "Other" bit (#24) is cleared.
-+ */
-+ icr = (val & E1000_ICR_OTHER) ? (icr & ~E1000_ICR_OTHER_CAUSES) : icr;
-+ trace_e1000e_irq_icr_write(val, core->mac[ICR], icr);
-+ core->mac[ICR] = icr;
- e1000e_update_interrupt_state(core);
- }
-
---
-2.11.0
-
--- /dev/null
+From f7f03687246e62d8efed10ee5ce8c571fc3debc4 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 21 Apr 2017 11:16:27 +0200
+Subject: [PATCH 09/13] vga: make display updates thread safe.
+
+The vga code clears the dirty bits *after* reading the framebuffer
+memory. So if the guest framebuffer updates hits the race window
+between vga reading the framebuffer and vga clearing the dirty bits
+vga will miss that update
+
+Fix it by using the new memory_region_copy_and_clear_dirty()
+memory_region_copy_get_dirty() functions. That way we clear the
+dirty bitmap before reading the framebuffer. Any guest display
+updates happening in parallel will be properly tracked in the
+dirty bitmap then and the next display refresh will pick them up.
+
+Problem triggers with mttcg only. Before mttcg was merged tcg
+never ran in parallel to vga emulation. Using kvm will hide the
+problem too, due to qemu operating on a userspace copy of the
+kernel's dirty bitmap.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170421091632.30900-5-kraxel@redhat.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/display/vga.c | 36 +++++++++++++++++-------------------
+ 1 file changed, 17 insertions(+), 19 deletions(-)
+
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index 3991b88aac..b2516c8d21 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1465,7 +1465,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ DisplaySurface *surface = qemu_console_surface(s->con);
+ int y1, y, update, linesize, y_start, double_scan, mask, depth;
+ int width, height, shift_control, line_offset, bwidth, bits;
+- ram_addr_t page0, page1, page_min, page_max;
++ ram_addr_t page0, page1;
++ DirtyBitmapSnapshot *snap = NULL;
+ int disp_width, multi_scan, multi_run;
+ uint8_t *d;
+ uint32_t v, addr1, addr;
+@@ -1480,9 +1481,6 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+
+ full_update |= update_basic_params(s);
+
+- if (!full_update)
+- vga_sync_dirty_bitmap(s);
+-
+ s->get_resolution(s, &width, &height);
+ disp_width = width;
+
+@@ -1625,11 +1623,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ addr1 = (s->start_addr * 4);
+ bwidth = (width * bits + 7) / 8;
+ y_start = -1;
+- page_min = -1;
+- page_max = 0;
+ d = surface_data(surface);
+ linesize = surface_stride(surface);
+ y1 = 0;
++
++ if (!full_update) {
++ vga_sync_dirty_bitmap(s);
++ snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1,
++ bwidth * height,
++ DIRTY_MEMORY_VGA);
++ }
++
+ for(y = 0; y < height; y++) {
+ addr = addr1;
+ if (!(s->cr[VGA_CRTC_MODE] & 1)) {
+@@ -1644,17 +1648,17 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ update = full_update;
+ page0 = addr;
+ page1 = addr + bwidth - 1;
+- update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
+- DIRTY_MEMORY_VGA);
++ if (full_update) {
++ update = 1;
++ } else {
++ update = memory_region_snapshot_get_dirty(&s->vram, snap,
++ page0, page1 - page0);
++ }
+ /* explicit invalidation for the hardware cursor (cirrus only) */
+ update |= vga_scanline_invalidated(s, y);
+ if (update) {
+ if (y_start < 0)
+ y_start = y;
+- if (page0 < page_min)
+- page_min = page0;
+- if (page1 > page_max)
+- page_max = page1;
+ if (!(is_buffer_shared(surface))) {
+ vga_draw_line(s, d, s->vram_ptr + addr, width);
+ if (s->cursor_draw_line)
+@@ -1687,13 +1691,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ dpy_gfx_update(s->con, 0, y_start,
+ disp_width, y - y_start);
+ }
+- /* reset modified pages */
+- if (page_max >= page_min) {
+- memory_region_reset_dirty(&s->vram,
+- page_min,
+- page_max - page_min,
+- DIRTY_MEMORY_VGA);
+- }
++ g_free(snap);
+ memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
+ }
+
+--
+2.11.0
+
+++ /dev/null
-From 9c4164d74133304aaf7d77001e5ac8a22150df44 Mon Sep 17 00:00:00 2001
-From: Kevin Wolf <kwolf@redhat.com>
-Date: Mon, 29 May 2017 14:08:32 +0200
-Subject: [PATCH 10/23] mirror: Drop permissions on s->target on completion
-
-This fixes an assertion failure that was triggered by qemu-iotests 129
-on some CI host, while the same test case didn't seem to fail on other
-hosts.
-
-Essentially the problem is that the blk_unref(s->target) in
-mirror_exit() doesn't necessarily mean that the BlockBackend goes away
-immediately. It is possible that the job completion was triggered nested
-in mirror_drain(), which looks like this:
-
- BlockBackend *target = s->target;
- blk_ref(target);
- blk_drain(target);
- blk_unref(target);
-
-In this case, the write permissions for s->target are retained until
-after blk_drain(), which makes removing mirror_top_bs fail for the
-active commit case (can't have a writable backing file in the chain
-without the filter driver).
-
-Explicitly dropping the permissions first means that the additional
-reference doesn't hurt and the job can complete successfully even if
-called from the nested blk_drain().
-
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
-Reviewed-by: Max Reitz <mreitz@redhat.com>
----
- block/mirror.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/block/mirror.c b/block/mirror.c
-index 164438f422..779b753b8a 100644
---- a/block/mirror.c
-+++ b/block/mirror.c
-@@ -514,7 +514,12 @@ static void mirror_exit(BlockJob *job, void *opaque)
-
- /* Remove target parent that still uses BLK_PERM_WRITE/RESIZE before
- * inserting target_bs at s->to_replace, where we might not be able to get
-- * these permissions. */
-+ * these permissions.
-+ *
-+ * Note that blk_unref() alone doesn't necessarily drop permissions because
-+ * we might be running nested inside mirror_drain(), which takes an extra
-+ * reference, so use an explicit blk_set_perm() first. */
-+ blk_set_perm(s->target, 0, BLK_PERM_ALL, &error_abort);
- blk_unref(s->target);
- s->target = NULL;
-
---
-2.11.0
-
--- /dev/null
+From 616f285a074869fd79bc26509a0bd50e6e04e39d Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 9 May 2017 12:48:39 +0200
+Subject: [PATCH 10/13] vga: fix display update region calculation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+vga display update mis-calculated the region for the dirty bitmap
+snapshot in case the scanlines are padded. This can triggere an
+assert in cpu_physical_memory_snapshot_get_dirty().
+
+Fixes: fec5e8c92becad223df9d972770522f64aafdb72
+Reported-by: Kevin Wolf <kwolf@redhat.com>
+Reported-by: 李强 <liqiang6-s@360.cn>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170509104839.19415-1-kraxel@redhat.com
+---
+ hw/display/vga.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index b2516c8d21..dcc95f88e2 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1630,7 +1630,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ if (!full_update) {
+ vga_sync_dirty_bitmap(s);
+ snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1,
+- bwidth * height,
++ line_offset * height,
+ DIRTY_MEMORY_VGA);
+ }
+
+--
+2.11.0
+
--- /dev/null
+From c93a020a1c6a37398d124f063af23d6acb3eb5cb Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 1 Sep 2017 14:57:38 +0200
+Subject: [PATCH 11/13] vga: fix display update region calculation (split
+ screen)
+
+vga display update mis-calculated the region for the dirty bitmap
+snapshot in case split screen mode is used. This can trigger an
+assert in cpu_physical_memory_snapshot_get_dirty().
+
+Impact: DoS for privileged guest users.
+
+Fixes: CVE-2017-13673
+Fixes: fec5e8c92becad223df9d972770522f64aafdb72
+Cc: P J P <ppandit@redhat.com>
+Reported-by: David Buchanan <d@vidbuchanan.co.uk>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170828123307.15392-1-kraxel@redhat.com
+---
+ hw/display/vga.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index dcc95f88e2..533d8d7895 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1628,9 +1628,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ y1 = 0;
+
+ if (!full_update) {
++ ram_addr_t region_start = addr1;
++ ram_addr_t region_end = addr1 + line_offset * height;
+ vga_sync_dirty_bitmap(s);
+- snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1,
+- line_offset * height,
++ if (s->line_compare < height) {
++ /* split screen mode */
++ region_start = 0;
++ }
++ snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
++ region_end - region_start,
+ DIRTY_MEMORY_VGA);
+ }
+
+--
+2.11.0
+
+++ /dev/null
-From 1e709e6e073c7907676ea9263a1f92b1bd5fc9ac 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 11/23] 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(-)
-
-diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
-index 75575461e2..4a106da856 100644
---- a/hw/scsi/vmw_pvscsi.c
-+++ b/hw/scsi/vmw_pvscsi.c
-@@ -202,7 +202,7 @@ pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
- uint32_t len_log2;
- uint32_t ring_size;
-
-- if (ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) {
-+ 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;
---
-2.11.0
-
+++ /dev/null
-From 74f9fd9420fadd64a42ee8de780dc6de61864ea8 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 28 Apr 2017 09:56:12 +0200
-Subject: [PATCH 12/23] 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.
-
-Fixes: CVE-2017-8309
-Cc: P J P <ppandit@redhat.com>
-Cc: Huawei PSIRT <PSIRT@huawei.com>
-Reported-by: "Jiangxin (hunter, SCC)" <jiangxin1@huawei.com>
-Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-Reviewed-by: Prasad J Pandit <pjp@fedoraproject.org>
-Message-id: 20170428075612.9997-1-kraxel@redhat.com
----
- audio/audio.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/audio/audio.c b/audio/audio.c
-index c8898d8422..beafed209b 100644
---- a/audio/audio.c
-+++ b/audio/audio.c
-@@ -2028,6 +2028,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;
---
-2.11.0
-
--- /dev/null
+From 15c2b7e06a85dd78c7d45b3703639735eee09c01 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 1 Sep 2017 14:57:39 +0200
+Subject: [PATCH 12/13] vga: stop passing pointers to vga_draw_line* functions
+
+Instead pass around the address (aka offset into vga memory).
+Add vga_read_* helper functions which apply vbe_size_mask to
+the address, to make sure the address stays within the valid
+range, similar to the cirrus blitter fixes (commits ffaf857778
+and 026aeffcb4).
+
+Impact: DoS for privileged guest users. qemu crashes with
+a segfault, when hitting the guard page after vga memory
+allocation, while reading vga memory for display updates.
+
+Fixes: CVE-2017-13672
+Cc: P J P <ppandit@redhat.com>
+Reported-by: David Buchanan <d@vidbuchanan.co.uk>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Message-id: 20170828122906.18993-1-kraxel@redhat.com
+---
+ hw/display/vga-helpers.h | 202 ++++++++++++++++++++++++++---------------------
+ hw/display/vga.c | 5 +-
+ hw/display/vga_int.h | 1 +
+ 3 files changed, 114 insertions(+), 94 deletions(-)
+
+diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h
+index 94f6de2046..5a752b3f9e 100644
+--- a/hw/display/vga-helpers.h
++++ b/hw/display/vga-helpers.h
+@@ -95,20 +95,46 @@ static void vga_draw_glyph9(uint8_t *d, int linesize,
+ } while (--h);
+ }
+
++static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr)
++{
++ return vga->vram_ptr[addr & vga->vbe_size_mask];
++}
++
++static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr)
++{
++ uint32_t offset = addr & vga->vbe_size_mask & ~1;
++ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
++ return lduw_le_p(ptr);
++}
++
++static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr)
++{
++ uint32_t offset = addr & vga->vbe_size_mask & ~1;
++ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
++ return lduw_be_p(ptr);
++}
++
++static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr)
++{
++ uint32_t offset = addr & vga->vbe_size_mask & ~3;
++ uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset);
++ return ldl_le_p(ptr);
++}
++
+ /*
+ * 4 color mode
+ */
+-static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line2(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ uint32_t plane_mask, *palette, data, v;
+ int x;
+
+- palette = s1->last_palette;
+- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
++ palette = vga->last_palette;
++ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+- data = ((uint32_t *)s)[0];
++ data = vga_read_dword_le(vga, addr);
+ data &= plane_mask;
+ v = expand2[GET_PLANE(data, 0)];
+ v |= expand2[GET_PLANE(data, 2)] << 2;
+@@ -124,7 +150,7 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
+ ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
+ ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
+ d += 32;
+- s += 4;
++ addr += 4;
+ }
+ }
+
+@@ -134,17 +160,17 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
+ /*
+ * 4 color mode, dup2 horizontal
+ */
+-static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ uint32_t plane_mask, *palette, data, v;
+ int x;
+
+- palette = s1->last_palette;
+- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
++ palette = vga->last_palette;
++ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+- data = ((uint32_t *)s)[0];
++ data = vga_read_dword_le(vga, addr);
+ data &= plane_mask;
+ v = expand2[GET_PLANE(data, 0)];
+ v |= expand2[GET_PLANE(data, 2)] << 2;
+@@ -160,24 +186,24 @@ static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
+ PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
+ PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
+ d += 64;
+- s += 4;
++ addr += 4;
+ }
+ }
+
+ /*
+ * 16 color mode
+ */
+-static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line4(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ uint32_t plane_mask, data, v, *palette;
+ int x;
+
+- palette = s1->last_palette;
+- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
++ palette = vga->last_palette;
++ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+- data = ((uint32_t *)s)[0];
++ data = vga_read_dword_le(vga, addr);
+ data &= plane_mask;
+ v = expand4[GET_PLANE(data, 0)];
+ v |= expand4[GET_PLANE(data, 1)] << 1;
+@@ -192,24 +218,24 @@ static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
+ ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
+ ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
+ d += 32;
+- s += 4;
++ addr += 4;
+ }
+ }
+
+ /*
+ * 16 color mode, dup2 horizontal
+ */
+-static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ uint32_t plane_mask, data, v, *palette;
+ int x;
+
+- palette = s1->last_palette;
+- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
++ palette = vga->last_palette;
++ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+- data = ((uint32_t *)s)[0];
++ data = vga_read_dword_le(vga, addr);
+ data &= plane_mask;
+ v = expand4[GET_PLANE(data, 0)];
+ v |= expand4[GET_PLANE(data, 1)] << 1;
+@@ -224,7 +250,7 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
+ PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
+ PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
+ d += 64;
+- s += 4;
++ addr += 4;
+ }
+ }
+
+@@ -233,21 +259,21 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
+ *
+ * XXX: add plane_mask support (never used in standard VGA modes)
+ */
+-static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ uint32_t *palette;
+ int x;
+
+- palette = s1->last_palette;
++ palette = vga->last_palette;
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+- PUT_PIXEL2(d, 0, palette[s[0]]);
+- PUT_PIXEL2(d, 1, palette[s[1]]);
+- PUT_PIXEL2(d, 2, palette[s[2]]);
+- PUT_PIXEL2(d, 3, palette[s[3]]);
++ PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]);
++ PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]);
++ PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]);
++ PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]);
+ d += 32;
+- s += 4;
++ addr += 4;
+ }
+ }
+
+@@ -256,63 +282,63 @@ static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d,
+ *
+ * XXX: add plane_mask support (never used in standard VGA modes)
+ */
+-static void vga_draw_line8(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line8(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ uint32_t *palette;
+ int x;
+
+- palette = s1->last_palette;
++ palette = vga->last_palette;
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+- ((uint32_t *)d)[0] = palette[s[0]];
+- ((uint32_t *)d)[1] = palette[s[1]];
+- ((uint32_t *)d)[2] = palette[s[2]];
+- ((uint32_t *)d)[3] = palette[s[3]];
+- ((uint32_t *)d)[4] = palette[s[4]];
+- ((uint32_t *)d)[5] = palette[s[5]];
+- ((uint32_t *)d)[6] = palette[s[6]];
+- ((uint32_t *)d)[7] = palette[s[7]];
++ ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
++ ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)];
++ ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)];
++ ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)];
++ ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)];
++ ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)];
++ ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)];
++ ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)];
+ d += 32;
+- s += 8;
++ addr += 8;
+ }
+ }
+
+ /*
+ * 15 bit color
+ */
+-static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ int w;
+ uint32_t v, r, g, b;
+
+ w = width;
+ do {
+- v = lduw_le_p((void *)s);
++ v = vga_read_word_le(vga, addr);
+ r = (v >> 7) & 0xf8;
+ g = (v >> 2) & 0xf8;
+ b = (v << 3) & 0xf8;
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 2;
++ addr += 2;
+ d += 4;
+ } while (--w != 0);
+ }
+
+-static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ int w;
+ uint32_t v, r, g, b;
+
+ w = width;
+ do {
+- v = lduw_be_p((void *)s);
++ v = vga_read_word_be(vga, addr);
+ r = (v >> 7) & 0xf8;
+ g = (v >> 2) & 0xf8;
+ b = (v << 3) & 0xf8;
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 2;
++ addr += 2;
+ d += 4;
+ } while (--w != 0);
+ }
+@@ -320,38 +346,38 @@ static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d,
+ /*
+ * 16 bit color
+ */
+-static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ int w;
+ uint32_t v, r, g, b;
+
+ w = width;
+ do {
+- v = lduw_le_p((void *)s);
++ v = vga_read_word_le(vga, addr);
+ r = (v >> 8) & 0xf8;
+ g = (v >> 3) & 0xfc;
+ b = (v << 3) & 0xf8;
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 2;
++ addr += 2;
+ d += 4;
+ } while (--w != 0);
+ }
+
+-static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ int w;
+ uint32_t v, r, g, b;
+
+ w = width;
+ do {
+- v = lduw_be_p((void *)s);
++ v = vga_read_word_be(vga, addr);
+ r = (v >> 8) & 0xf8;
+ g = (v >> 3) & 0xfc;
+ b = (v << 3) & 0xf8;
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 2;
++ addr += 2;
+ d += 4;
+ } while (--w != 0);
+ }
+@@ -359,36 +385,36 @@ static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d,
+ /*
+ * 24 bit color
+ */
+-static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ int w;
+ uint32_t r, g, b;
+
+ w = width;
+ do {
+- b = s[0];
+- g = s[1];
+- r = s[2];
++ b = vga_read_byte(vga, addr + 0);
++ g = vga_read_byte(vga, addr + 1);
++ r = vga_read_byte(vga, addr + 2);
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 3;
++ addr += 3;
+ d += 4;
+ } while (--w != 0);
+ }
+
+-static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+ int w;
+ uint32_t r, g, b;
+
+ w = width;
+ do {
+- r = s[0];
+- g = s[1];
+- b = s[2];
++ r = vga_read_byte(vga, addr + 0);
++ g = vga_read_byte(vga, addr + 1);
++ b = vga_read_byte(vga, addr + 2);
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 3;
++ addr += 3;
+ d += 4;
+ } while (--w != 0);
+ }
+@@ -396,44 +422,36 @@ static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d,
+ /*
+ * 32 bit color
+ */
+-static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+-#ifndef HOST_WORDS_BIGENDIAN
+- memcpy(d, s, width * 4);
+-#else
+ int w;
+ uint32_t r, g, b;
+
+ w = width;
+ do {
+- b = s[0];
+- g = s[1];
+- r = s[2];
++ b = vga_read_byte(vga, addr + 0);
++ g = vga_read_byte(vga, addr + 1);
++ r = vga_read_byte(vga, addr + 2);
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 4;
++ addr += 4;
+ d += 4;
+ } while (--w != 0);
+-#endif
+ }
+
+-static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width)
++static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
++ uint32_t addr, int width)
+ {
+-#ifdef HOST_WORDS_BIGENDIAN
+- memcpy(d, s, width * 4);
+-#else
+ int w;
+ uint32_t r, g, b;
+
+ w = width;
+ do {
+- r = s[1];
+- g = s[2];
+- b = s[3];
++ r = vga_read_byte(vga, addr + 1);
++ g = vga_read_byte(vga, addr + 2);
++ b = vga_read_byte(vga, addr + 3);
+ ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
+- s += 4;
++ addr += 4;
+ d += 4;
+ } while (--w != 0);
+-#endif
+ }
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index 533d8d7895..13e4a5d55d 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1005,7 +1005,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
+ }
+
+ typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
+- const uint8_t *s, int width);
++ uint32_t srcaddr, int width);
+
+ #include "vga-helpers.h"
+
+@@ -1666,7 +1666,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
+ if (y_start < 0)
+ y_start = y;
+ if (!(is_buffer_shared(surface))) {
+- vga_draw_line(s, d, s->vram_ptr + addr, width);
++ vga_draw_line(s, d, addr, width);
+ if (s->cursor_draw_line)
+ s->cursor_draw_line(s, d, y);
+ }
+@@ -2170,6 +2170,7 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
+ if (!s->vbe_size) {
+ s->vbe_size = s->vram_size;
+ }
++ s->vbe_size_mask = s->vbe_size - 1;
+
+ s->is_vbe_vmstate = 1;
+ memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size,
+diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
+index dd6c958da3..ad34a1f048 100644
+--- a/hw/display/vga_int.h
++++ b/hw/display/vga_int.h
+@@ -94,6 +94,7 @@ typedef struct VGACommonState {
+ uint32_t vram_size;
+ uint32_t vram_size_mb; /* property */
+ uint32_t vbe_size;
++ uint32_t vbe_size_mask;
+ uint32_t latch;
+ bool has_chain4_alias;
+ MemoryRegion chain4_alias;
+--
+2.11.0
+
+++ /dev/null
-From e96b198df364a2918896c41a9759b38aaebcf211 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Fri, 28 Apr 2017 10:42:37 +0200
-Subject: [PATCH 13/23] 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(-)
-
-diff --git a/ui/input.c b/ui/input.c
-index ed88cda6d6..fb1f404095 100644
---- a/ui/input.c
-+++ b/ui/input.c
-@@ -41,6 +41,8 @@ static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
- 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)
-@@ -268,6 +270,7 @@ static void qemu_input_queue_process(void *opaque)
- break;
- }
- QTAILQ_REMOVE(queue, item, node);
-+ queue_count--;
- g_free(item);
- }
- }
-@@ -282,6 +285,7 @@ static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
- 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)
-@@ -298,6 +302,7 @@ static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
- item->src = src;
- item->evt = evt;
- QTAILQ_INSERT_TAIL(queue, item, node);
-+ queue_count++;
- }
-
- static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
-@@ -306,6 +311,7 @@ static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
-
- item->type = QEMU_INPUT_QUEUE_SYNC;
- QTAILQ_INSERT_TAIL(queue, item, node);
-+ queue_count++;
- }
-
- void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
-@@ -381,7 +387,7 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
- 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);
- }
-@@ -409,8 +415,10 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms)
- 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)
---
-2.11.0
-
--- /dev/null
+From fff4299fb7be857e93ff5c6ea0f871c62d159c1d Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp@fedoraproject.org>
+Date: Thu, 7 Sep 2017 12:02:56 +0530
+Subject: [PATCH 13/13] 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.
+
+This is CVE-2017-14167.
+
+Reported-by: Thomas Garnier <thgarnie@google.com>
+Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
+---
+ hw/i386/multiboot.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
+index f13e23139b..22688d376d 100644
+--- a/hw/i386/multiboot.c
++++ b/hw/i386/multiboot.c
+@@ -221,15 +221,34 @@ int load_multiboot(FWCfgState *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;
+ }
+--
+2.11.0
+
+++ /dev/null
-From c442fb4a11d8dc527c90bf90a1fd1b15646f4c57 Mon Sep 17 00:00:00 2001
-From: Prasad J Pandit <pjp@fedoraproject.org>
-Date: Mon, 24 Apr 2017 17:36:34 +0530
-Subject: [PATCH 14/23] scsi: avoid an off-by-one error in megasas_mmio_write
-
-While reading magic sequence(MFI_SEQ) in megasas_mmio_write,
-an off-by-one error could occur as 's->adp_reset' index is not
-reset after reading the last sequence.
-
-Reported-by: YY Z <bigbird475958471@gmail.com>
-Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
-Message-Id: <20170424120634.12268-1-ppandit@redhat.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- hw/scsi/megasas.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
-index 84b8caf901..804122ab05 100644
---- a/hw/scsi/megasas.c
-+++ b/hw/scsi/megasas.c
-@@ -2138,15 +2138,15 @@ static void megasas_mmio_write(void *opaque, hwaddr addr,
- case MFI_SEQ:
- trace_megasas_mmio_writel("MFI_SEQ", val);
- /* Magic sequence to start ADP reset */
-- if (adp_reset_seq[s->adp_reset] == val) {
-- s->adp_reset++;
-+ if (adp_reset_seq[s->adp_reset++] == val) {
-+ if (s->adp_reset == 6) {
-+ s->adp_reset = 0;
-+ s->diag = MFI_DIAG_WRITE_ENABLE;
-+ }
- } else {
- s->adp_reset = 0;
- s->diag = 0;
- }
-- if (s->adp_reset == 6) {
-- s->diag = MFI_DIAG_WRITE_ENABLE;
-- }
- break;
- case MFI_DIAG:
- trace_megasas_mmio_writel("MFI_DIAG", val);
---
-2.11.0
-
+++ /dev/null
-From 209fb3054000bd3a45da63e3758b9c220fba0a25 Mon Sep 17 00:00:00 2001
-From: Greg Kurz <groug@kaod.org>
-Date: Fri, 5 May 2017 14:48:08 +0200
-Subject: [PATCH 15/23] 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(-)
-
-diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
-index 7a0c383e7e..226234d386 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;
-@@ -1092,6 +1127,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, "/")) {
-@@ -1112,6 +1153,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;
-@@ -1202,6 +1250,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
-
+++ /dev/null
-From 95a82526f2bfd3e9f0ac65a1f2ed505b2429d9de Mon Sep 17 00:00:00 2001
-From: Paolo Bonzini <pbonzini@redhat.com>
-Date: Thu, 1 Jun 2017 17:18:23 +0200
-Subject: [PATCH 16/23] 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(-)
-
-diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
-index 804122ab05..887958481b 100644
---- a/hw/scsi/megasas.c
-+++ b/hw/scsi/megasas.c
-@@ -63,6 +63,7 @@ typedef struct MegasasCmd {
-
- hwaddr pa;
- hwaddr pa_size;
-+ uint32_t dcmd_opcode;
- union mfi_frame *frame;
- SCSIRequest *req;
- QEMUSGList qsg;
-@@ -511,6 +512,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
- cmd->context &= (uint64_t)0xFFFFFFFF;
- }
- cmd->count = count;
-+ cmd->dcmd_opcode = -1;
- s->busy++;
-
- if (s->consumer_pa) {
-@@ -1559,22 +1561,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);
-@@ -1589,13 +1590,11 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd)
- 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);
-- 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;
-@@ -1603,7 +1602,7 @@ static int megasas_finish_internal_dcmd(MegasasCmd *cmd,
- 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;
- }
-@@ -1824,7 +1823,6 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
- {
- MegasasCmd *cmd = req->hba_private;
- uint8_t *buf;
-- uint32_t opcode;
-
- trace_megasas_io_complete(cmd->index, len);
-
-@@ -1834,8 +1832,7 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
- }
-
- 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) {
-@@ -1846,7 +1843,7 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len)
- 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) {
---
-2.11.0
-
+++ /dev/null
-From d312b31b5c5e8e36c6e283bdb04b4784dd2e023b Mon Sep 17 00:00:00 2001
-From: Paolo Bonzini <pbonzini@redhat.com>
-Date: Thu, 1 Jun 2017 17:26:14 +0200
-Subject: [PATCH 17/23] 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 ++++++++++++++++---------------
- 1 file changed, 16 insertions(+), 15 deletions(-)
-
-diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
-index 887958481b..a0cafe3010 100644
---- a/hw/scsi/megasas.c
-+++ b/hw/scsi/megasas.c
-@@ -607,6 +607,9 @@ static void megasas_reset_frames(MegasasState *s)
- static void megasas_abort_command(MegasasCmd *cmd)
- {
- /* Never abort internal commands. */
-+ if (cmd->dcmd_opcode != -1) {
-+ return;
-+ }
- if (cmd->req != NULL) {
- scsi_req_cancel(cmd->req);
- }
-@@ -1014,7 +1017,6 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
- 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) {
-@@ -1023,8 +1025,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
- 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);
-@@ -1033,26 +1035,26 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
- }
- 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;
- }
-@@ -1214,7 +1216,6 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
- 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;
- uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
- uint64_t ld_size;
-@@ -1223,8 +1224,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
- cmd->iov_buf = g_malloc0(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);
-@@ -1233,10 +1234,10 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
- }
- 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;
- }
-@@ -1865,7 +1866,7 @@ static void megasas_command_complete(SCSIRequest *req, uint32_t status,
- return;
- }
-
-- if (cmd->req == NULL) {
-+ if (cmd->dcmd_opcode != -1) {
- /*
- * Internal command complete
- */
---
-2.11.0
-
+++ /dev/null
-From 4dbc47f9d71b8a17b174ffed314988aa99dc4775 Mon Sep 17 00:00:00 2001
-From: Eric Blake <eblake@redhat.com>
-Date: Fri, 26 May 2017 22:04:21 -0500
-Subject: [PATCH 18/23] nbd: Fully initialize client in case of failed
- negotiation
-
-If a non-NBD client connects to qemu-nbd, we would end up with
-a SIGSEGV in nbd_client_put() because we were trying to
-unregister the client's association to the export, even though
-we skipped inserting the client into that list. Easy trigger
-in two terminals:
-
-$ qemu-nbd -p 30001 --format=raw file
-$ nmap 127.0.0.1 -p 30001
-
-nmap claims that it thinks it connected to a pago-services1
-server (which probably means nmap could be updated to learn the
-NBD protocol and give a more accurate diagnosis of the open
-port - but that's not our problem), then terminates immediately,
-so our call to nbd_negotiate() fails. The fix is to reorder
-nbd_co_client_start() to ensure that all initialization occurs
-before we ever try talking to a client in nbd_negotiate(), so
-that the teardown sequence on negotiation failure doesn't fault
-while dereferencing a half-initialized object.
-
-While debugging this, I also noticed that nbd_update_server_watch()
-called by nbd_client_closed() was still adding a channel to accept
-the next client, even when the state was no longer RUNNING. That
-is fixed by making nbd_can_accept() pay attention to the current
-state.
-
-Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
-
-Signed-off-by: Eric Blake <eblake@redhat.com>
-Message-Id: <20170527030421.28366-1-eblake@redhat.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- nbd/server.c | 8 +++-----
- qemu-nbd.c | 2 +-
- 2 files changed, 4 insertions(+), 6 deletions(-)
-
-diff --git a/nbd/server.c b/nbd/server.c
-index 924a1fe2db..edfda84d43 100644
---- a/nbd/server.c
-+++ b/nbd/server.c
-@@ -1376,16 +1376,14 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
-
- if (exp) {
- nbd_export_get(exp);
-+ QTAILQ_INSERT_TAIL(&exp->clients, client, next);
- }
-+ qemu_co_mutex_init(&client->send_lock);
-+
- if (nbd_negotiate(data)) {
- client_close(client);
- goto out;
- }
-- qemu_co_mutex_init(&client->send_lock);
--
-- if (exp) {
-- QTAILQ_INSERT_TAIL(&exp->clients, client, next);
-- }
-
- nbd_client_receive_next_request(client);
-
-diff --git a/qemu-nbd.c b/qemu-nbd.c
-index e080fb7c75..b44764eb87 100644
---- a/qemu-nbd.c
-+++ b/qemu-nbd.c
-@@ -324,7 +324,7 @@ out:
-
- static int nbd_can_accept(void)
- {
-- return nb_fds < shared;
-+ return state == RUNNING && nb_fds < shared;
- }
-
- static void nbd_export_closed(NBDExport *exp)
---
-2.11.0
-
+++ /dev/null
-From 97c7e46a9f8ae03e24df1d18d3b5e9df420f39ce Mon Sep 17 00:00:00 2001
-From: Eric Blake <eblake@redhat.com>
-Date: Thu, 8 Jun 2017 17:26:17 -0500
-Subject: [PATCH 19/23] nbd: Fix regression on resiliency to port scan
-
-Back in qemu 2.5, qemu-nbd was immune to port probes (a transient
-server would not quit, regardless of how many probe connections
-came and went, until a connection actually negotiated). But we
-broke that in commit ee7d7aa when removing the return value to
-nbd_client_new(), although that patch also introduced a bug causing
-an assertion failure on a client that fails negotiation. We then
-made it worse during refactoring in commit 1a6245a (a segfault
-before we could even assert); the (masked) assertion was cleaned
-up in d3780c2 (still in 2.6), and just recently we finally fixed
-the segfault ("nbd: Fully intialize client in case of failed
-negotiation"). But that still means that ever since we added
-TLS support to qemu-nbd, we have been vulnerable to an ill-timed
-port-scan being able to cause a denial of service by taking down
-qemu-nbd before a real client has a chance to connect.
-
-Since negotiation is now handled asynchronously via coroutines,
-we no longer have a synchronous point of return by re-adding a
-return value to nbd_client_new(). So this patch instead wires
-things up to pass the negotiation status through the close_fn
-callback function.
-
-Simple test across two terminals:
-$ qemu-nbd -f raw -p 30001 file
-$ nmap 127.0.0.1 -p 30001 && \
- qemu-io -c 'r 0 512' -f raw nbd://localhost:30001
-
-Note that this patch does not change what constitutes successful
-negotiation (thus, a client must enter transmission phase before
-that client can be considered as a reason to terminate the server
-when the connection ends). Perhaps we may want to tweak things
-in a later patch to also treat a client that uses NBD_OPT_ABORT
-as being a 'successful' negotiation (the client correctly talked
-the NBD protocol, and informed us it was not going to use our
-export after all), but that's a discussion for another day.
-
-Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
-
-Signed-off-by: Eric Blake <eblake@redhat.com>
-Message-Id: <20170608222617.20376-1-eblake@redhat.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- blockdev-nbd.c | 6 +++++-
- include/block/nbd.h | 2 +-
- nbd/server.c | 24 +++++++++++++++---------
- qemu-nbd.c | 4 ++--
- 4 files changed, 23 insertions(+), 13 deletions(-)
-
-diff --git a/blockdev-nbd.c b/blockdev-nbd.c
-index 8a11807df3..8d7284ac56 100644
---- a/blockdev-nbd.c
-+++ b/blockdev-nbd.c
-@@ -27,6 +27,10 @@ typedef struct NBDServerData {
-
- static NBDServerData *nbd_server;
-
-+static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
-+{
-+ nbd_client_put(client);
-+}
-
- static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
- gpointer opaque)
-@@ -46,7 +50,7 @@ static gboolean nbd_accept(QIOChannel *ioc, GIOCondition condition,
- qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
- nbd_client_new(NULL, cioc,
- nbd_server->tlscreds, NULL,
-- nbd_client_put);
-+ nbd_blockdev_client_closed);
- object_unref(OBJECT(cioc));
- return TRUE;
- }
-diff --git a/include/block/nbd.h b/include/block/nbd.h
-index 3e373f0498..b69c30d063 100644
---- a/include/block/nbd.h
-+++ b/include/block/nbd.h
-@@ -160,7 +160,7 @@ void nbd_client_new(NBDExport *exp,
- QIOChannelSocket *sioc,
- QCryptoTLSCreds *tlscreds,
- const char *tlsaclname,
-- void (*close)(NBDClient *));
-+ void (*close_fn)(NBDClient *, bool));
- void nbd_client_get(NBDClient *client);
- void nbd_client_put(NBDClient *client);
-
-diff --git a/nbd/server.c b/nbd/server.c
-index edfda84d43..a98bb21a0a 100644
---- a/nbd/server.c
-+++ b/nbd/server.c
-@@ -81,7 +81,7 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
-
- struct NBDClient {
- int refcount;
-- void (*close)(NBDClient *client);
-+ void (*close_fn)(NBDClient *client, bool negotiated);
-
- bool no_zeroes;
- NBDExport *exp;
-@@ -796,7 +796,7 @@ void nbd_client_put(NBDClient *client)
- }
- }
-
--static void client_close(NBDClient *client)
-+static void client_close(NBDClient *client, bool negotiated)
- {
- if (client->closing) {
- return;
-@@ -811,8 +811,8 @@ static void client_close(NBDClient *client)
- NULL);
-
- /* Also tell the client, so that they release their reference. */
-- if (client->close) {
-- client->close(client);
-+ if (client->close_fn) {
-+ client->close_fn(client, negotiated);
- }
- }
-
-@@ -993,7 +993,7 @@ void nbd_export_close(NBDExport *exp)
-
- nbd_export_get(exp);
- QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
-- client_close(client);
-+ client_close(client, true);
- }
- nbd_export_set_name(exp, NULL);
- nbd_export_set_description(exp, NULL);
-@@ -1355,7 +1355,7 @@ done:
-
- out:
- nbd_request_put(req);
-- client_close(client);
-+ client_close(client, true);
- nbd_client_put(client);
- }
-
-@@ -1381,7 +1381,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
- qemu_co_mutex_init(&client->send_lock);
-
- if (nbd_negotiate(data)) {
-- client_close(client);
-+ client_close(client, false);
- goto out;
- }
-
-@@ -1391,11 +1391,17 @@ out:
- g_free(data);
- }
-
-+/*
-+ * Create a new client listener on the given export @exp, using the
-+ * given channel @sioc. Begin servicing it in a coroutine. When the
-+ * connection closes, call @close_fn with an indication of whether the
-+ * client completed negotiation.
-+ */
- void nbd_client_new(NBDExport *exp,
- QIOChannelSocket *sioc,
- QCryptoTLSCreds *tlscreds,
- const char *tlsaclname,
-- void (*close_fn)(NBDClient *))
-+ void (*close_fn)(NBDClient *, bool))
- {
- NBDClient *client;
- NBDClientNewData *data = g_new(NBDClientNewData, 1);
-@@ -1412,7 +1418,7 @@ void nbd_client_new(NBDExport *exp,
- object_ref(OBJECT(client->sioc));
- client->ioc = QIO_CHANNEL(sioc);
- object_ref(OBJECT(client->ioc));
-- client->close = close_fn;
-+ client->close_fn = close_fn;
-
- data->client = client;
- data->co = qemu_coroutine_create(nbd_co_client_start, data);
-diff --git a/qemu-nbd.c b/qemu-nbd.c
-index b44764eb87..483dd77a77 100644
---- a/qemu-nbd.c
-+++ b/qemu-nbd.c
-@@ -335,10 +335,10 @@ static void nbd_export_closed(NBDExport *exp)
-
- static void nbd_update_server_watch(void);
-
--static void nbd_client_closed(NBDClient *client)
-+static void nbd_client_closed(NBDClient *client, bool negotiated)
- {
- nb_fds--;
-- if (nb_fds == 0 && !persistent && state == RUNNING) {
-+ if (negotiated && nb_fds == 0 && !persistent && state == RUNNING) {
- state = TERMINATE;
- }
- nbd_update_server_watch();
---
-2.11.0
-
+++ /dev/null
-From 36d48727155c4a440ee23c703778533f87002964 Mon Sep 17 00:00:00 2001
-From: Max Reitz <mreitz@redhat.com>
-Date: Sun, 11 Jun 2017 14:37:14 +0200
-Subject: [PATCH 20/23] qemu-nbd: 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).
-
-Signed-off-by: Max Reitz <mreitz@redhat.com>
-Message-Id: <20170611123714.31292-1-mreitz@redhat.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- qemu-nbd.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/qemu-nbd.c b/qemu-nbd.c
-index 483dd77a77..5deb37e03e 100644
---- a/qemu-nbd.c
-+++ b/qemu-nbd.c
-@@ -581,6 +581,10 @@ int main(int argc, char **argv)
- sa_sigterm.sa_handler = termsig_handler;
- sigaction(SIGTERM, &sa_sigterm, NULL);
-
-+#ifdef CONFIG_POSIX
-+ signal(SIGPIPE, SIG_IGN);
-+#endif
-+
- module_call_init(MODULE_INIT_TRACE);
- qcrypto_init(&error_fatal);
-
---
-2.11.0
-
+++ /dev/null
-From ce2b5a53421794394fc81d155837b1c8ac79ea15 Mon Sep 17 00:00:00 2001
-From: Gerd Hoffmann <kraxel@redhat.com>
-Date: Tue, 9 May 2017 13:01:28 +0200
-Subject: [PATCH 21/23] usb-redir: fix stack overflow in usbredir_log_data
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-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(-)
-
-diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
-index 0efe62f725..eb70dc7218 100644
---- a/hw/usb/redirect.c
-+++ b/hw/usb/redirect.c
-@@ -229,21 +229,10 @@ static void usbredir_log(void *priv, int level, const char *msg)
- 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);
- }
-
- /*
---
-2.11.0
-
+++ /dev/null
-From d587bf95f1099fd253e6a7b768bf73d4e25de07c Mon Sep 17 00:00:00 2001
-From: Prasad J Pandit <pjp@fedoraproject.org>
-Date: Wed, 12 Jul 2017 18:08:40 +0530
-Subject: [PATCH 22/23] exec: use qemu_ram_ptr_length to access guest ram
-
-When accessing guest's ram block during DMA operation, use
-'qemu_ram_ptr_length' to get ram block pointer. It ensures
-that DMA operation of given length is possible; And avoids
-any OOB memory access situations.
-
-Reported-by: Alex <broscutamaker@gmail.com>
-Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
-Message-Id: <20170712123840.29328-1-ppandit@redhat.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- exec.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/exec.c b/exec.c
-index c97ef4a8da..72d636a4fb 100644
---- a/exec.c
-+++ b/exec.c
-@@ -2765,7 +2765,7 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
- }
- } else {
- /* RAM case */
-- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
- memcpy(ptr, buf, l);
- invalidate_and_set_dirty(mr, addr1, l);
- }
-@@ -2856,7 +2856,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
- }
- } else {
- /* RAM case */
-- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
-+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
- memcpy(buf, ptr, l);
- }
-
---
-2.11.0
-
+++ /dev/null
-From f3b5bdea7ea51404bbf88bea6fc8887586a423b2 Mon Sep 17 00:00:00 2001
-From: Prasad J Pandit <pjp@fedoraproject.org>
-Date: Mon, 17 Jul 2017 17:33:26 +0530
-Subject: [PATCH 23/23] 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>
----
- slirp/bootp.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/slirp/bootp.c b/slirp/bootp.c
-index 5a4646c182..5dd1a415b5 100644
---- a/slirp/bootp.c
-+++ b/slirp/bootp.c
-@@ -123,6 +123,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) {
---
-2.11.0
-
-From 926ac2ae6be8a7971e4c24d45345981e3a62d560 Mon Sep 17 00:00:00 2001
+From 5f03cca26a4ba9c08d6f6e19b97b6c6c1f0f236a Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:15:49 +0100
Subject: [PATCH 01/28] fr-ca keymap corrections
-From 65a038b874c5770f48077cf77742ac10bb083922 Mon Sep 17 00:00:00 2001
+From 499c1880a00cd772bf85167cb2bb3f5ff4eb4d33 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:16:49 +0100
Subject: [PATCH 02/28] Adjust network script path to /etc/kvm/
-From 034ee9d08002e8e57c4d09e9a9750aad547f65f1 Mon Sep 17 00:00:00 2001
+From 99ae84628c46f29cfce39c753801f91efe102a8c Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:18:46 +0100
Subject: [PATCH 03/28] qemu-img: return success on info without snapshots
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/qemu-img.c b/qemu-img.c
-index b220cf71d7..4f7f458dd2 100644
+index e4a2686f56..c7804d63ee 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2596,7 +2596,8 @@ static int img_info(int argc, char **argv)
-From 0203288ce982ea135ff82cf4ea6a7868ef053470 Mon Sep 17 00:00:00 2001
+From f1e0cc0d0f287a8072a0f69fe1a10a0cf1cd6b49 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:27:05 +0100
Subject: [PATCH 04/28] use kvm by default
-From d91355991605106e86f246e0e9091ffc1275b52f Mon Sep 17 00:00:00 2001
+From 6b88624be0e6018ad674abdb01d6cb04fabc703e Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:27:49 +0100
Subject: [PATCH 05/28] virtio-balloon: fix query
-From 99d1d87c126c630afed3885a26b5c4c6ca6e050b Mon Sep 17 00:00:00 2001
+From f321f239eb7d28861a16d6f941bd3b756621147c Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:30:21 +0100
Subject: [PATCH 06/28] set the CPU model to kvm64/32 instead of qemu64/32
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
-index d24388e05f..81e91a4897 100644
+index 610050eb4f..e96901435a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1151,9 +1151,9 @@ void pc_cpus_init(PCMachineState *pcms)
-From a761848c2ded6eb644c0e0e5d9184f54db59828a Mon Sep 17 00:00:00 2001
+From ba17137d9645c421717b20aef09fed3945dc6d14 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:31:18 +0100
Subject: [PATCH 07/28] qapi: modify query machines
##
diff --git a/vl.c b/vl.c
-index 0b4ed5241c..868c4893df 100644
+index b719cc432e..46de1b9087 100644
--- a/vl.c
+++ b/vl.c
@@ -1518,6 +1518,11 @@ MachineInfoList *qmp_query_machines(Error **errp)
-From 7215cf5a1ef31a3b0470c16d0b2a3585edf5dbc5 Mon Sep 17 00:00:00 2001
+From d31b55269adad7b160a0942e7c887d3ec754f7d3 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:32:11 +0100
Subject: [PATCH 08/28] qapi: modify spice query
-From 3ea2b6f80c46456be2ed339dc2338a61cc7b7bfe Mon Sep 17 00:00:00 2001
+From 6eb3751cbdb888cf3a0b8e481ef7faa3f58f67cb Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:33:34 +0100
Subject: [PATCH 09/28] ui/spice: default to pve certs unless otherwise
-From 1f5a5623052ba8d593e4356f9fda0281e607be76 Mon Sep 17 00:00:00 2001
+From 27d7cf1b94244a56cd0e8a408af3e40a84dace81 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 16:04:32 +0100
Subject: [PATCH 10/28] internal snapshot async
---
Makefile.objs | 1 +
- block.c | 2 +-
hmp-commands-info.hx | 13 ++
hmp-commands.hx | 32 +++
hmp.c | 57 ++++++
hmp.h | 5 +
- include/block/block.h | 1 +
include/sysemu/sysemu.h | 5 +-
migration/savevm.c | 12 +-
qapi-schema.json | 68 +++++++
qemu-options.hx | 13 ++
savevm-async.c | 523 ++++++++++++++++++++++++++++++++++++++++++++++++
vl.c | 8 +
- 13 files changed, 732 insertions(+), 8 deletions(-)
+ 11 files changed, 730 insertions(+), 7 deletions(-)
create mode 100644 savevm-async.c
diff --git a/Makefile.objs b/Makefile.objs
common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
-diff --git a/block.c b/block.c
-index 1fbbb8d606..6ea9ed1c62 100644
---- a/block.c
-+++ b/block.c
-@@ -3091,7 +3091,7 @@ out:
- bdrv_unref(bs_new);
- }
-
--static void bdrv_delete(BlockDriverState *bs)
-+void bdrv_delete(BlockDriverState *bs)
- {
- assert(!bs->job);
- assert(bdrv_op_blocker_is_empty(bs));
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index a53f105c52..5fc57a2210 100644
--- a/hmp-commands-info.hx
void hmp_sendkey(Monitor *mon, const QDict *qdict);
void hmp_screendump(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_start(Monitor *mon, const QDict *qdict);
-diff --git a/include/block/block.h b/include/block/block.h
-index 5ddc0cf21b..7eff87c7dd 100644
---- a/include/block/block.h
-+++ b/include/block/block.h
-@@ -295,6 +295,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
- int bdrv_get_backing_file_depth(BlockDriverState *bs);
- void bdrv_refresh_filename(BlockDriverState *bs);
- int bdrv_truncate(BdrvChild *child, int64_t offset);
-+void bdrv_delete(BlockDriverState *bs);
- int64_t bdrv_nb_sectors(BlockDriverState *bs);
- int64_t bdrv_getlength(BlockDriverState *bs);
- int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 576c7ce640..74623de16c 100644
--- a/include/sysemu/sysemu.h
#
# An enumeration of key name.
diff --git a/qemu-options.hx b/qemu-options.hx
-index 99af8edf5f..10f0e81f9b 100644
+index 48dfffd86a..cbcb27da9a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3396,6 +3396,19 @@ STEXI
"-daemonize daemonize QEMU after initializing\n", QEMU_ARCH_ALL)
diff --git a/savevm-async.c b/savevm-async.c
new file mode 100644
-index 0000000000..2f4766cf6c
+index 0000000000..5fcb56d373
--- /dev/null
+++ b/savevm-async.c
@@ -0,0 +1,523 @@
+ * note: bdrv_read() need whole blocks, so we round up
+ */
+ size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
-+ blk_truncate(snap_state.target, size);
++ blk_truncate(snap_state.target, size, NULL);
+ blk_op_unblock_all(snap_state.target, snap_state.blocker);
+ error_free(snap_state.blocker);
+ snap_state.blocker = NULL;
+ return ret;
+}
diff --git a/vl.c b/vl.c
-index 868c4893df..19afd47871 100644
+index 46de1b9087..2132a77129 100644
--- a/vl.c
+++ b/vl.c
@@ -2960,6 +2960,7 @@ int main(int argc, char **argv, char **envp)
MachineClass *machine_class;
const char *cpu_model;
const char *vga_model = NULL;
-@@ -3631,6 +3632,9 @@ int main(int argc, char **argv, char **envp)
+@@ -3635,6 +3636,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_loadvm:
loadvm = optarg;
break;
case QEMU_OPTION_full_screen:
full_screen = 1;
break;
-@@ -4689,6 +4693,10 @@ int main(int argc, char **argv, char **envp)
+@@ -4693,6 +4697,10 @@ int main(int argc, char **argv, char **envp)
if (load_vmstate(loadvm) < 0) {
autostart = 0;
}
-From 1a92a719b15ed17e57999e009bc0fb4cf94ef468 Mon Sep 17 00:00:00 2001
+From bed6817c14a520409f4ffee05e635c988c8b5994 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Tue, 8 Nov 2016 11:13:06 +0100
Subject: [PATCH 11/28] convert savevm-async to threads
1 file changed, 88 insertions(+), 56 deletions(-)
diff --git a/savevm-async.c b/savevm-async.c
-index 2f4766cf6c..624e3a34b4 100644
+index 5fcb56d373..97d51d3edd 100644
--- a/savevm-async.c
+++ b/savevm-async.c
@@ -48,6 +48,8 @@ static struct SnapshotState {
-From 6c70ffe629c678a110d311fab784d65836a7917e Mon Sep 17 00:00:00 2001
+From a43e451816ebd6d961412b0d88597c79eb6dd478 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 16:34:41 +0100
Subject: [PATCH 12/28] qmp: add get_link_status
-From 3afb3d14378cc401e37dafd8437cfc45cce2aaea Mon Sep 17 00:00:00 2001
+From 8d4dc658bad2438d6225d261aae8647088b853a1 Mon Sep 17 00:00:00 2001
From: Alexandre Derumier <aderumier@odiso.com>
Date: Tue, 29 Sep 2015 15:37:44 +0200
Subject: [PATCH 13/28] smm_available = false
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
-index 81e91a4897..4161a45dc0 100644
+index e96901435a..f049bbca9a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -2123,7 +2123,7 @@ bool pc_machine_is_smm_enabled(PCMachineState *pcms)
-From 8f6787a80cafc259d2247a294ea657aee0928488 Mon Sep 17 00:00:00 2001
+From 4c989793d0df71e8f90da8c8f883d42a8aa92191 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 16:50:05 +0100
Subject: [PATCH 14/28] use whitespace between VERSION and PKGVERSION
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/vl.c b/vl.c
-index 19afd47871..d0780a41b4 100644
+index 2132a77129..5d888cd179 100644
--- a/vl.c
+++ b/vl.c
@@ -1909,7 +1909,7 @@ static void main_loop(void)
-From 8c4c8041d0cb8523af453e1d1a8408215db6964f Mon Sep 17 00:00:00 2001
+From 9082b919824dbedc5c3aa04369abb2f433ef6ec1 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 14:17:38 +0100
Subject: [PATCH 15/28] vnc: altgr emulation
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/ui/vnc.c b/ui/vnc.c
-index 349cfc9d86..9c8ab42eea 100644
+index b0314441c4..f30687884b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1631,6 +1631,10 @@ static void kbd_leds(void *opaque, int ledstate)
-From e90d84abb42bc2befe9a48a9be2873d5dce68236 Mon Sep 17 00:00:00 2001
+From 78f096b96d63ed2e7eefd5826c5b8ef62f1244eb Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Tue, 12 Jan 2016 09:09:49 +0100
Subject: [PATCH 16/28] vnc: make x509 imply tls again
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/ui/vnc.c b/ui/vnc.c
-index 9c8ab42eea..eb9420e830 100644
+index f30687884b..a345bf0d78 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3881,9 +3881,8 @@ void vnc_display_open(const char *id, Error **errp)
-From e9712692a0a336bf56025e1bc8056636cbd3931e Mon Sep 17 00:00:00 2001
+From 981ee6783da6e4d5905fcc972950296187a55c0d Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Mon, 11 Jan 2016 10:40:31 +0100
Subject: [PATCH 17/28] vnc: PVE VNC authentication
void vnc_display_open(const char *id, Error **errp);
void vnc_display_add_client(const char *id, int csock, bool skipauth);
diff --git a/qemu-options.hx b/qemu-options.hx
-index 10f0e81f9b..fbd1a1cecf 100644
+index cbcb27da9a..0b1957c034 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -513,6 +513,9 @@ STEXI
vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
}
diff --git a/ui/vnc.c b/ui/vnc.c
-index eb9420e830..2710614a72 100644
+index a345bf0d78..42db7e386b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -56,6 +56,125 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
+
#endif /* QEMU_VNC_H */
diff --git a/vl.c b/vl.c
-index d0780a41b4..2496b066b7 100644
+index 5d888cd179..1000a4a259 100644
--- a/vl.c
+++ b/vl.c
@@ -2947,6 +2947,7 @@ static int qemu_read_default_config_file(void)
int snapshot, linux_boot;
const char *initrd_filename;
const char *kernel_filename, *kernel_cmdline;
-@@ -3774,6 +3775,14 @@ int main(int argc, char **argv, char **envp)
+@@ -3778,6 +3779,14 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
break;
-From 0b8732d8e19f69471e2f9b8c9a654de62482915a Mon Sep 17 00:00:00 2001
+From 9398ed96d5c02451ec85a3fcea2284b6efd4b7a8 Mon Sep 17 00:00:00 2001
From: Thomas Lamprecht <t.lamprecht@proxmox.com>
Date: Wed, 6 Apr 2016 16:45:15 +0200
Subject: [PATCH 18/28] migrate: fix possible unitialised return value
-From b0603dbd9bd127305472e8162e9b3289b866b824 Mon Sep 17 00:00:00 2001
+From 24fea0d7356b39d70dde9eb683183ed5c67a4ac9 Mon Sep 17 00:00:00 2001
From: Alexandre Derumier <aderumier@odiso.com>
Date: Tue, 26 Jul 2016 16:51:00 +0200
Subject: [PATCH 19/28] block: rbd: disable rbd_cache_writethrough_until_flush
1 file changed, 4 insertions(+)
diff --git a/block/rbd.c b/block/rbd.c
-index 1ceeeb5a60..30fe179585 100644
+index 2354ffcc64..b7700648ff 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -623,6 +623,10 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
-From 976296684d224ab866fc8b7ebe0d2de4b5b39170 Mon Sep 17 00:00:00 2001
+From dccd9887366b5df7eeb8394cc0476536ebc8dd45 Mon Sep 17 00:00:00 2001
From: Alexandre Derumier <aderumier@odiso.com>
Date: Tue, 13 Sep 2016 01:57:56 +0200
Subject: [PATCH 20/28] block: snapshot: qmp_snapshot_drive: add aiocontext
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/savevm-async.c b/savevm-async.c
-index 624e3a34b4..95995eab31 100644
+index 97d51d3edd..ece193a065 100644
--- a/savevm-async.c
+++ b/savevm-async.c
@@ -377,6 +377,7 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
-From 1540187ba7716d502908a1815298d7c3fc8db6a6 Mon Sep 17 00:00:00 2001
+From e46b7bfe99cf88021d65b7796318066b1326ad53 Mon Sep 17 00:00:00 2001
From: Alexandre Derumier <aderumier@odiso.com>
Date: Mon, 7 Nov 2016 11:47:50 +0100
Subject: [PATCH 21/28] block: snapshot: qmp_delete_drive_snapshot : add
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/savevm-async.c b/savevm-async.c
-index 95995eab31..9f839faab5 100644
+index ece193a065..716dd2d7a1 100644
--- a/savevm-async.c
+++ b/savevm-async.c
@@ -459,6 +459,7 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
-From 26129edb715505ae35207eff2477cffec50af13e Mon Sep 17 00:00:00 2001
+From a53fb2c9746d90e6020a0d7e5e8e2e346c81fb99 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Mon, 24 Oct 2016 09:32:36 +0200
Subject: [PATCH 22/28] glusterfs: no default logfile if daemonized
-From 113e86e08a88805de1fb3aa88327174c8fa1d437 Mon Sep 17 00:00:00 2001
+From b7b68751ac7a5779872611ee1084be52b7645988 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 30 Nov 2016 10:27:47 +0100
Subject: [PATCH 23/28] glusterfs: allow partial reads
-From f5ec823838e35470f0c9ff6bf7968ac02fa08b4d Mon Sep 17 00:00:00 2001
+From 728c38cd3035da76df02cf955c0452c3401eb3f3 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Thu, 17 Mar 2016 11:33:37 +0100
Subject: [PATCH 24/28] block: add the zeroinit block driver filter
block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
diff --git a/block/zeroinit.c b/block/zeroinit.c
new file mode 100644
-index 0000000000..a857ec3c62
+index 0000000000..305185512e
--- /dev/null
+++ b/block/zeroinit.c
@@ -0,0 +1,220 @@
+
+static int zeroinit_truncate(BlockDriverState *bs, int64_t offset)
+{
-+ return bdrv_truncate(bs->file, offset);
++ return bdrv_truncate(bs->file, offset, NULL);
+}
+
+static int zeroinit_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
-From 3bd6a30a92ecb420bac469ec977fbcc0ad918d1c Mon Sep 17 00:00:00 2001
+From e1031eef2db9f19cd09c21ba36f0d106528d8df0 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 23 Jun 2017 12:01:43 +0200
Subject: [PATCH 25/28] qemu-img dd: add osize and read from/to stdin/stdout
DEF("info", img_info,
diff --git a/qemu-img.c b/qemu-img.c
-index 4f7f458dd2..b9d1ef7bb8 100644
+index c7804d63ee..ee7816e727 100644
--- a/qemu-img.c
+++ b/qemu-img.c
-@@ -4035,10 +4035,12 @@ out:
+@@ -4026,10 +4026,12 @@ out:
#define C_IF 04
#define C_OF 010
#define C_SKIP 020
};
struct DdIo {
-@@ -4117,6 +4119,20 @@ static int img_dd_skip(const char *arg,
+@@ -4108,6 +4110,20 @@ static int img_dd_skip(const char *arg,
return 0;
}
static int img_dd(int argc, char **argv)
{
int ret = 0;
-@@ -4156,6 +4172,7 @@ static int img_dd(int argc, char **argv)
+@@ -4147,6 +4163,7 @@ static int img_dd(int argc, char **argv)
{ "if", img_dd_if, C_IF },
{ "of", img_dd_of, C_OF },
{ "skip", img_dd_skip, C_SKIP },
{ NULL, NULL, 0 }
};
const struct option long_options[] = {
-@@ -4223,84 +4240,106 @@ static int img_dd(int argc, char **argv)
+@@ -4214,84 +4231,106 @@ static int img_dd(int argc, char **argv)
arg = NULL;
}
}
if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
-@@ -4318,11 +4357,18 @@ static int img_dd(int argc, char **argv)
+@@ -4309,11 +4348,18 @@ static int img_dd(int argc, char **argv)
for (out_pos = 0; in_pos < size; block_count++) {
int in_ret, out_ret;
}
if (in_ret < 0) {
error_report("error while reading from input image file: %s",
-@@ -4332,9 +4378,13 @@ static int img_dd(int argc, char **argv)
+@@ -4323,9 +4369,13 @@ static int img_dd(int argc, char **argv)
}
in_pos += in_ret;
-From 020e2108f7571fac3853c47ba1ea8bafb5eef81e Mon Sep 17 00:00:00 2001
+From 6017af4918c9795a7f98a463426e1e21065b15d5 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 15:04:57 +0100
Subject: [PATCH 26/28] backup: modify job api
error_propagate(errp, local_err);
backup_job_cleanup(bs);
diff --git a/blockdev.c b/blockdev.c
-index 4927914ce3..ec5e931029 100644
+index e8a9a65167..9b6cfafd33 100644
--- a/blockdev.c
+++ b/blockdev.c
-@@ -3273,7 +3273,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
+@@ -3262,7 +3262,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
backup->sync, bmap, backup->compress,
backup->on_source_error, backup->on_target_error,
bdrv_unref(target_bs);
if (local_err != NULL) {
error_propagate(errp, local_err);
-@@ -3352,7 +3352,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
+@@ -3341,7 +3341,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
backup->sync, NULL, backup->compress,
backup->on_source_error, backup->on_target_error,
}
diff --git a/include/block/block_int.h b/include/block/block_int.h
-index 59400bd848..2b3ecd0575 100644
+index 89d7b458e7..19b84b027f 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
-@@ -878,6 +878,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
+@@ -879,6 +879,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
BlockdevOnError on_target_error,
int creation_flags,
BlockCompletionFunc *cb, void *opaque,
-From c904f41916fbfa522513267933da3f08ec74215f Mon Sep 17 00:00:00 2001
+From fb4bcaaced8119f2b99d1621fdfe5fce159311f4 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 2 Aug 2017 13:51:02 +0200
Subject: [PATCH 27/28] backup: introduce vma archive format
create mode 100644 block/vma.c
diff --git a/MAINTAINERS b/MAINTAINERS
-index c60235eaf6..d95f278eb4 100644
+index 430efb0ab7..6a7d338aad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -1810,6 +1810,12 @@ L: qemu-block@nongnu.org
+@@ -1811,6 +1811,12 @@ L: qemu-block@nongnu.org
S: Supported
F: block/vvfat.c
+
+block_init(bdrv_vma_init);
diff --git a/blockdev.c b/blockdev.c
-index ec5e931029..981276692a 100644
+index 9b6cfafd33..e23eb16fc8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -31,10 +31,12 @@
#include "block/throttle-groups.h"
#include "monitor/monitor.h"
#include "qemu/error-report.h"
-@@ -2956,6 +2958,503 @@ out:
+@@ -2932,6 +2934,503 @@ out:
aio_context_release(aio_context);
}
#
# Detailed migration status.
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 033457ce86..891afe5eaa 100644
+index 7ce90ec940..b0ffd3de4d 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -2116,7 +2116,7 @@
+@@ -2118,7 +2118,7 @@
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
##
# @BlockdevOptionsFile:
-@@ -2866,6 +2866,21 @@
+@@ -2895,6 +2895,21 @@
'data': { '*offset': 'int', '*size': 'int' } }
##
# @BlockdevOptions:
#
# Options for creating a block device. Many options are available for all
-@@ -2927,7 +2942,8 @@
+@@ -2956,7 +2971,8 @@
'vhdx': 'BlockdevOptionsGenericFormat',
'vmdk': 'BlockdevOptionsGenericCOWFormat',
'vpc': 'BlockdevOptionsGenericFormat',
-From 19761ee4aa12da9a3e4028cc611a18d972559de0 Mon Sep 17 00:00:00 2001
+From bda9612a0dc8b39b73c8e99a149f2aa967a056a3 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Mon, 7 Aug 2017 08:51:16 +0200
Subject: [PATCH 28/28] adding old vma files
if (local_err) {
error_propagate(errp, local_err);
diff --git a/blockdev.c b/blockdev.c
-index 981276692a..76a7103743 100644
+index e23eb16fc8..19a82e8774 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -31,7 +31,6 @@
static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
-@@ -2958,20 +2958,44 @@ out:
+@@ -2934,20 +2934,44 @@ out:
aio_context_release(aio_context);
}
size_t total;
size_t transferred;
size_t zero_bytes;
-@@ -2981,6 +3005,7 @@ typedef struct PVEBackupDevInfo {
+@@ -2957,6 +2981,7 @@ typedef struct PVEBackupDevInfo {
BlockDriverState *bs;
size_t size;
uint8_t dev_id;
bool completed;
char targetfile[PATH_MAX];
BlockDriverState *target;
-@@ -2988,13 +3013,79 @@ typedef struct PVEBackupDevInfo {
+@@ -2964,13 +2989,79 @@ typedef struct PVEBackupDevInfo {
static void pvebackup_run_next_job(void);
}
if (backup_state.di_list) {
-@@ -3009,6 +3100,13 @@ static void pvebackup_cleanup(void)
+@@ -2985,6 +3076,13 @@ static void pvebackup_cleanup(void)
}
}
static void pvebackup_complete_cb(void *opaque, int ret)
{
PVEBackupDevInfo *di = opaque;
-@@ -3020,14 +3118,18 @@ static void pvebackup_complete_cb(void *opaque, int ret)
+@@ -2996,14 +3094,18 @@ static void pvebackup_complete_cb(void *opaque, int ret)
ret, strerror(-ret));
}
if (!backup_state.cancel) {
pvebackup_run_next_job();
}
-@@ -3041,14 +3143,9 @@ static void pvebackup_cancel(void *opaque)
+@@ -3017,14 +3119,9 @@ static void pvebackup_cancel(void *opaque)
error_setg(&backup_state.error, "backup cancelled");
}
}
GList *l = backup_state.di_list;
-@@ -3073,19 +3170,15 @@ void qmp_backup_cancel(Error **errp)
+@@ -3049,19 +3146,15 @@ void qmp_backup_cancel(Error **errp)
Coroutine *co = qemu_coroutine_create(pvebackup_cancel, NULL);
qemu_coroutine_enter(co);
{
char *cdata = NULL;
gsize clen = 0;
-@@ -3098,12 +3191,17 @@ static int config_to_vma(const char *file, BackupFormat format,
+@@ -3074,12 +3167,17 @@ static int config_to_vma(const char *file, BackupFormat format,
char *basename = g_path_get_basename(file);
if (format == BACKUP_FORMAT_VMA) {
g_free(cdata);
g_free(basename);
return 1;
-@@ -3113,35 +3211,37 @@ static int config_to_vma(const char *file, BackupFormat format,
+@@ -3089,35 +3187,37 @@ static int config_to_vma(const char *file, BackupFormat format,
g_free(basename);
g_free(cdata);
bool has_devlist, const char *devlist,
bool has_speed, int64_t speed, Error **errp)
{
-@@ -3149,14 +3249,15 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
+@@ -3125,14 +3225,15 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
BlockDriverState *bs = NULL;
const char *backup_dir = NULL;
Error *local_err = NULL;
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
"previous backup not finished");
return NULL;
-@@ -3231,40 +3332,28 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
+@@ -3207,40 +3308,28 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
total += size;
}
goto err;
}
}
-@@ -3305,15 +3394,15 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
+@@ -3281,15 +3370,15 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
/* add configuration file to archive */
if (has_config_file) {
}
}
/* initialize global backup_state now */
-@@ -3335,11 +3424,12 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
+@@ -3311,11 +3400,12 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
}
backup_state.backup_file = g_strdup(backup_file);
backup_state.total = total;
backup_state.transferred = 0;
-@@ -3350,21 +3440,16 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
+@@ -3326,21 +3416,16 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
while (l) {
PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
l = g_list_next(l);
}
if (!backup_state.error) {
-@@ -3398,9 +3483,10 @@ err:
+@@ -3374,9 +3459,10 @@ err:
g_strfreev(devs);
}
}
if (backup_dir) {
-@@ -3772,7 +3858,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
+@@ -3761,7 +3847,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
backup->sync, bmap, backup->compress,
backup->on_source_error, backup->on_target_error,
bdrv_unref(target_bs);
if (local_err != NULL) {
error_propagate(errp, local_err);
-@@ -3851,7 +3937,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
+@@ -3840,7 +3926,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
backup->sync, NULL, backup->compress,
backup->on_source_error, backup->on_target_error,
if (block_job_is_internal(job)) {
return;
diff --git a/include/block/block_int.h b/include/block/block_int.h
-index 2b3ecd0575..278da161fb 100644
+index 19b84b027f..fc1c53a059 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -59,6 +59,9 @@
enum BdrvTrackedRequestType {
BDRV_TRACKED_READ,
BDRV_TRACKED_WRITE,
-@@ -877,6 +880,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
+@@ -878,6 +881,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
int creation_flags,
pve/0027-backup-introduce-vma-archive-format.patch
pve/0028-adding-old-vma-files.patch
extra/0001-Revert-target-i386-disable-LINT0-after-reset.patch
-extra/0002-qemu-img-wait-for-convert-coroutines-to-complete.patch
-extra/0003-block-Do-not-unref-bs-file-on-error-in-BD-s-open.patch
-extra/0004-9pfs-local-fix-unlink-of-alien-files-in-mapped-file-.patch
-extra/0005-blockdev-use-drained_begin-end-for-qmp_block_resize.patch
-extra/0006-aio-add-missing-aio_notify-to-aio_enable_external.patch
-extra/0007-virtio-serial-bus-Unset-hotplug-handler-when-unreali.patch
-extra/0008-virtio-serial-fix-segfault-on-disconnect.patch
-extra/0009-e1000e-Fix-ICR-Other-causes-clear-logic.patch
-extra/0010-mirror-Drop-permissions-on-s-target-on-completion.patch
-extra/0011-vmw_pvscsi-check-message-ring-page-count-at-initiali.patch
-extra/0012-audio-release-capture-buffers.patch
-extra/0013-input-limit-kbd-queue-depth.patch
-extra/0014-scsi-avoid-an-off-by-one-error-in-megasas_mmio_write.patch
-extra/0015-9pfs-local-forbid-client-access-to-metadata-CVE-2017.patch
-extra/0016-megasas-do-not-read-DCMD-opcode-more-than-once-from-.patch
-extra/0017-megasas-always-store-SCSIRequest-into-MegasasCmd.patch
-extra/0018-nbd-Fully-initialize-client-in-case-of-failed-negoti.patch
-extra/0019-nbd-Fix-regression-on-resiliency-to-port-scan.patch
-extra/0020-qemu-nbd-Ignore-SIGPIPE.patch
-extra/0021-usb-redir-fix-stack-overflow-in-usbredir_log_data.patch
-extra/0022-exec-use-qemu_ram_ptr_length-to-access-guest-ram.patch
-extra/0023-slirp-check-len-against-dhcp-options-array-end.patch
+extra/0002-virtio-serial-fix-segfault-on-disconnect.patch
+extra/0003-megasas-always-store-SCSIRequest-into-MegasasCmd.patch
+extra/0004-slirp-check-len-against-dhcp-options-array-end.patch
+extra/0005-IDE-Do-not-flush-empty-CDROM-drives.patch
+extra/0006-bitmap-add-bitmap_copy_and_clear_atomic.patch
+extra/0007-memory-add-support-getting-and-using-a-dirty-bitmap-.patch
+extra/0008-vga-add-vga_scanline_invalidated-helper.patch
+extra/0009-vga-make-display-updates-thread-safe.patch
+extra/0010-vga-fix-display-update-region-calculation.patch
+extra/0011-vga-fix-display-update-region-calculation-split-scre.patch
+extra/0012-vga-stop-passing-pointers-to-vga_draw_line-functions.patch
+extra/0013-multiboot-validate-multiboot-header-address-values.patch
-Subproject commit 359c41abe32638adad503e386969fa428cecff52
+Subproject commit 4cd42653f5c1df326a2678a84f24a78fb9601277