diff --git a/block-create-Do-not-abort-if-a-block-driver-is-not-available.patch b/block-create-Do-not-abort-if-a-block-driver-is-not-available.patch new file mode 100644 index 0000000..ef0a880 --- /dev/null +++ b/block-create-Do-not-abort-if-a-block-driver-is-not-available.patch @@ -0,0 +1,96 @@ +From c24d971c130d889d4d001d2ae2cb02b9a34d51b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 12 Sep 2019 00:08:49 +0200 +Subject: [PATCH] block/create: Do not abort if a block driver is not available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The 'blockdev-create' QMP command was introduced as experimental +feature in commit b0292b851b8, using the assert() debug call. +It got promoted to 'stable' command in 3fb588a0f2c, but the +assert call was not removed. + +Some block drivers are optional, and bdrv_find_format() might +return a NULL value, triggering the assertion. + +Stable code is not expected to abort, so return an error instead. + +This is easily reproducible when libnfs is not installed: + + ./configure + [...] + module support no + Block whitelist (rw) + Block whitelist (ro) + libiscsi support yes + libnfs support no + [...] + +Start QEMU: + + $ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait + +Send the 'blockdev-create' with the 'nfs' driver: + + $ ( cat << 'EOF' + {'execute': 'qmp_capabilities'} + {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} + EOF + ) | socat STDIO UNIX:/tmp/qemu.qmp + {"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}} + {"return": {}} + +QEMU crashes: + + $ gdb qemu-system-x86_64 core + Program received signal SIGSEGV, Segmentation fault. + (gdb) bt + #0 0x00007ffff510957f in raise () at /lib64/libc.so.6 + #1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6 + #2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6 + #3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6 + #4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69 + #5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314 + #6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131 + #7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174 + +With this patch applied, QEMU returns a QMP error: + + {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} + {"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}} + +Cc: qemu-stable@nongnu.org +Reported-by: Xu Tian +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Eric Blake +Reviewed-by: John Snow +Signed-off-by: Kevin Wolf +(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba) +Signed-off-by: Michael Roth +--- + block/create.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/create.c b/block/create.c +index 95341219ef..de5e97bb18 100644 +--- a/block/create.c ++++ b/block/create.c +@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, + const char *fmt = BlockdevDriver_str(options->driver); + BlockDriver *drv = bdrv_find_format(fmt); + ++ if (!drv) { ++ error_setg(errp, "Block driver '%s' not found or not supported", fmt); ++ return; ++ } ++ + /* If the driver is in the schema, we know that it exists. But it may not + * be whitelisted. */ +- assert(drv); + if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) { + error_setg(errp, "Driver is not whitelisted"); + return; +-- +2.19.1 + diff --git a/block-nfs-tear-down-aio-before-nfs_close.patch b/block-nfs-tear-down-aio-before-nfs_close.patch new file mode 100644 index 0000000..a22a7ee --- /dev/null +++ b/block-nfs-tear-down-aio-before-nfs_close.patch @@ -0,0 +1,42 @@ +From 6cb3e9e4f17c182c43ded773a04b1072c881aa78 Mon Sep 17 00:00:00 2001 +From: Peter Lieven +Date: Tue, 10 Sep 2019 17:41:09 +0200 +Subject: [PATCH] block/nfs: tear down aio before nfs_close + +nfs_close is a sync call from libnfs and has its own event +handler polling on the nfs FD. Avoid that both QEMU and libnfs +are intefering here. + +CC: qemu-stable@nongnu.org +Signed-off-by: Peter Lieven +Signed-off-by: Kevin Wolf +(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914) +Signed-off-by: Michael Roth +--- + block/nfs.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/block/nfs.c b/block/nfs.c +index 531903610b..f04f675c63 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -389,12 +389,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs, + static void nfs_client_close(NFSClient *client) + { + if (client->context) { ++ qemu_mutex_lock(&client->mutex); ++ aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), ++ false, NULL, NULL, NULL, NULL); ++ qemu_mutex_unlock(&client->mutex); + if (client->fh) { + nfs_close(client->context, client->fh); + client->fh = NULL; + } +- aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), +- false, NULL, NULL, NULL, NULL); + nfs_destroy_context(client->context); + client->context = NULL; + } +-- +2.19.1 + diff --git a/blockdev-backup-don-t-check-aio_context-too-early.patch b/blockdev-backup-don-t-check-aio_context-too-early.patch new file mode 100644 index 0000000..aa793d5 --- /dev/null +++ b/blockdev-backup-don-t-check-aio_context-too-early.patch @@ -0,0 +1,53 @@ +From 2429dc4eea91b381ff67a4d25ea9f6bbfe87c784 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Thu, 23 May 2019 13:06:39 -0400 +Subject: [PATCH] blockdev-backup: don't check aio_context too early + +in blockdev_backup_prepare, we check to make sure that the target is +associated with a compatible aio context. However, do_blockdev_backup is +called later and has some logic to move the target to a compatible +aio_context. The transaction version will fail certain commands +needlessly early as a result. + +Allow blockdev_backup_prepare to simply call do_blockdev_backup, which +will ultimately decide if the contexts are compatible or not. + +Note: the transaction version has always disallowed this operation since +its initial commit bd8baecd (2014), whereas the version of +qmp_blockdev_backup at the time, from commit c29c1dd312f, tried to +enforce the aio_context switch instead. It's not clear, and I can't see +from the mailing list archives at the time, why the two functions take a +different approach. It wasn't until later in efd7556708b (2016) that the +standalone version tried to determine if it could set the context or +not. + +Reported-by: aihua liang +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1683498 +Signed-off-by: John Snow +Message-id: 20190523170643.20794-2-jsnow@redhat.com +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz +(cherry picked from commit d81e1efbea7d19c2f142d300df56538c73800590) +Signed-off-by: Michael Roth +--- + blockdev.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 4775a07d93..d358169995 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1871,10 +1871,6 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) + } + + aio_context = bdrv_get_aio_context(bs); +- if (aio_context != bdrv_get_aio_context(target)) { +- error_setg(errp, "Backup between two IO threads is not implemented"); +- return; +- } + aio_context_acquire(aio_context); + state->bs = bs; + +-- +2.19.1 + diff --git a/blockjob-update-nodes-head-while-removing-all-bdrv.patch b/blockjob-update-nodes-head-while-removing-all-bdrv.patch new file mode 100644 index 0000000..4ad76d4 --- /dev/null +++ b/blockjob-update-nodes-head-while-removing-all-bdrv.patch @@ -0,0 +1,62 @@ +From b9405afb0956fe2c293a94bdc4440579e5c0efee Mon Sep 17 00:00:00 2001 +From: Sergio Lopez +Date: Wed, 11 Sep 2019 12:03:16 +0200 +Subject: [PATCH] blockjob: update nodes head while removing all bdrv + +block_job_remove_all_bdrv() iterates through job->nodes, calling +bdrv_root_unref_child() for each entry. The call to the latter may +reach child_job_[can_]set_aio_ctx(), which will also attempt to +traverse job->nodes, potentially finding entries that where freed +on previous iterations. + +To avoid this situation, update job->nodes head on each iteration to +ensure that already freed entries are no longer linked to the list. + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631 +Signed-off-by: Sergio Lopez +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190911100316.32282-1-mreitz@redhat.com +Reviewed-by: Sergio Lopez +Signed-off-by: Max Reitz +(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f) +Signed-off-by: Michael Roth +--- + blockjob.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/blockjob.c b/blockjob.c +index 730101d282..d770144fd6 100644 +--- a/blockjob.c ++++ b/blockjob.c +@@ -193,14 +193,23 @@ static const BdrvChildRole child_job = { + + void block_job_remove_all_bdrv(BlockJob *job) + { +- GSList *l; +- for (l = job->nodes; l; l = l->next) { ++ /* ++ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(), ++ * which will also traverse job->nodes, so consume the list one by ++ * one to make sure that such a concurrent access does not attempt ++ * to process an already freed BdrvChild. ++ */ ++ while (job->nodes) { ++ GSList *l = job->nodes; + BdrvChild *c = l->data; ++ ++ job->nodes = l->next; ++ + bdrv_op_unblock_all(c->bs, job->blocker); + bdrv_root_unref_child(c); ++ ++ g_slist_free_1(l); + } +- g_slist_free(job->nodes); +- job->nodes = NULL; + } + + int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, +-- +2.19.1 + diff --git a/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch b/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch new file mode 100644 index 0000000..db01a65 --- /dev/null +++ b/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch @@ -0,0 +1,80 @@ +From 53c641048e0a8da1d2bed76cbd17f259a35e39a0 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 29 Jul 2019 23:34:16 +0200 +Subject: [PATCH] dma-helpers: ensure AIO callback is invoked after + cancellation + +dma_aio_cancel unschedules the BH if there is one, which corresponds +to the reschedule_dma case of dma_blk_cb. This can stall the DMA +permanently, because dma_complete will never get invoked and therefore +nobody will ever invoke the original AIO callback in dbs->common.cb. + +Fix this by invoking the callback (which is ensured to happen after +a bdrv_aio_cancel_async, or done manually in the dbs->bh case), and +add assertions to check that the DMA state machine is indeed waiting +for dma_complete or reschedule_dma, but never both. + +Reported-by: John Snow +Signed-off-by: Paolo Bonzini +Message-id: 20190729213416.1972-1-pbonzini@redhat.com +Signed-off-by: John Snow +(cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f) +Signed-off-by: Michael Roth +--- + dma-helpers.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/dma-helpers.c b/dma-helpers.c +index 2d7e02d35e..d3871dc61e 100644 +--- a/dma-helpers.c ++++ b/dma-helpers.c +@@ -90,6 +90,7 @@ static void reschedule_dma(void *opaque) + { + DMAAIOCB *dbs = (DMAAIOCB *)opaque; + ++ assert(!dbs->acb && dbs->bh); + qemu_bh_delete(dbs->bh); + dbs->bh = NULL; + dma_blk_cb(dbs, 0); +@@ -111,15 +112,12 @@ static void dma_complete(DMAAIOCB *dbs, int ret) + { + trace_dma_complete(dbs, ret, dbs->common.cb); + ++ assert(!dbs->acb && !dbs->bh); + dma_blk_unmap(dbs); + if (dbs->common.cb) { + dbs->common.cb(dbs->common.opaque, ret); + } + qemu_iovec_destroy(&dbs->iov); +- if (dbs->bh) { +- qemu_bh_delete(dbs->bh); +- dbs->bh = NULL; +- } + qemu_aio_unref(dbs); + } + +@@ -179,14 +177,21 @@ static void dma_aio_cancel(BlockAIOCB *acb) + + trace_dma_aio_cancel(dbs); + ++ assert(!(dbs->acb && dbs->bh)); + if (dbs->acb) { ++ /* This will invoke dma_blk_cb. */ + blk_aio_cancel_async(dbs->acb); ++ return; + } ++ + if (dbs->bh) { + cpu_unregister_map_client(dbs->bh); + qemu_bh_delete(dbs->bh); + dbs->bh = NULL; + } ++ if (dbs->common.cb) { ++ dbs->common.cb(dbs->common.opaque, -ECANCELED); ++ } + } + + static AioContext *dma_get_aio_context(BlockAIOCB *acb) +-- +2.19.1 + diff --git a/hw-core-loader-Fix-possible-crash-in-rom_copy.patch b/hw-core-loader-Fix-possible-crash-in-rom_copy.patch new file mode 100644 index 0000000..d4301f7 --- /dev/null +++ b/hw-core-loader-Fix-possible-crash-in-rom_copy.patch @@ -0,0 +1,46 @@ +From 4f1c6cb2f9afafda05eab150fd2bd284edce6676 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 25 Sep 2019 14:16:43 +0200 +Subject: [PATCH] hw/core/loader: Fix possible crash in rom_copy() + +Both, "rom->addr" and "addr" are derived from the binary image +that can be loaded with the "-kernel" paramer. The code in +rom_copy() then calculates: + + d = dest + (rom->addr - addr); + +and uses "d" as destination in a memcpy() some lines later. Now with +bad kernel images, it is possible that rom->addr is smaller than addr, +thus "rom->addr - addr" gets negative and the memcpy() then tries to +copy contents from the image to a bad memory location. This could +maybe be used to inject code from a kernel image into the QEMU binary, +so we better fix it with an additional sanity check here. + +Cc: qemu-stable@nongnu.org +Reported-by: Guangming Liu +Buglink: https://bugs.launchpad.net/qemu/+bug/1844635 +Message-Id: <20190925130331.27825-1-thuth@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Thomas Huth +(cherry picked from commit e423455c4f23a1a828901c78fe6d03b7dde79319) +Signed-off-by: Michael Roth +--- + hw/core/loader.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/core/loader.c b/hw/core/loader.c +index fe5cb24122..4ef2095247 100644 +--- a/hw/core/loader.c ++++ b/hw/core/loader.c +@@ -1240,7 +1240,7 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size) + if (rom->addr + rom->romsize < addr) { + continue; + } +- if (rom->addr > end) { ++ if (rom->addr > end || rom->addr < addr) { + break; + } + +-- +2.19.1 + diff --git a/migration-Fix-use-after-free-during-process-exit.patch b/migration-Fix-use-after-free-during-process-exit.patch new file mode 100644 index 0000000..e640342 --- /dev/null +++ b/migration-Fix-use-after-free-during-process-exit.patch @@ -0,0 +1,205 @@ +From 35d6458d6a100b2f15a7e079558a4570742c6e5a Mon Sep 17 00:00:00 2001 +From: Yury Kotov +Date: Mon, 8 Apr 2019 14:33:43 +0300 +Subject: [PATCH] migration: Fix use-after-free during process exit + +It fixes heap-use-after-free which was found by clang's ASAN. + +Control flow of this use-after-free: +main_thread: + * Got SIGTERM and completes main loop + * Calls migration_shutdown + - migrate_fd_cancel (so, migration_thread begins to complete) + - object_unref(OBJECT(current_migration)); + +migration_thread: + * migration_iteration_finish -> schedule cleanup bh + * object_unref(OBJECT(s)); (Now, current_migration is freed) + * exits + +main_thread: + * Calls vm_shutdown -> drain bdrvs -> main loop + -> cleanup_bh -> use after free + +If you want to reproduce, these couple of sleeps will help: +vl.c:4613: + migration_shutdown(); ++ sleep(2); +migration.c:3269: ++ sleep(1); + trace_migration_thread_after_loop(); + migration_iteration_finish(s); + +Original output: +qemu-system-x86_64: terminating on signal 15 from pid 31980 () +================================================================= +==31958==ERROR: AddressSanitizer: heap-use-after-free on address 0x61900001d210 + at pc 0x555558a535ca bp 0x7fffffffb190 sp 0x7fffffffb188 +READ of size 8 at 0x61900001d210 thread T0 (qemu-vm-0) + #0 0x555558a535c9 in migrate_fd_cleanup migration/migration.c:1502:23 + #1 0x5555594fde0a in aio_bh_call util/async.c:90:5 + #2 0x5555594fe522 in aio_bh_poll util/async.c:118:13 + #3 0x555559524783 in aio_poll util/aio-posix.c:725:17 + #4 0x555559504fb3 in aio_wait_bh_oneshot util/aio-wait.c:71:5 + #5 0x5555573bddf6 in virtio_blk_data_plane_stop + hw/block/dataplane/virtio-blk.c:282:5 + #6 0x5555589d5c09 in virtio_bus_stop_ioeventfd hw/virtio/virtio-bus.c:246:9 + #7 0x5555589e9917 in virtio_pci_stop_ioeventfd hw/virtio/virtio-pci.c:287:5 + #8 0x5555589e22bf in virtio_pci_vmstate_change hw/virtio/virtio-pci.c:1072:9 + #9 0x555557628931 in virtio_vmstate_change hw/virtio/virtio.c:2257:9 + #10 0x555557c36713 in vm_state_notify vl.c:1605:9 + #11 0x55555716ef53 in do_vm_stop cpus.c:1074:9 + #12 0x55555716eeff in vm_shutdown cpus.c:1092:12 + #13 0x555557c4283e in main vl.c:4617:5 + #14 0x7fffdfdb482f in __libc_start_main + (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) + #15 0x555556ecb118 in _start (x86_64-softmmu/qemu-system-x86_64+0x1977118) + +0x61900001d210 is located 144 bytes inside of 952-byte region + [0x61900001d180,0x61900001d538) +freed by thread T6 (live_migration) here: + #0 0x555556f76782 in __interceptor_free + /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:124:3 + #1 0x555558d5fa94 in object_finalize qom/object.c:618:9 + #2 0x555558d57651 in object_unref qom/object.c:1068:9 + #3 0x555558a55588 in migration_thread migration/migration.c:3272:5 + #4 0x5555595393f2 in qemu_thread_start util/qemu-thread-posix.c:502:9 + #5 0x7fffe057f6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9) + +previously allocated by thread T0 (qemu-vm-0) here: + #0 0x555556f76b03 in __interceptor_malloc + /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:146:3 + #1 0x7ffff6ee37b8 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x4f7b8) + #2 0x555558d58031 in object_new qom/object.c:640:12 + #3 0x555558a31f21 in migration_object_init migration/migration.c:139:25 + #4 0x555557c41398 in main vl.c:4320:5 + #5 0x7fffdfdb482f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) + +Thread T6 (live_migration) created by T0 (qemu-vm-0) here: + #0 0x555556f5f0dd in pthread_create + /tmp/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:210:3 + #1 0x555559538cf9 in qemu_thread_create util/qemu-thread-posix.c:539:11 + #2 0x555558a53304 in migrate_fd_connect migration/migration.c:3332:5 + #3 0x555558a72bd8 in migration_channel_connect migration/channel.c:92:5 + #4 0x555558a6ef87 in exec_start_outgoing_migration migration/exec.c:42:5 + #5 0x555558a4f3c2 in qmp_migrate migration/migration.c:1922:9 + #6 0x555558bb4f6a in qmp_marshal_migrate qapi/qapi-commands-migration.c:607:5 + #7 0x555559363738 in do_qmp_dispatch qapi/qmp-dispatch.c:131:5 + #8 0x555559362a15 in qmp_dispatch qapi/qmp-dispatch.c:174:11 + #9 0x5555571bac15 in monitor_qmp_dispatch monitor.c:4124:11 + #10 0x55555719a22d in monitor_qmp_bh_dispatcher monitor.c:4207:9 + #11 0x5555594fde0a in aio_bh_call util/async.c:90:5 + #12 0x5555594fe522 in aio_bh_poll util/async.c:118:13 + #13 0x5555595201e0 in aio_dispatch util/aio-posix.c:460:5 + #14 0x555559503553 in aio_ctx_dispatch util/async.c:261:5 + #15 0x7ffff6ede196 in g_main_context_dispatch + (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x4a196) + +SUMMARY: AddressSanitizer: heap-use-after-free migration/migration.c:1502:23 + in migrate_fd_cleanup +Shadow bytes around the buggy address: + 0x0c327fffb9f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c327fffba00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c327fffba10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c327fffba20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c327fffba30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd +=>0x0c327fffba40: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd + 0x0c327fffba50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd + 0x0c327fffba60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd + 0x0c327fffba70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd + 0x0c327fffba80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd + 0x0c327fffba90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb + Shadow gap: cc +==31958==ABORTING + +Signed-off-by: Yury Kotov +Message-Id: <20190408113343.2370-1-yury-kotov@yandex-team.ru> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert + Fixed up comment formatting +(cherry picked from commit fd392cfa8e6fb0dc34bd0327fc356dfbf6edf1fd) +Signed-off-by: Michael Roth +--- + migration/migration.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/migration/migration.c b/migration/migration.c +index 609e0df5d0..2f617b9dba 100644 +--- a/migration/migration.c ++++ b/migration/migration.c +@@ -1495,10 +1495,8 @@ static void block_cleanup_parameters(MigrationState *s) + } + } + +-static void migrate_fd_cleanup(void *opaque) ++static void migrate_fd_cleanup(MigrationState *s) + { +- MigrationState *s = opaque; +- + qemu_bh_delete(s->cleanup_bh); + s->cleanup_bh = NULL; + +@@ -1543,6 +1541,23 @@ static void migrate_fd_cleanup(void *opaque) + block_cleanup_parameters(s); + } + ++static void migrate_fd_cleanup_schedule(MigrationState *s) ++{ ++ /* ++ * Ref the state for bh, because it may be called when ++ * there're already no other refs ++ */ ++ object_ref(OBJECT(s)); ++ qemu_bh_schedule(s->cleanup_bh); ++} ++ ++static void migrate_fd_cleanup_bh(void *opaque) ++{ ++ MigrationState *s = opaque; ++ migrate_fd_cleanup(s); ++ object_unref(OBJECT(s)); ++} ++ + void migrate_set_error(MigrationState *s, const Error *error) + { + qemu_mutex_lock(&s->error_mutex); +@@ -3144,7 +3159,7 @@ static void migration_iteration_finish(MigrationState *s) + error_report("%s: Unknown ending state %d", __func__, s->state); + break; + } +- qemu_bh_schedule(s->cleanup_bh); ++ migrate_fd_cleanup_schedule(s); + qemu_mutex_unlock_iothread(); + } + +@@ -3279,7 +3294,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in) + bool resume = s->state == MIGRATION_STATUS_POSTCOPY_PAUSED; + + s->expected_downtime = s->parameters.downtime_limit; +- s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s); ++ s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup_bh, s); + if (error_in) { + migrate_fd_error(s, error_in); + migrate_fd_cleanup(s); +-- +2.19.1 + diff --git a/migration-dirty-bitmaps-change-bitmap-enumeration-method.patch b/migration-dirty-bitmaps-change-bitmap-enumeration-method.patch new file mode 100644 index 0000000..c720cc1 --- /dev/null +++ b/migration-dirty-bitmaps-change-bitmap-enumeration-method.patch @@ -0,0 +1,83 @@ +From 3a87d07722d4be717a97b59cfbc7b2ba27ca30b0 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Tue, 28 May 2019 19:33:31 -0400 +Subject: [PATCH] migration/dirty-bitmaps: change bitmap enumeration method +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Shift from looking at every root BDS to *every* BDS. This will migrate +bitmaps that are attached to blockdev created nodes instead of just ones +attached to emulated storage devices. + +Note that this will not migrate anonymous or internal-use bitmaps, as +those are defined as having no name. + +This will also fix the Coverity issues Peter Maydell has been asking +about for the past several releases, as well as fixing a real bug. + +Reported-by: Peter Maydell +Reported-by: Coverity 😅 +Reported-by: aihua liang +Reviewed-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: John Snow +Message-id: 20190514201926.10407-1-jsnow@redhat.com +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1652490 +Fixes: Coverity CID 1390625 +CC: Stefan Hajnoczi +Signed-off-by: John Snow +(cherry picked from commit 592203e7cfbd1ad261178431fcf390adfe8b16df) +Signed-off-by: Michael Roth +--- + migration/block-dirty-bitmap.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c +index d1bb863cb6..4a896a09eb 100644 +--- a/migration/block-dirty-bitmap.c ++++ b/migration/block-dirty-bitmap.c +@@ -273,7 +273,6 @@ static int init_dirty_bitmap_migration(void) + BlockDriverState *bs; + BdrvDirtyBitmap *bitmap; + DirtyBitmapMigBitmapState *dbms; +- BdrvNextIterator it; + Error *local_err = NULL; + + dirty_bitmap_mig_state.bulk_completed = false; +@@ -281,13 +280,8 @@ static int init_dirty_bitmap_migration(void) + dirty_bitmap_mig_state.prev_bitmap = NULL; + dirty_bitmap_mig_state.no_bitmaps = false; + +- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { +- const char *drive_name = bdrv_get_device_or_node_name(bs); +- +- /* skip automatically inserted nodes */ +- while (bs && bs->drv && bs->implicit) { +- bs = backing_bs(bs); +- } ++ for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) { ++ const char *name = bdrv_get_device_or_node_name(bs); + + for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap; + bitmap = bdrv_dirty_bitmap_next(bs, bitmap)) +@@ -296,7 +290,7 @@ static int init_dirty_bitmap_migration(void) + continue; + } + +- if (drive_name == NULL) { ++ if (!name || strcmp(name, "") == 0) { + error_report("Found bitmap '%s' in unnamed node %p. It can't " + "be migrated", bdrv_dirty_bitmap_name(bitmap), bs); + goto fail; +@@ -313,7 +307,7 @@ static int init_dirty_bitmap_migration(void) + + dbms = g_new0(DirtyBitmapMigBitmapState, 1); + dbms->bs = bs; +- dbms->node_name = drive_name; ++ dbms->node_name = name; + dbms->bitmap = bitmap; + dbms->total_sectors = bdrv_nb_sectors(bs); + dbms->sectors_per_chunk = CHUNK_SIZE * 8 * +-- +2.19.1 + diff --git a/mirror-Only-mirror-granularity-aligned-chunks.patch b/mirror-Only-mirror-granularity-aligned-chunks.patch new file mode 100644 index 0000000..17a87ee --- /dev/null +++ b/mirror-Only-mirror-granularity-aligned-chunks.patch @@ -0,0 +1,84 @@ +From d65d02614b6b0f6bcc64cd2a737b5204c0fc5304 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 5 Aug 2019 17:33:08 +0200 +Subject: [PATCH] mirror: Only mirror granularity-aligned chunks + +In write-blocking mode, all writes to the top node directly go to the +target. We must only mirror chunks of data that are aligned to the +job's granularity, because that is how the dirty bitmap works. +Therefore, the request alignment for writes must be the job's +granularity (in write-blocking mode). + +Unfortunately, this forces all reads and writes to have the same +granularity (we only need this alignment for writes to the target, not +the source), but that is something to be fixed another time. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190805153308.2657-1-mreitz@redhat.com +Reviewed-by: Vladimir Sementsov-Ogievskiy +Fixes: d06107ade0ce74dc39739bac80de84b51ec18546 +Signed-off-by: Max Reitz +(cherry picked from commit 9adc1cb49af8d4e54f57980b1eed5c0a4b2dafa6) +Signed-off-by: Michael Roth +--- + block/mirror.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/block/mirror.c b/block/mirror.c +index ff15cfb197..062dc42867 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1477,6 +1477,15 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c, + *nshared = BLK_PERM_ALL; + } + ++static void bdrv_mirror_top_refresh_limits(BlockDriverState *bs, Error **errp) ++{ ++ MirrorBDSOpaque *s = bs->opaque; ++ ++ if (s && s->job && s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING) { ++ bs->bl.request_alignment = s->job->granularity; ++ } ++} ++ + /* Dummy node that provides consistent read to its users without requiring it + * from its backing file and that allows writes on the backing file chain. */ + static BlockDriver bdrv_mirror_top = { +@@ -1489,6 +1498,7 @@ static BlockDriver bdrv_mirror_top = { + .bdrv_co_block_status = bdrv_co_block_status_from_backing, + .bdrv_refresh_filename = bdrv_mirror_top_refresh_filename, + .bdrv_child_perm = bdrv_mirror_top_child_perm, ++ .bdrv_refresh_limits = bdrv_mirror_top_refresh_limits, + }; + + static void mirror_start_job(const char *job_id, BlockDriverState *bs, +@@ -1627,6 +1637,25 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, + s->should_complete = true; + } + ++ /* ++ * Must be called before we start tracking writes, but after ++ * ++ * ((MirrorBlockJob *) ++ * ((MirrorBDSOpaque *) ++ * mirror_top_bs->opaque ++ * )->job ++ * )->copy_mode ++ * ++ * has the correct value. ++ * (We start tracking writes as of the following ++ * bdrv_create_dirty_bitmap() call.) ++ */ ++ bdrv_refresh_limits(mirror_top_bs, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ goto fail; ++ } ++ + s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); + if (!s->dirty_bitmap) { + goto fail; +-- +2.19.1 + diff --git a/pr-manager-Fix-invalid-g_free-crash-bug.patch b/pr-manager-Fix-invalid-g_free-crash-bug.patch new file mode 100644 index 0000000..7e0fc7e --- /dev/null +++ b/pr-manager-Fix-invalid-g_free-crash-bug.patch @@ -0,0 +1,40 @@ +From 83f9b84c8bcb24265e25cd7f22e971e81cacebc6 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Thu, 22 Aug 2019 15:38:46 +0200 +Subject: [PATCH] pr-manager: Fix invalid g_free() crash bug +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +pr_manager_worker() passes its @opaque argument to g_free(). Wrong; +it points to pr_manager_worker()'s automatic @data. Broken when +commit 2f3a7ab39be converted @data from heap- to stack-allocated. Fix +by deleting the g_free(). + +Fixes: 2f3a7ab39bec4ba8022dc4d42ea641165b004e3e +Cc: qemu-stable@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Acked-by: Paolo Bonzini +Signed-off-by: Kevin Wolf +(cherry picked from commit 6b9d62c2a9e83bbad73fb61406f0ff69b46ff6f3) +Signed-off-by: Michael Roth +--- + scsi/pr-manager.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c +index d9f4e8c3ad..227bdfaad2 100644 +--- a/scsi/pr-manager.c ++++ b/scsi/pr-manager.c +@@ -38,7 +38,6 @@ static int pr_manager_worker(void *opaque) + int fd = data->fd; + int r; + +- g_free(data); + trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]); + + /* The reference was taken in pr_manager_execute. */ +-- +2.19.1 + diff --git a/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch b/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch new file mode 100644 index 0000000..54c4512 --- /dev/null +++ b/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch @@ -0,0 +1,59 @@ +From cb7630af20d353cbde66ddfb14d858737ffaf877 Mon Sep 17 00:00:00 2001 +From: Alberto Garcia +Date: Fri, 16 Aug 2019 15:17:42 +0300 +Subject: [PATCH] qcow2: Fix the calculation of the maximum L2 cache size + +The size of the qcow2 L2 cache defaults to 32 MB, which can be easily +larger than the maximum amount of L2 metadata that the image can have. +For example: with 64 KB clusters the user would need a qcow2 image +with a virtual size of 256 GB in order to have 32 MB of L2 metadata. + +Because of that, since commit b749562d9822d14ef69c9eaa5f85903010b86c30 +we forbid the L2 cache to become larger than the maximum amount of L2 +metadata for the image, calculated using this formula: + + uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); + +The problem with this formula is that the result should be rounded up +to the cluster size because an L2 table on disk always takes one full +cluster. + +For example, a 1280 MB qcow2 image with 64 KB clusters needs exactly +160 KB of L2 metadata, but we need 192 KB on disk (3 clusters) even if +the last 32 KB of those are not going to be used. + +However QEMU rounds the numbers down and only creates 2 cache tables +(128 KB), which is not enough for the image. + +A quick test doing 4KB random writes on a 1280 MB image gives me +around 500 IOPS, while with the correct cache size I get 16K IOPS. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit b70d08205b2e4044c529eefc21df2c8ab61b473b) +Signed-off-by: Michael Roth +--- + block/qcow2.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 840f289a48..c80f48a02b 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -831,7 +831,11 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts, + bool l2_cache_entry_size_set; + int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size; + uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; +- uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); ++ uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size); ++ /* An L2 table is always one cluster in size so the max cache size ++ * should be a multiple of the cluster size. */ ++ uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t), ++ s->cluster_size); + + combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE); + l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE); +-- +2.19.1 + diff --git a/qemu.spec b/qemu.spec index 630daa2..d993374 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.0.0 -Release: 3 +Release: 4 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY @@ -29,39 +29,57 @@ Patch0016: megasas-fix-mapped-frame-size.patch Patch0017: kbd-state-fix-autorepeat-handling.patch Patch0018: block-file-posix-Unaligned-O_DIRECT-block-status.patch Patch0019: hw-add-compat-machines-for-4.1.patch -Patch0020: q35-Revert-to-kernel-irqchip.patch -Patch0021: hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch -Patch0022: vl-Fix-drive-blockdev-persistent-reservation-managem.patch -Patch0023: vhost-fix-vhost_log-size-overflow-during-migration.patch -Patch0024: virtio-pci-fix-missing-device-properties.patch -Patch0025: i386-acpi-fix-gint-overflow-in-crs_range_compare.patch -Patch0026: ioapic-kvm-Skip-route-updates-for-masked-pins.patch -Patch0027: i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch -Patch0028: virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch -Patch0029: virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch -Patch0030: virtio-balloon-Simplify-deflate-with-pbp.patch -Patch0031: virtio-balloon-Better-names-for-offset-variables.patch -Patch0032: virtio-balloon-Rework-pbp-tracking-data.patch -Patch0033: virtio-balloon-Use-temporary-PBP-only.patch -Patch0034: virtio-balloon-don-t-track-subpages-for-the-PBP.patch -Patch0035: virtio-balloon-free-pbp-more-aggressively.patch -Patch0036: qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch -Patch0037: qemu-bridge-helper-move-repeating-code-in-parse_acl.patch -Patch0038: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch -Patch0039: hw-arm-virt-Introduce-cpu-topology-support.patch -Patch0040: hw-arm64-add-vcpu-cache-info-support.patch -Patch0041: xhci-Fix-memory-leak-in-xhci_address_slot.patch -Patch0042: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch -Patch0043: ehci-fix-queue-dev-null-ptr-dereference.patch -Patch0044: memory-unref-the-memory-region-in-simplify-flatview.patch -Patch0045: scsi-lsi-exit-infinite-loop-while-executing-script-C.patch -Patch0046: util-async-hold-AioContext-ref-to-prevent-use-after-.patch -Patch0047: vhost-user-scsi-prevent-using-uninitialized-vqs.patch -Patch0048: cpu-add-Kunpeng-920-cpu-support.patch -Patch0049: cpu-parse-feature-to-avoid-failure.patch -Patch0050: cpu-add-Cortex-A72-processor-kvm-target-support.patch -Patch0051: vnc-fix-memory-leak-when-vnc-disconnect.patch -Patch0052: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch +Patch0020: usb-tablet-fix-serial-compat-property.patch +Patch0021: q35-Revert-to-kernel-irqchip.patch +Patch0022: hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch +Patch0023: vl-Fix-drive-blockdev-persistent-reservation-management.patch +Patch0024: vhost-fix-vhost_log-size-overflow-during-migration.patch +Patch0025: virtio-pci-fix-missing-device-properties.patch +Patch0026: i386-acpi-fix-gint-overflow-in-crs_range_compare.patch +Patch0027: ioapic-kvm-Skip-route-updates-for-masked-pins.patch +Patch0028: i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch +Patch0029: virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch +Patch0030: virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch +Patch0031: virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch +Patch0032: virtio-balloon-Simplify-deflate-with-pbp.patch +Patch0033: virtio-balloon-Better-names-for-offset-variables.patch +Patch0034: virtio-balloon-Rework-pbp-tracking-data.patch +Patch0035: virtio-balloon-Use-temporary-PBP-only.patch +Patch0036: virtio-balloon-don-t-track-subpages-for-the-PBP.patch +Patch0037: virtio-balloon-free-pbp-more-aggressively.patch +Patch0038: qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch +Patch0039: qemu-bridge-helper-move-repeating-code-in-parse_acl.patch +Patch0040: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch +Patch0041: hw-arm-virt-Introduce-cpu-topology-support.patch +Patch0042: hw-arm64-add-vcpu-cache-info-support.patch +Patch0043: xhci-Fix-memory-leak-in-xhci_address_slot.patch +Patch0044: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch +Patch0045: ehci-fix-queue-dev-null-ptr-dereference.patch +Patch0046: memory-unref-the-memory-region-in-simplify-flatview.patch +Patch0047: scsi-lsi-exit-infinite-loop-while-executing-script.patch +Patch0048: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch +Patch0049: vhost-user-scsi-prevent-using-uninitialized-vqs.patch +Patch0050: cpu-add-Kunpeng-920-cpu-support.patch +Patch0051: cpu-parse-feature-to-avoid-failure.patch +Patch0052: cpu-add-Cortex-A72-processor-kvm-target-support.patch +Patch0053: vnc-fix-memory-leak-when-vnc-disconnect.patch +Patch0054: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch +Patch0055: blockdev-backup-don-t-check-aio_context-too-early.patch +Patch0056: migration-dirty-bitmaps-change-bitmap-enumeration-method.patch +Patch0057: target-i386-add-MDS-NO-feature.patch +Patch0058: usbredir-fix-buffer-overflow-on-vmload.patch +Patch0059: util-hbitmap-update-orig_size-on-truncate.patch +Patch0060: mirror-Only-mirror-granularity-aligned-chunks.patch +Patch0061: qcow2-Fix-the-calculation-of-the-maximum-L2-cache-size.patch +Patch0062: dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch +Patch0063: pr-manager-Fix-invalid-g_free-crash-bug.patch +Patch0064: block-create-Do-not-abort-if-a-block-driver-is-not-available.patch +Patch0065: block-nfs-tear-down-aio-before-nfs_close.patch +Patch0066: blockjob-update-nodes-head-while-removing-all-bdrv.patch +Patch0067: slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch +Patch0068: slirp-ip_reass-Fix-use-after-free.patch +Patch0069: hw-core-loader-Fix-possible-crash-in-rom_copy.patch +Patch0070: migration-Fix-use-after-free-during-process-exit.patch BuildRequires: flex BuildRequires: bison @@ -392,6 +410,26 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Fri Nov 12 2019 backport from qemu upstream v4.0.1 release +- usb-tablet: fix serial compat property +- blockdev-backup: don't check aio_context too early +- migration/dirty-bitmaps: change bitmap enumeration method +- target/i386: add MDS-NO feature +- usbredir: fix buffer-overflow on vmload +- tpm: Exit in reset when backend indicates failure +- tpm_emulator: Translate TPM error codes to strings +- util/hbitmap: update orig_size on truncate +- mirror: Only mirror granularity-aligned chunks +- qcow2: Fix the calculation of the maximum L2 cache size +- dma-helpers: ensure AIO callback is invoked after cancellation +- pr-manager: Fix invalid g_free() crash bug +- block/nfs: tear down aio before nfs_close +- blockjob: update nodes head while removing all bdrv +- slirp: Fix heap overflow in ip_reass on big packet input +- slirp: ip_reass: Fix use after free +- hw/core/loader: Fix possible crash in rom_copy() +- migration: Fix use-after-free during process exit + * Thu Oct 17 2019 backport from qemu upstream - vnc-fix-memory-leak-when-vnc-disconnect.patch diff --git a/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch b/scsi-lsi-exit-infinite-loop-while-executing-script.patch similarity index 100% rename from scsi-lsi-exit-infinite-loop-while-executing-script-C.patch rename to scsi-lsi-exit-infinite-loop-while-executing-script.patch diff --git a/slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch b/slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch new file mode 100644 index 0000000..3ebf029 --- /dev/null +++ b/slirp-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch @@ -0,0 +1,53 @@ +From c2e03e2aa42d0f4f41deb08c2655503835840afa Mon Sep 17 00:00:00 2001 +From: Michael Roth +Date: Tue, 24 Sep 2019 15:57:59 -0500 +Subject: [PATCH] slirp: Fix heap overflow in ip_reass on big packet input + +When the first fragment does not fit in the preallocated buffer, q will +already be pointing to the ext buffer, so we mustn't try to update it. + +Signed-off-by: Samuel Thibault +(from libslirp.git commit 126c04acbabd7ad32c2b018fe10dfac2a3bc1210) +(from libslirp.git commit e0be80430c390bce181ea04dfcdd6ea3dfa97de1) +*squash in e0be80 (clarifying comments) +Fixes: CVE-2019-14378 +Signed-off-by: Michael Roth +--- + slirp/src/ip_input.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c +index a714fecd58..68a99de5b5 100644 +--- a/slirp/src/ip_input.c ++++ b/slirp/src/ip_input.c +@@ -331,6 +331,8 @@ insert: + q = fp->frag_link.next; + m = dtom(slirp, q); + ++ int was_ext = m->m_flags & M_EXT; ++ + q = (struct ipasfrag *) q->ipf_next; + while (q != (struct ipasfrag*)&fp->frag_link) { + struct mbuf *t = dtom(slirp, q); +@@ -347,13 +349,12 @@ insert: + q = fp->frag_link.next; + + /* +- * If the fragments concatenated to an mbuf that's +- * bigger than the total size of the fragment, then and +- * m_ext buffer was alloced. But fp->ipq_next points to +- * the old buffer (in the mbuf), so we must point ip +- * into the new buffer. ++ * If the fragments concatenated to an mbuf that's bigger than the total ++ * size of the fragment and the mbuf was not already using an m_ext buffer, ++ * then an m_ext buffer was alloced. But fp->ipq_next points to the old ++ * buffer (in the mbuf), so we must point ip into the new buffer. + */ +- if (m->m_flags & M_EXT) { ++ if (!was_ext && m->m_flags & M_EXT) { + int delta = (char *)q - m->m_dat; + q = (struct ipasfrag *)(m->m_ext + delta); + } +-- +2.19.1 + diff --git a/slirp-ip_reass-Fix-use-after-free.patch b/slirp-ip_reass-Fix-use-after-free.patch new file mode 100644 index 0000000..b603379 --- /dev/null +++ b/slirp-ip_reass-Fix-use-after-free.patch @@ -0,0 +1,47 @@ +From b27192be13da3fb59f51185d9a1f944b3474b2fc Mon Sep 17 00:00:00 2001 +From: Michael Roth +Date: Tue, 24 Sep 2019 16:04:04 -0500 +Subject: [PATCH] slirp: ip_reass: Fix use after free + +Using ip_deq after m_free might read pointers from an allocation reuse. + +This would be difficult to exploit, but that is still related with +CVE-2019-14378 which generates fragmented IP packets that would trigger this +issue and at least produce a DoS. + +Signed-off-by: Samuel Thibault +(from libslirp.git commit c59279437eda91841b9d26079c70b8a540d41204) +Fixes: CVE-2019-15890 +Signed-off-by: Michael Roth +--- + slirp/src/ip_input.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c +index 68a99de5b5..89ae04e0c1 100644 +--- a/slirp/src/ip_input.c ++++ b/slirp/src/ip_input.c +@@ -297,6 +297,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) + */ + while (q != (struct ipasfrag*)&fp->frag_link && + ip->ip_off + ip->ip_len > q->ipf_off) { ++ struct ipasfrag *prev; + i = (ip->ip_off + ip->ip_len) - q->ipf_off; + if (i < q->ipf_len) { + q->ipf_len -= i; +@@ -304,9 +305,10 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) + m_adj(dtom(slirp, q), i); + break; + } ++ prev = q; + q = q->ipf_next; +- m_free(dtom(slirp, q->ipf_prev)); +- ip_deq(q->ipf_prev); ++ ip_deq(prev); ++ m_free(dtom(slirp, prev)); + } + + insert: +-- +2.19.1 + diff --git a/target-i386-add-MDS-NO-feature.patch b/target-i386-add-MDS-NO-feature.patch new file mode 100644 index 0000000..0c8ccfd --- /dev/null +++ b/target-i386-add-MDS-NO-feature.patch @@ -0,0 +1,39 @@ +From 41e1564fb50515d7902628d25c0c8421a8516cc1 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 6 Jun 2019 16:12:03 +0200 +Subject: [PATCH] target/i386: add MDS-NO feature + +Microarchitectural Data Sampling is a hardware vulnerability which allows +unprivileged speculative access to data which is available in various CPU +internal buffers. + +Some Intel processors use the ARCH_CAP_MDS_NO bit in the +IA32_ARCH_CAPABILITIES +MSR to report that they are not vulnerable, make it available to guests. + +Signed-off-by: Paolo Bonzini +Message-Id: <20190516185320.28340-1-pbonzini@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 20140a82c67467f53814ca197403d5e1b561a5e5) +Signed-off-by: Oguz Bektas +Signed-off-by: Michael Roth +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index d6bb57d210..ee4b8b47e2 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1183,7 +1183,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", +- "ssb-no", NULL, NULL, NULL, ++ "ssb-no", "mds-no", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +2.19.1 + diff --git a/usb-tablet-fix-serial-compat-property.patch b/usb-tablet-fix-serial-compat-property.patch new file mode 100644 index 0000000..6397f61 --- /dev/null +++ b/usb-tablet-fix-serial-compat-property.patch @@ -0,0 +1,39 @@ +From 665218cc085c5c1ec871d8af6986903313638fbf Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 20 May 2019 10:18:05 +0200 +Subject: [PATCH] usb-tablet: fix serial compat property +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +s/kbd/tablet/, fixes cut+paste bug. + +Cc: qemu-stable@nongnu.org +Reported-by: Dr. David Alan Gilbert +Signed-off-by: Gerd Hoffmann +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Laurent Vivier +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20190520081805.15019-1-kraxel@redhat.com +(cherry picked from commit 442bac16a6cd708a9f87adb0a263f9d833f03ed5) +Signed-off-by: Michael Roth +--- + hw/core/machine.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 743fef2898..b6766632d9 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -33,7 +33,7 @@ GlobalProperty hw_compat_3_1[] = { + { "tpm-tis", "ppi", "false" }, + { "usb-kbd", "serial", "42" }, + { "usb-mouse", "serial", "42" }, +- { "usb-kbd", "serial", "42" }, ++ { "usb-tablet", "serial", "42" }, + { "virtio-blk-device", "discard", "false" }, + { "virtio-blk-device", "write-zeroes", "false" }, + }; +-- +2.19.1 + diff --git a/usbredir-fix-buffer-overflow-on-vmload.patch b/usbredir-fix-buffer-overflow-on-vmload.patch new file mode 100644 index 0000000..2fec639 --- /dev/null +++ b/usbredir-fix-buffer-overflow-on-vmload.patch @@ -0,0 +1,55 @@ +From e86e620656becb37890a6d91e0148c74f3e43f3d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 7 Aug 2019 12:40:48 +0400 +Subject: [PATCH] usbredir: fix buffer-overflow on vmload +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If interface_count is NO_INTERFACE_INFO, let's not access the arrays +out-of-bounds. + +==994==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000243930 at pc 0x5642068086a8 bp 0x7f0b6f9ffa50 sp 0x7f0b6f9ffa40 +READ of size 1 at 0x625000243930 thread T0 + #0 0x5642068086a7 in usbredir_check_bulk_receiving /home/elmarco/src/qemu/hw/usb/redirect.c:1503 + #1 0x56420681301c in usbredir_post_load /home/elmarco/src/qemu/hw/usb/redirect.c:2154 + #2 0x5642068a56c2 in vmstate_load_state /home/elmarco/src/qemu/migration/vmstate.c:168 + #3 0x56420688e2ac in vmstate_load /home/elmarco/src/qemu/migration/savevm.c:829 + #4 0x5642068980cb in qemu_loadvm_section_start_full /home/elmarco/src/qemu/migration/savevm.c:2211 + #5 0x564206899645 in qemu_loadvm_state_main /home/elmarco/src/qemu/migration/savevm.c:2395 + #6 0x5642068998cf in qemu_loadvm_state /home/elmarco/src/qemu/migration/savevm.c:2467 + #7 0x56420685f3e9 in process_incoming_migration_co /home/elmarco/src/qemu/migration/migration.c:449 + #8 0x564207106c47 in coroutine_trampoline /home/elmarco/src/qemu/util/coroutine-ucontext.c:115 + #9 0x7f0c0604e37f (/lib64/libc.so.6+0x4d37f) + +Signed-off-by: Marc-André Lureau +Reviewed-by: Liam Merwick +Reviewed-by: Li Qiang +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20190807084048.4258-1-marcandre.lureau@redhat.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 7b84b90966568da0e05655ecaa78c209300aae6e) +Signed-off-by: Michael Roth +--- + hw/usb/redirect.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index 7cb6b120d4..586c7db025 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -1494,6 +1494,11 @@ static void usbredir_check_bulk_receiving(USBRedirDevice *dev) + for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) { + dev->endpoint[i].bulk_receiving_enabled = 0; + } ++ ++ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) { ++ return; ++ } ++ + for (i = 0; i < dev->interface_info.interface_count; i++) { + quirks = usb_get_quirks(dev->device_info.vendor_id, + dev->device_info.product_id, +-- +2.19.1 + diff --git a/util-async-hold-AioContext-ref-to-prevent-use-after-.patch b/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch similarity index 100% rename from util-async-hold-AioContext-ref-to-prevent-use-after-.patch rename to util-async-hold-AioContext-ref-to-prevent-use-after-free.patch diff --git a/util-hbitmap-update-orig_size-on-truncate.patch b/util-hbitmap-update-orig_size-on-truncate.patch new file mode 100644 index 0000000..137d8b9 --- /dev/null +++ b/util-hbitmap-update-orig_size-on-truncate.patch @@ -0,0 +1,48 @@ +From fc5c701636127a0b90cd7ab564da0354d06809dc Mon Sep 17 00:00:00 2001 +From: Vladimir Sementsov-Ogievskiy +Date: Mon, 5 Aug 2019 15:01:20 +0300 +Subject: [PATCH] util/hbitmap: update orig_size on truncate + +Without this, hbitmap_next_zero and hbitmap_next_dirty_area are broken +after truncate. So, orig_size is broken since it's introduction in +76d570dc495c56bb. + +Fixes: 76d570dc495c56bb +Signed-off-by: Vladimir Sementsov-Ogievskiy +Message-id: 20190805120120.23585-1-vsementsov@virtuozzo.com +Reviewed-by: Max Reitz +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +(cherry picked from commit 4e4de222799634d8159ee7b9303b9e1b45c6be2c) +Signed-off-by: Michael Roth +--- + util/hbitmap.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/util/hbitmap.c b/util/hbitmap.c +index 7905212a8b..bcc0acdc6a 100644 +--- a/util/hbitmap.c ++++ b/util/hbitmap.c +@@ -53,7 +53,9 @@ + */ + + struct HBitmap { +- /* Size of the bitmap, as requested in hbitmap_alloc. */ ++ /* ++ * Size of the bitmap, as requested in hbitmap_alloc or in hbitmap_truncate. ++ */ + uint64_t orig_size; + + /* Number of total bits in the bottom level. */ +@@ -732,6 +734,8 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size) + uint64_t num_elements = size; + uint64_t old; + ++ hb->orig_size = size; ++ + /* Size comes in as logical elements, adjust for granularity. */ + size = (size + (1ULL << hb->granularity) - 1) >> hb->granularity; + assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE)); +-- +2.19.1 + diff --git a/virtio-balloon-Use-temporary-PBP-only.patch b/virtio-balloon-Use-temporary-PBP-only.patch index 9d1553b..9d0a8cd 100644 --- a/virtio-balloon-Use-temporary-PBP-only.patch +++ b/virtio-balloon-Use-temporary-PBP-only.patch @@ -1,4 +1,4 @@ -From a8cd64d488325f3be5c4ddec4bf07efb3b8c7330 Mon Sep 17 00:00:00 2001 +From 8e20acad634e38f29afd54b951c42eec113288bc Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 22 Jul 2019 15:41:08 +0200 Subject: [PATCH] virtio-balloon: Use temporary PBP only @@ -23,14 +23,15 @@ Message-Id: <20190722134108.22151-7-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: David Gibson -(cherry-picked from commit a8cd64d488325f3be5c4ddec4bf07efb3b8c7330) +(cherry picked from commit a8cd64d488325f3be5c4ddec4bf07efb3b8c7330) +Signed-off-by: Michael Roth --- hw/virtio/virtio-balloon.c | 21 +++++++++------------ include/hw/virtio/virtio-balloon.h | 3 --- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index ccd766d2..d4b4a05b 100644 +index 49999d0bbe..bd54e302de 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -34,11 +34,11 @@ @@ -110,7 +111,7 @@ index ccd766d2..d4b4a05b 100644 static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h -index 1afafb12..503349a3 100644 +index 5a99293a45..d1c968d237 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -33,8 +33,6 @@ typedef struct virtio_balloon_stat_modern { @@ -127,6 +128,9 @@ index 1afafb12..503349a3 100644 int64_t stats_poll_interval; uint32_t host_features; - PartiallyBalloonedPage *pbp; - } VirtIOBalloon; - #endif + bool qemu_4_0_config_size; + } VirtIOBalloon; +-- +2.19.1 + diff --git a/virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch b/virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch new file mode 100644 index 0000000..be4a77b --- /dev/null +++ b/virtio-balloon-fix-QEMU-4.0-config-size-migration-in.patch @@ -0,0 +1,148 @@ +From a6fe4a3aa8007524ffe4758109c08f3ac102c628 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Wed, 10 Jul 2019 16:14:40 +0200 +Subject: [PATCH] virtio-balloon: fix QEMU 4.0 config size migration + incompatibility + +The virtio-balloon config size changed in QEMU 4.0 even for existing +machine types. Migration from QEMU 3.1 to 4.0 can fail in some +circumstances with the following error: + + qemu-system-x86_64: get_pci_config_device: Bad config data: i=0x10 read: a1 device: 1 cmask: ff wmask: c0 w1cmask:0 + +This happens because the virtio-balloon config size affects the VIRTIO +Legacy I/O Memory PCI BAR size. + +Introduce a qdev property called "qemu-4-0-config-size" and enable it +only for the QEMU 4.0 machine types. This way <4.0 machine types use +the old size, 4.0 uses the larger size, and >4.0 machine types use the +appropriate size depending on enabled virtio-balloon features. + +Live migration to and from old QEMUs to QEMU 4.1 works again as long as +a versioned machine type is specified (do not use just "pc"!). + +Originally-by: Wolfgang Bumiller +Signed-off-by: Stefan Hajnoczi +Message-Id: <20190710141440.27635-1-stefanha@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Tested-by: Dr. David Alan Gilbert +Tested-by: Wolfgang Bumiller +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 2bbadb08ce272d65e1f78621002008b07d1e0f03) + Conflicts: + hw/core/machine.c +* drop context dep. on 0a71966253c +Signed-off-by: Michael Roth +--- + hw/core/machine.c | 5 ++++- + hw/virtio/virtio-balloon.c | 28 +++++++++++++++++++++++++--- + include/hw/virtio/virtio-balloon.h | 2 ++ + 3 files changed, 31 insertions(+), 4 deletions(-) + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index eb34f53a85..55b08f1466 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -24,7 +24,9 @@ + #include "hw/pci/pci.h" + #include "hw/mem/nvdimm.h" + +-GlobalProperty hw_compat_4_0[] = {}; ++GlobalProperty hw_compat_4_0[] = { ++ { "virtio-balloon-device", "qemu-4-0-config-size", "true" }, ++}; + const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); + + GlobalProperty hw_compat_3_1[] = { +@@ -39,6 +41,7 @@ GlobalProperty hw_compat_3_1[] = { + { "usb-tablet", "serial", "42" }, + { "virtio-blk-device", "discard", "false" }, + { "virtio-blk-device", "write-zeroes", "false" }, ++ { "virtio-balloon-device", "qemu-4-0-config-size", "false" }, + }; + const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1); + +diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c +index 2112874055..5579260fd4 100644 +--- a/hw/virtio/virtio-balloon.c ++++ b/hw/virtio/virtio-balloon.c +@@ -615,6 +615,22 @@ virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data) + return 0; + } + ++static size_t virtio_balloon_config_size(VirtIOBalloon *s) ++{ ++ uint64_t features = s->host_features; ++ ++ if (s->qemu_4_0_config_size) { ++ return sizeof(struct virtio_balloon_config); ++ } ++ if (virtio_has_feature(features, VIRTIO_BALLOON_F_PAGE_POISON)) { ++ return sizeof(struct virtio_balloon_config); ++ } ++ if (virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { ++ return offsetof(struct virtio_balloon_config, poison_val); ++ } ++ return offsetof(struct virtio_balloon_config, free_page_report_cmd_id); ++} ++ + static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) + { + VirtIOBalloon *dev = VIRTIO_BALLOON(vdev); +@@ -635,7 +651,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) + } + + trace_virtio_balloon_get_config(config.num_pages, config.actual); +- memcpy(config_data, &config, sizeof(struct virtio_balloon_config)); ++ memcpy(config_data, &config, virtio_balloon_config_size(dev)); + } + + static int build_dimm_list(Object *obj, void *opaque) +@@ -679,7 +695,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, + uint32_t oldactual = dev->actual; + ram_addr_t vm_ram_size = get_current_ram_size(); + +- memcpy(&config, config_data, sizeof(struct virtio_balloon_config)); ++ memcpy(&config, config_data, virtio_balloon_config_size(dev)); + dev->actual = le32_to_cpu(config.actual); + if (dev->actual != oldactual) { + qapi_event_send_balloon_change(vm_ram_size - +@@ -766,7 +782,7 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) + int ret; + + virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, +- sizeof(struct virtio_balloon_config)); ++ virtio_balloon_config_size(s)); + + ret = qemu_add_balloon_handler(virtio_balloon_to_target, + virtio_balloon_stat, s); +@@ -897,6 +913,12 @@ static Property virtio_balloon_properties[] = { + VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false), + DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_FREE_PAGE_HINT, false), ++ /* QEMU 4.0 accidentally changed the config size even when free-page-hint ++ * is disabled, resulting in QEMU 3.1 migration incompatibility. This ++ * property retains this quirk for QEMU 4.1 machine types. ++ */ ++ DEFINE_PROP_BOOL("qemu-4-0-config-size", VirtIOBalloon, ++ qemu_4_0_config_size, false), + DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD, + IOThread *), + DEFINE_PROP_END_OF_LIST(), +diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h +index 1afafb12f6..5a99293a45 100644 +--- a/include/hw/virtio/virtio-balloon.h ++++ b/include/hw/virtio/virtio-balloon.h +@@ -71,6 +71,8 @@ typedef struct VirtIOBalloon { + int64_t stats_poll_interval; + uint32_t host_features; + PartiallyBalloonedPage *pbp; ++ ++ bool qemu_4_0_config_size; + } VirtIOBalloon; + + #endif +-- +2.19.1 + diff --git a/vl-Fix-drive-blockdev-persistent-reservation-managem.patch b/vl-Fix-drive-blockdev-persistent-reservation-management.patch similarity index 100% rename from vl-Fix-drive-blockdev-persistent-reservation-managem.patch rename to vl-Fix-drive-blockdev-persistent-reservation-management.patch