[Spice-commits] 102 commits - MAINTAINERS VERSION block.c block/bochs.c block/cloop.c block/curl.c block/dmg.c block/iscsi.c block/parallels.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/vdi.c block/vhdx.c block/vpc.c block/vvfat.c cpu-exec.c dma-helpers.c hw/arm hw/block hw/intc hw/misc hw/scsi include/block include/qemu include/sysemu iothread.c linux-user/syscall.c qemu-img.c target-i386/machine.c tests/Makefile tests/i82801b11-test.c tests/libqtest.c tests/libqtest.h tests/nvme-test.c tests/pvpanic-test.c tests/qemu-iotests tests/test-aio.c tests/tmp105-test.c tests/virtio-9p-test.c trace-events translate-all.c ui/input.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Apr 7 03:19:53 PDT 2014


 MAINTAINERS                                               |   12 
 VERSION                                                   |    2 
 block.c                                                   |  165 ++++----
 block/bochs.c                                             |  109 ++---
 block/cloop.c                                             |   81 +++-
 block/curl.c                                              |    5 
 block/dmg.c                                               |  275 ++++++++------
 block/iscsi.c                                             |   25 -
 block/parallels.c                                         |   14 
 block/qcow2-cluster.c                                     |   12 
 block/qcow2-refcount.c                                    |  111 +++--
 block/qcow2-snapshot.c                                    |   50 +-
 block/qcow2.c                                             |  170 +++++++-
 block/qcow2.h                                             |   52 ++
 block/vdi.c                                               |   37 +
 block/vhdx.c                                              |   12 
 block/vpc.c                                               |   32 +
 block/vvfat.c                                             |    2 
 cpu-exec.c                                                |    8 
 dma-helpers.c                                             |    1 
 hw/arm/highbank.c                                         |   19 
 hw/arm/vexpress.c                                         |    7 
 hw/block/dataplane/virtio-blk.c                           |   31 -
 hw/block/nvme.c                                           |    4 
 hw/intc/apic_common.c                                     |    7 
 hw/intc/openpic_kvm.c                                     |   10 
 hw/misc/tmp105.c                                          |    8 
 hw/scsi/scsi-bus.c                                        |    1 
 include/block/block.h                                     |    1 
 include/qemu/bswap.h                                      |    2 
 include/sysemu/iothread.h                                 |   12 
 iothread.c                                                |   11 
 linux-user/syscall.c                                      |    7 
 qemu-img.c                                                |    1 
 target-i386/machine.c                                     |    2 
 tests/Makefile                                            |   23 +
 tests/i82801b11-test.c                                    |   33 +
 tests/libqtest.c                                          |   65 ++-
 tests/libqtest.h                                          |   22 +
 tests/nvme-test.c                                         |   34 +
 tests/pvpanic-test.c                                      |   47 ++
 tests/qemu-iotests/026.out                                |    6 
 tests/qemu-iotests/029                                    |   40 +-
 tests/qemu-iotests/029.out                                |   17 
 tests/qemu-iotests/039                                    |   20 +
 tests/qemu-iotests/039.out                                |   11 
 tests/qemu-iotests/044.out                                |    2 
 tests/qemu-iotests/051                                    |   12 
 tests/qemu-iotests/051.out                                |   49 ++
 tests/qemu-iotests/075                                    |  106 +++++
 tests/qemu-iotests/075.out                                |   38 +
 tests/qemu-iotests/076                                    |   76 +++
 tests/qemu-iotests/076.out                                |   18 
 tests/qemu-iotests/078                                    |   87 ++++
 tests/qemu-iotests/078.out                                |   26 +
 tests/qemu-iotests/080                                    |  180 +++++++++
 tests/qemu-iotests/080.out                                |   83 ++++
 tests/qemu-iotests/084                                    |  104 +++++
 tests/qemu-iotests/084.out                                |   33 +
 tests/qemu-iotests/088                                    |   64 +++
 tests/qemu-iotests/088.out                                |   17 
 tests/qemu-iotests/common                                 |   21 +
 tests/qemu-iotests/common.rc                              |    3 
 tests/qemu-iotests/group                                  |    6 
 tests/qemu-iotests/sample_images/empty.bochs.bz2          |binary
 tests/qemu-iotests/sample_images/fake.parallels.bz2       |binary
 tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 |binary
 tests/test-aio.c                                          |   16 
 tests/tmp105-test.c                                       |  136 +++++-
 tests/virtio-9p-test.c                                    |   46 ++
 trace-events                                              |    2 
 translate-all.c                                           |    1 
 ui/input.c                                                |   19 
 73 files changed, 2259 insertions(+), 502 deletions(-)

New commits:
commit 466e6e9d13d56bbb6da1d2396d7d6347df483af0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 2 17:33:02 2014 +0200

    target-i386: reorder fields in cpu/msr_hyperv_hypercall subsection
    
    The subsection already exists in one well-known enterprise Linux
    distribution, but for some strange reason the fields were swapped
    when forward-porting the patch to upstream.
    
    Limit headaches for said enterprise Linux distributor when the
    time will come to rebase their version of QEMU.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1396452782-21473-1-git-send-email-pbonzini at redhat.com
    Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-i386/machine.c b/target-i386/machine.c
index 24bc373..168cab6 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -569,8 +569,8 @@ static const VMStateDescription vmstate_msr_hypercall_hypercall = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU),
         VMSTATE_UINT64(env.msr_hv_guest_os_id, X86CPU),
+        VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
commit 8ae60ee85ceaea6bfc4c62fb8ed180a1ba8010a5
Merge: bae2c27 54bee5c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Apr 5 00:18:19 2014 +0100

    Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
    
    Block patches for 2.0.0
    
    # gpg: Signature made Fri 04 Apr 2014 20:25:08 BST using RSA key ID C88F2FD6
    # gpg: Good signature from "Kevin Wolf <kwolf at redhat.com>"
    
    * remotes/kevin/tags/for-upstream:
      dataplane: replace iothread object_add() with embedded instance
      iothread: make IOThread struct definition public
      dma-helpers: Initialize DMAAIOCB in_cancel flag
      block: Check bdrv_getlength() return value in bdrv_append_temp_snapshot()
      block: Fix snapshot=on for protocol parsed from filename
      qemu-iotests: Remove CR line endings in reference output
      block: Don't parse 'filename' option
      qcow2: Put cache reference in error case
      qcow2: Flush metadata during read-only reopen
      iscsi: Don't set error if already set in iscsi_do_inquiry
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 54bee5c2b487250dcb8631ddff4307f329ec0541
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 20 15:06:32 2014 +0100

    dataplane: replace iothread object_add() with embedded instance
    
    Before IOThread was its own object, each virtio-blk device would create
    its own internal thread.  We need to preserve this behavior for
    backwards compatibility when users do not specify -device
    virtio-blk-pci,iothread=<id>.
    
    This patch changes how the internal IOThread object is created.
    Previously we used the monitor object_add() function, which is really a
    layering violation.  The problem is that this needs to assign a name but
    we don't have a name for this internal object.
    
    Generating names for internal objects is a pain but even worse is that
    they may collide with user-defined names.
    
    Paolo Bonzini <pbonzini at redhat.com> suggested that the internal IOThread
    object should not be named.  This way the conflict cannot happen and we
    no longer need object_add().
    
    One gotcha is that internal IOThread objects will not be listed by the
    query-iothreads command since they are not named.  This is okay though
    because query-iothreads is new and the internal IOThread is just for
    backwards compatibility.  New users should explicitly define IOThread
    objects.
    
    Reported-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index f558b45..70b8a5a 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -23,7 +23,7 @@
 #include "virtio-blk.h"
 #include "block/aio.h"
 #include "hw/virtio/virtio-bus.h"
-#include "monitor/monitor.h" /* for object_add() */
+#include "qom/object_interfaces.h"
 
 enum {
     SEG_MAX = 126,                  /* maximum number of I/O segments */
@@ -59,7 +59,7 @@ struct VirtIOBlockDataPlane {
      * use it).
      */
     IOThread *iothread;
-    bool internal_iothread;
+    IOThread internal_iothread_obj;
     AioContext *ctx;
     EventNotifier io_notifier;      /* Linux AIO completion */
     EventNotifier host_notifier;    /* doorbell */
@@ -391,23 +391,19 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
     s->blk = blk;
 
     if (blk->iothread) {
-        s->internal_iothread = false;
         s->iothread = blk->iothread;
+        object_ref(OBJECT(s->iothread));
     } else {
-        /* Create per-device IOThread if none specified */
-        Error *local_err = NULL;
-
-        s->internal_iothread = true;
-        object_add(TYPE_IOTHREAD, vdev->name, NULL, NULL, &local_err);
-        if (error_is_set(&local_err)) {
-            error_propagate(errp, local_err);
-            g_free(s);
-            return;
-        }
-        s->iothread = iothread_find(vdev->name);
-        assert(s->iothread);
+        /* Create per-device IOThread if none specified.  This is for
+         * x-data-plane option compatibility.  If x-data-plane is removed we
+         * can drop this.
+         */
+        object_initialize(&s->internal_iothread_obj,
+                          sizeof(s->internal_iothread_obj),
+                          TYPE_IOTHREAD);
+        user_creatable_complete(OBJECT(&s->internal_iothread_obj), &error_abort);
+        s->iothread = &s->internal_iothread_obj;
     }
-    object_ref(OBJECT(s->iothread));
     s->ctx = iothread_get_aio_context(s->iothread);
 
     /* Prevent block operations that conflict with data plane thread */
@@ -426,9 +422,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
     virtio_blk_data_plane_stop(s);
     bdrv_set_in_use(s->blk->conf.bs, 0);
     object_unref(OBJECT(s->iothread));
-    if (s->internal_iothread) {
-        object_unparent(OBJECT(s->iothread));
-    }
     g_free(s);
 }
 
commit 8c2664d86917c987944f1ca9770d1f7bbbf8eca8
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 20 15:06:31 2014 +0100

    iothread: make IOThread struct definition public
    
    Make the IOThread struct definition public so objects can be embedded in
    parent structs.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
index a32214a..7c01a61 100644
--- a/include/sysemu/iothread.h
+++ b/include/sysemu/iothread.h
@@ -15,10 +15,20 @@
 #define IOTHREAD_H
 
 #include "block/aio.h"
+#include "qemu/thread.h"
 
 #define TYPE_IOTHREAD "iothread"
 
-typedef struct IOThread IOThread;
+typedef struct {
+    Object parent_obj;
+
+    QemuThread thread;
+    AioContext *ctx;
+    QemuMutex init_done_lock;
+    QemuCond init_done_cond;    /* is thread initialization done? */
+    bool stopping;
+    int thread_id;
+} IOThread;
 
 #define IOTHREAD(obj) \
    OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
diff --git a/iothread.c b/iothread.c
index cb5986b..1fbf9f1 100644
--- a/iothread.c
+++ b/iothread.c
@@ -14,7 +14,6 @@
 #include "qom/object.h"
 #include "qom/object_interfaces.h"
 #include "qemu/module.h"
-#include "qemu/thread.h"
 #include "block/aio.h"
 #include "sysemu/iothread.h"
 #include "qmp-commands.h"
@@ -22,16 +21,6 @@
 #define IOTHREADS_PATH "/objects"
 
 typedef ObjectClass IOThreadClass;
-struct IOThread {
-    Object parent_obj;
-
-    QemuThread thread;
-    AioContext *ctx;
-    QemuMutex init_done_lock;
-    QemuCond init_done_cond;    /* is thread initialization done? */
-    bool stopping;
-    int thread_id;
-};
 
 #define IOTHREAD_GET_CLASS(obj) \
    OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
commit 4d1cb6e6f51b0d8405f701806a203a73e7431fe5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 28 14:22:49 2014 +0000

    dma-helpers: Initialize DMAAIOCB in_cancel flag
    
    Initialize the dbs->in_cancel flag in dma_bdrv_io(), since qemu_aio_get()
    does not return zero-initialized memory. Spotted by the clang sanitizer
    (which complained when the value loaded in dma_complete() was not valid
    for a bool type); this might have resulted in leaking the AIO block.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/dma-helpers.c b/dma-helpers.c
index c9620a5..5f421e9 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -213,6 +213,7 @@ BlockDriverAIOCB *dma_bdrv_io(
     dbs->sg_cur_index = 0;
     dbs->sg_cur_byte = 0;
     dbs->dir = dir;
+    dbs->in_cancel = false;
     dbs->io_func = io_func;
     dbs->bh = NULL;
     qemu_iovec_init(&dbs->iov, sg->nsg);
commit f187743acd39747cc8cc32111518142c924963b9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 4 17:07:19 2014 +0200

    block: Check bdrv_getlength() return value in bdrv_append_temp_snapshot()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>

diff --git a/block.c b/block.c
index d89c344..990a754 100644
--- a/block.c
+++ b/block.c
@@ -1184,7 +1184,12 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
        instead of opening 'filename' directly */
 
     /* Get the required size from the image */
-    total_size = bdrv_getlength(bs) & BDRV_SECTOR_MASK;
+    total_size = bdrv_getlength(bs);
+    if (total_size < 0) {
+        error_setg_errno(errp, -total_size, "Could not get image size");
+        return;
+    }
+    total_size &= BDRV_SECTOR_MASK;
 
     /* Create the temporary image */
     ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
commit b998875dcf2b21678cffa8b9a83c09930523861f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Apr 3 12:09:34 2014 +0200

    block: Fix snapshot=on for protocol parsed from filename
    
    Since commit 9fd3171a, BDRV_O_SNAPSHOT uses an option QDict to specify
    the originally requested image as the backing file of the newly created
    temporary snapshot. This means that the filename is stored in
    "file.filename", which is an option that is not parsed for protocol
    names. Therefore things like -drive file=nbd:localhost:10809 were
    broken because it looked for a local file with the literal name
    'nbd:localhost:10809'.
    
    This patch changes the way BDRV_O_SNAPSHOT works once again. We now open
    the originally requested image as normal, and then do a similar
    operation as for live snapshots to put the temporary snapshot on top.
    This way, both driver specific options and parsed filenames work.
    
    As a nice side effect, this results in code movement to factor
    bdrv_append_temp_snapshot() out. This is a good preparation for moving
    its call to drive_init() and friends eventually.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>

diff --git a/block.c b/block.c
index df2b8d1..d89c344 100644
--- a/block.c
+++ b/block.c
@@ -767,6 +767,11 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
 {
     int open_flags = flags | BDRV_O_CACHE_WB;
 
+    /* The backing file of a temporary snapshot is read-only */
+    if (flags & BDRV_O_SNAPSHOT) {
+        open_flags &= ~BDRV_O_RDWR;
+    }
+
     /*
      * Clear flags that are internal to the block layer before opening the
      * image.
@@ -1162,6 +1167,68 @@ done:
     return ret;
 }
 
+void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
+{
+    /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
+    char tmp_filename[PATH_MAX + 1];
+
+    int64_t total_size;
+    BlockDriver *bdrv_qcow2;
+    QEMUOptionParameter *create_options;
+    QDict *snapshot_options;
+    BlockDriverState *bs_snapshot;
+    Error *local_err;
+    int ret;
+
+    /* if snapshot, we create a temporary backing file and open it
+       instead of opening 'filename' directly */
+
+    /* Get the required size from the image */
+    total_size = bdrv_getlength(bs) & BDRV_SECTOR_MASK;
+
+    /* Create the temporary image */
+    ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Could not get temporary filename");
+        return;
+    }
+
+    bdrv_qcow2 = bdrv_find_format("qcow2");
+    create_options = parse_option_parameters("", bdrv_qcow2->create_options,
+                                             NULL);
+
+    set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
+
+    ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
+    free_option_parameters(create_options);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Could not create temporary overlay "
+                         "'%s': %s", tmp_filename,
+                         error_get_pretty(local_err));
+        error_free(local_err);
+        return;
+    }
+
+    /* Prepare a new options QDict for the temporary file */
+    snapshot_options = qdict_new();
+    qdict_put(snapshot_options, "file.driver",
+              qstring_from_str("file"));
+    qdict_put(snapshot_options, "file.filename",
+              qstring_from_str(tmp_filename));
+
+    bs_snapshot = bdrv_new("");
+    bs_snapshot->is_temporary = 1;
+
+    ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
+                    bs->open_flags & ~BDRV_O_SNAPSHOT, bdrv_qcow2, &local_err);
+    if (ret < 0) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    bdrv_append(bs_snapshot, bs);
+}
+
 /*
  * Opens a disk image (raw, qcow2, vmdk, ...)
  *
@@ -1182,8 +1249,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
               BlockDriver *drv, Error **errp)
 {
     int ret;
-    /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
-    char tmp_filename[PATH_MAX + 1];
     BlockDriverState *file = NULL, *bs;
     const char *drvname;
     Error *local_err = NULL;
@@ -1243,74 +1308,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         }
     }
 
-    /* For snapshot=on, create a temporary qcow2 overlay */
-    if (flags & BDRV_O_SNAPSHOT) {
-        BlockDriverState *bs1;
-        int64_t total_size;
-        BlockDriver *bdrv_qcow2;
-        QEMUOptionParameter *create_options;
-        QDict *snapshot_options;
-
-        /* if snapshot, we create a temporary backing file and open it
-           instead of opening 'filename' directly */
-
-        /* Get the required size from the image */
-        QINCREF(options);
-        bs1 = NULL;
-        ret = bdrv_open(&bs1, filename, NULL, options, BDRV_O_NO_BACKING,
-                        drv, &local_err);
-        if (ret < 0) {
-            goto fail;
-        }
-        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
-
-        bdrv_unref(bs1);
-
-        /* Create the temporary image */
-        ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
-        if (ret < 0) {
-            error_setg_errno(errp, -ret, "Could not get temporary filename");
-            goto fail;
-        }
-
-        bdrv_qcow2 = bdrv_find_format("qcow2");
-        create_options = parse_option_parameters("", bdrv_qcow2->create_options,
-                                                 NULL);
-
-        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
-
-        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err);
-        free_option_parameters(create_options);
-        if (ret < 0) {
-            error_setg_errno(errp, -ret, "Could not create temporary overlay "
-                             "'%s': %s", tmp_filename,
-                             error_get_pretty(local_err));
-            error_free(local_err);
-            local_err = NULL;
-            goto fail;
-        }
-
-        /* Prepare a new options QDict for the temporary file, where user
-         * options refer to the backing file */
-        if (filename) {
-            qdict_put(options, "file.filename", qstring_from_str(filename));
-        }
-        if (drv) {
-            qdict_put(options, "driver", qstring_from_str(drv->format_name));
-        }
-
-        snapshot_options = qdict_new();
-        qdict_put(snapshot_options, "backing", options);
-        qdict_flatten(snapshot_options);
-
-        bs->options = snapshot_options;
-        options = qdict_clone_shallow(bs->options);
-
-        filename = tmp_filename;
-        drv = bdrv_qcow2;
-        bs->is_temporary = 1;
-    }
-
     /* Open image file without format layer */
     if (flags & BDRV_O_RDWR) {
         flags |= BDRV_O_ALLOW_RDWR;
@@ -1372,6 +1369,17 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         }
     }
 
+    /* For snapshot=on, create a temporary qcow2 overlay. bs points to the
+     * temporary snapshot afterwards. */
+    if (flags & BDRV_O_SNAPSHOT) {
+        bdrv_append_temp_snapshot(bs, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            goto close_and_fail;
+        }
+    }
+
+
 done:
     /* Check if any unknown options were used */
     if (options && (qdict_size(options) != 0)) {
diff --git a/include/block/block.h b/include/block/block.h
index 1ed55d8..b3230a2 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -190,6 +190,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
                     QDict *options, const char *bdref_key, int flags,
                     bool allow_none, Error **errp);
 int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
+void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp);
 int bdrv_open(BlockDriverState **pbs, const char *filename,
               const char *reference, QDict *options, int flags,
               BlockDriver *drv, Error **errp);
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 2f79b26..073dc7a 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -218,6 +218,14 @@ echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG"
 echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
 echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on | _filter_qemu_io
 echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2 -snapshot | _filter_qemu_io
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG" -snapshot | _filter_qemu_io
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG",snapshot=on | _filter_qemu_io
+
+# Opening a read-only file r/w with snapshot=on
+chmod u-w "$TEST_IMG"
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io
+echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
+chmod u+w "$TEST_IMG"
 
 $QEMU_IO -c "read -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io
 
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index a631b0b..01b0384 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -319,6 +319,34 @@ wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 (qemu) qququiquit
 
+Testing: -drive file=file:TEST_DIR/t.qcow2 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqem
 u-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22
 qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqem
 u-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22
 qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqem
 u-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22
 qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqem
 u-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22
 qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
 read 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off
commit bae2c270906475093e3d5f4c3103dbe67bf82009
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 4 17:42:56 2014 +0100

    cpu-exec: Unlock tb_lock if we longjmp out of code generation
    
    If the guest attempts to execute from unreadable memory, this will
    cause us to longjmp back to the main loop from inside the
    target frontend decoder. For linux-user mode, this means we will
    still hold the tb_ctx.tb_lock, and will deadlock when we try to
    start executing code again. Unlock the lock in the return-from-longjmp
    code path to avoid this.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Andrei Warkentin <andrey.warkentin at gmail.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/cpu-exec.c b/cpu-exec.c
index 0914d3c..2f54054 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -227,6 +227,8 @@ int cpu_exec(CPUArchState *env)
     TranslationBlock *tb;
     uint8_t *tc_ptr;
     uintptr_t next_tb;
+    /* This must be volatile so it is not trashed by longjmp() */
+    volatile bool have_tb_lock = false;
 
     if (cpu->halted) {
         if (!cpu_has_work(cpu)) {
@@ -600,6 +602,7 @@ int cpu_exec(CPUArchState *env)
                     cpu_loop_exit(cpu);
                 }
                 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
+                have_tb_lock = true;
                 tb = tb_find_fast(env);
                 /* Note: we do it here to avoid a gcc bug on Mac OS X when
                    doing it in tb_find_slow */
@@ -621,6 +624,7 @@ int cpu_exec(CPUArchState *env)
                     tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
                                 next_tb & TB_EXIT_MASK, tb);
                 }
+                have_tb_lock = false;
                 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
 
                 /* cpu_interrupt might be called while translating the
@@ -692,6 +696,10 @@ int cpu_exec(CPUArchState *env)
 #ifdef TARGET_I386
             x86_cpu = X86_CPU(cpu);
 #endif
+            if (have_tb_lock) {
+                spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
+                have_tb_lock = false;
+            }
         }
     } /* for(;;) */
 
commit cd7ccc83512a0cba5aa0c778e7507f267cfb1b16
Author: Andrei Warkentin <andrey.warkentin at gmail.com>
Date:   Fri Apr 4 17:42:55 2014 +0100

    page_check_range: don't bail out early after unprotecting page
    
    When checking a page range, if we found that a page was
    made read-only by QEMU because it contained translated code,
    we were incorrectly returning immediately after unprotecting
    that page, rather than continuing to check the entire range,
    so we might fail to unprotect pages later in the range, or
    might incorrectly return a "success" result even if later
    pages were not writable.
    
    In particular, this could cause segfaults in a case where
    signals are delivered back to back on a target architecture
    which uses trampoline code in the stack frame (as AArch64
    currently does). The second signal causes a segfault because
    the frame cannot be written to (it was protected because
    we translated and executed the restorer trampoline, and the
    unprotect logic did not unprotect the whole range).
    
    Signed-off-by: Andrei Warkentin <andrey.warkentin at gmail.com
    [PMM: expanded commit message a bit]
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/translate-all.c b/translate-all.c
index f243c10..5759974 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1777,7 +1777,6 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
                     return -1;
                 }
             }
-            return 0;
         }
     }
     return 0;
commit d097696eba076da781967827e59f66a7857c8ecb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 4 17:42:34 2014 +0100

    hw/arm/vexpress, hw/arm/highbank: Don't insist that CPU has reset-cbar property
    
    For the machine models which can have a Cortex-A15 CPU (vexpress-a15 and
    midway), silently continue if the CPU object has no reset-cbar property
    rather than failing. This allows these boards to be used under KVM with
    the "-cpu host" option, since the 'host' CPU object has no reset-cbar
    property.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Rob Herring <rob.herring at linaro.org>

diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 2a88b84..46b9f1e 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -230,6 +230,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
 
     for (n = 0; n < smp_cpus; n++) {
         ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
+        Object *cpuobj;
         ARMCPU *cpu;
         Error *err = NULL;
 
@@ -238,15 +239,14 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
             exit(1);
         }
 
-        cpu = ARM_CPU(object_new(object_class_get_name(oc)));
+        cpuobj = object_new(object_class_get_name(oc));
+        cpu = ARM_CPU(cpuobj);
 
-        object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar",
-                                &err);
-        if (err) {
-            error_report("%s", error_get_pretty(err));
-            exit(1);
+        if (object_property_find(cpuobj, "reset-cbar", NULL)) {
+            object_property_set_int(cpuobj, MPCORE_PERIPHBASE,
+                                    "reset-cbar", &error_abort);
         }
-        object_property_set_bool(OBJECT(cpu), true, "realized", &err);
+        object_property_set_bool(cpuobj, true, "realized", &err);
         if (err) {
             error_report("%s", error_get_pretty(err));
             exit(1);
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 67628af..169eb06 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -192,10 +192,9 @@ static void init_cpus(const char *cpu_model, const char *privdev,
         Object *cpuobj = object_new(object_class_get_name(cpu_oc));
         Error *err = NULL;
 
-        object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
-        if (err) {
-            error_report("%s", error_get_pretty(err));
-            exit(1);
+        if (object_property_find(cpuobj, "reset-cbar", NULL)) {
+            object_property_set_int(cpuobj, periphbase,
+                                    "reset-cbar", &error_abort);
         }
         object_property_set_bool(cpuobj, true, "realized", &err);
         if (err) {
commit 3b418d0c45fccd850f9ad9eb4bf9bdcd96b8e6f7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 4 17:42:33 2014 +0100

    hw/arm/highbank: Don't segfault on unknown CPU names
    
    If the user passes an unknown CPU name via the '-cpu' option, exit
    with an error message rather than segfaulting.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Rob Herring <rob.herring at linaro.org>

diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index f66d57b..2a88b84 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -233,6 +233,11 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine)
         ARMCPU *cpu;
         Error *err = NULL;
 
+        if (!oc) {
+            error_report("Unable to find CPU definition");
+            exit(1);
+        }
+
         cpu = ARM_CPU(object_new(object_class_get_name(oc)));
 
         object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar",
commit cd40890816a40ba70d4cd2107629a417f0f3c648
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Apr 3 12:48:38 2014 +0200

    qemu-iotests: Remove CR line endings in reference output
    
    qemu doesn't print these CRs any more. The test still didn't fail
    because the output comparison ignores line endings, but the change turns
    up each time when you want to update the output.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>

diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 671ac5f..a631b0b 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -44,11 +44,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TE
 === Overriding backing file ===
 
 Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
-ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
-    Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
-(qemu) qququiquit
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
+    Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
+(qemu) qququiquit
 
 
 === Enable and disable lazy refcounting on the command line, plus some invalid values ===
commit e3fa4bfa72d5037bfc1de95cf243d8c57e38f5da
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Apr 3 12:45:51 2014 +0200

    block: Don't parse 'filename' option
    
    When using the QDict option 'filename', it is supposed to be interpreted
    literally. The code did correctly avoid guessing the protocol from any
    string before the first colon, but it still called bdrv_parse_filename()
    which would, for example, incorrectly remove a 'file:' prefix in the
    raw-posix driver.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>

diff --git a/block.c b/block.c
index 7a90a1b..df2b8d1 100644
--- a/block.c
+++ b/block.c
@@ -968,7 +968,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
 {
     BlockDriver *drv;
     const char *drvname;
-    bool allow_protocol_prefix = false;
+    bool parse_filename = false;
     Error *local_err = NULL;
     int ret;
 
@@ -977,7 +977,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
         filename = qdict_get_try_str(*options, "filename");
     } else if (filename && !qdict_haskey(*options, "filename")) {
         qdict_put(*options, "filename", qstring_from_str(filename));
-        allow_protocol_prefix = true;
+        parse_filename = true;
     } else {
         error_setg(errp, "Can't specify 'file' and 'filename' options at the "
                    "same time");
@@ -994,7 +994,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
         }
         qdict_del(*options, "driver");
     } else if (filename) {
-        drv = bdrv_find_protocol(filename, allow_protocol_prefix);
+        drv = bdrv_find_protocol(filename, parse_filename);
         if (!drv) {
             error_setg(errp, "Unknown protocol");
         }
@@ -1010,7 +1010,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename,
     }
 
     /* Parse the filename and open it */
-    if (drv->bdrv_parse_filename && filename) {
+    if (drv->bdrv_parse_filename && parse_filename) {
         drv->bdrv_parse_filename(filename, *options, &local_err);
         if (local_err) {
             error_propagate(errp, local_err);
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 14694e1..2f79b26 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -204,6 +204,10 @@ run_qemu -hda foo:bar
 run_qemu -drive file=foo:bar
 run_qemu -drive file.filename=foo:bar
 
+run_qemu -hda "file:$TEST_IMG"
+run_qemu -drive file="file:$TEST_IMG"
+run_qemu -drive file.filename="file:$TEST_IMG"
+
 echo
 echo === Snapshot mode ===
 echo
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index f5e33ff..671ac5f 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -275,6 +275,17 @@ QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown proto
 Testing: -drive file.filename=foo:bar
 QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory
 
+Testing: -hda file:TEST_DIR/t.qcow2
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=file:TEST_DIR/t.qcow2
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file.filename=file:TEST_DIR/t.qcow2
+QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: could not open disk image ide0-hd0: Could not open 'file:TEST_DIR/t.qcow2': No such file or directory
+
 
 === Snapshot mode ===
 
commit 8885eadedd0ea8b57c1baa367ee2c2d616700bd9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Sat Feb 8 17:44:59 2014 +0100

    qcow2: Put cache reference in error case
    
    When qcow2_get_cluster_offset() sees a zero cluster in a version 2
    image, it (rightfully) returns an error. But in doing so it shouldn't
    leak an L2 table cache reference.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 60a6910..331ab08 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -491,6 +491,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
         break;
     case QCOW2_CLUSTER_ZERO:
         if (s->qcow_version < 3) {
+            qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
             return -EIO;
         }
         c = count_contiguous_clusters(nb_clusters, s->cluster_size,
commit 4c2e5f8f46a17966dc45b5a3e07b97434c0eabdf
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Apr 3 13:47:50 2014 +0200

    qcow2: Flush metadata during read-only reopen
    
    If lazy refcounts are enabled for a backing file, committing to this
    backing file may leave it in a dirty state even if the commit succeeds.
    The reason is that the bdrv_flush() call in bdrv_commit() doesn't flush
    refcount updates with lazy refcounts enabled, and qcow2_reopen_prepare()
    doesn't take care to flush metadata.
    
    In order to fix this, this patch also fixes qcow2_mark_clean(), which
    contains another ineffective bdrv_flush() call beause lazy refcounts are
    disabled only afterwards. All existing callers of qcow2_mark_clean()
    either don't modify refcounts or already flush manually, so that this
    fixes only a latent, but not yet actually triggerable bug.
    
    Another instance of the same problem is live snapshots. Again, a real
    corruption is prevented by an explicit flush for non-read-only images in
    external_snapshot_prepare(), but images using lazy refcounts stay dirty.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 333e26d..e903d97 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -269,12 +269,15 @@ static int qcow2_mark_clean(BlockDriverState *bs)
     BDRVQcowState *s = bs->opaque;
 
     if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
-        int ret = bdrv_flush(bs);
+        int ret;
+
+        s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
+
+        ret = bdrv_flush(bs);
         if (ret < 0) {
             return ret;
         }
 
-        s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
         return qcow2_update_header(bs);
     }
     return 0;
@@ -900,11 +903,25 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
     return 0;
 }
 
-/* We have nothing to do for QCOW2 reopen, stubs just return
- * success */
+/* We have no actual commit/abort logic for qcow2, but we need to write out any
+ * unwritten data if we reopen read-only. */
 static int qcow2_reopen_prepare(BDRVReopenState *state,
                                 BlockReopenQueue *queue, Error **errp)
 {
+    int ret;
+
+    if ((state->flags & BDRV_O_RDWR) == 0) {
+        ret = bdrv_flush(state->bs);
+        if (ret < 0) {
+            return ret;
+        }
+
+        ret = qcow2_mark_clean(state->bs);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
     return 0;
 }
 
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index 9b355c0..b9cbe99 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -131,6 +131,26 @@ ulimit -c "$old_ulimit"
 ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
 _check_test_img
 
+echo
+echo "== Committing to a backing file with lazy_refcounts=on =="
+
+IMGOPTS="compat=1.1,lazy_refcounts=on"
+TEST_IMG="$TEST_IMG".base _make_test_img $size
+
+IMGOPTS="compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base"
+_make_test_img $size
+
+$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG commit "$TEST_IMG"
+
+# The dirty bit must not be set
+./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+./qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
+
+_check_test_img
+TEST_IMG="$TEST_IMG".base _check_test_img
+
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
index 077fa64..fb31ae0 100644
--- a/tests/qemu-iotests/039.out
+++ b/tests/qemu-iotests/039.out
@@ -54,4 +54,15 @@ wrote 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 incompatible_features     0x0
 No errors were found on the image.
+
+== Committing to a backing file with lazy_refcounts=on ==
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' 
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Image committed.
+incompatible_features     0x0
+incompatible_features     0x0
+No errors were found on the image.
+No errors were found on the image.
 *** done
commit cbee81f6de57ddc1b21ba28f01f6a3b5d87428a5
Author: Fam Zheng <famz at redhat.com>
Date:   Fri Apr 4 19:53:29 2014 +0800

    iscsi: Don't set error if already set in iscsi_do_inquiry
    
    This eliminates the possible assertion failure in error_setg().
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 21c18a3..64a509f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1101,8 +1101,10 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun,
     return task;
 
 fail:
-    error_setg(errp, "iSCSI: Inquiry command failed : %s",
-               iscsi_get_error(iscsi));
+    if (!error_is_set(errp)) {
+        error_setg(errp, "iSCSI: Inquiry command failed : %s",
+                   iscsi_get_error(iscsi));
+    }
     if (task != NULL) {
         scsi_free_scsi_task(task);
     }
commit 5913815a17387a5e9825c734ccab760588471ee5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 3 15:51:01 2014 +0100

    Update version for v2.0.0-rc1 release
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/VERSION b/VERSION
index 32c79ec..0ff4310 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.7.90
+1.7.91
commit 888157fe96f68488efcdf50cbdb6f72291ab903e
Merge: de03c31 d25295d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 3 14:31:20 2014 +0100

    Merge remote-tracking branch 'remotes/riku/for-2.0' into staging
    
    * remotes/riku/for-2.0:
      linux-user: pass correct host flags to accept4()
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit de03c3164accc21311c39327601fcdd95da301f3
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Wed Apr 2 16:06:38 2014 +0200

    bswap: Fix build on FreeBSD 10.0
    
    FreeBSD 10.0-RELEASE has bswap16() etc. macros defined in sys/endian.h,
    which leads to a conflict with our static inline definitions.
    
    Force using the system version of the macros.
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Tested-by: Ed Maste <emaste at freebsd.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 0cb7c05..0f9c6cf 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -11,6 +11,8 @@
 # include <sys/endian.h>
 # include <sys/types.h>
 # include <machine/bswap.h>
+#elif defined(__FreeBSD__)
+# include <sys/endian.h>
 #elif defined(CONFIG_BYTESWAP_H)
 # include <byteswap.h>
 
commit 87d8354de3560eb705bcee83142d775f703177a6
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Apr 2 11:41:58 2014 +0200

    PPC: openpic_kvm: Filter memory events properly
    
    Commit 6f1834a2b exposed a bug in openpic_kvm where we don't filter
    for memory events that only happen to the region we want to know
    events about.
    
    Add proper filtering, fixing the e500plat target with KVM.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Message-id: 1396431718-14908-1-git-send-email-agraf at suse.de
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c
index afa604d..6635407 100644
--- a/hw/intc/openpic_kvm.c
+++ b/hw/intc/openpic_kvm.c
@@ -118,6 +118,11 @@ static void kvm_openpic_region_add(MemoryListener *listener,
         abort();
     }
 
+    /* Ignore events on regions that are not us */
+    if (section->mr != &opp->mem) {
+        return;
+    }
+
     reg_base = section->offset_within_address_space;
 
     attr.group = KVM_DEV_MPIC_GRP_MISC;
@@ -140,6 +145,11 @@ static void kvm_openpic_region_del(MemoryListener *listener,
     uint64_t reg_base = 0;
     int ret;
 
+    /* Ignore events on regions that are not us */
+    if (section->mr != &opp->mem) {
+        return;
+    }
+
     attr.group = KVM_DEV_MPIC_GRP_MISC;
     attr.attr = KVM_DEV_MPIC_BASE_ADDR;
     attr.addr = (uint64_t)(unsigned long)&reg_base;
commit 784a5592c9e7721d9035a83570f09a286cf75284
Merge: 97891af c97ca29
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Apr 3 12:24:35 2014 +0100

    Merge remote-tracking branch 'remotes/bonzini/scsi-next' into staging
    
    * remotes/bonzini/scsi-next:
      iscsi: always query max WRITE SAME length
      iscsi: ignore flushes on scsi-generic devices
      iscsi: recognize "invalid field" ASCQ from WRITE SAME command
      scsi-bus: remove bogus assertion
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 97891afab801a31dc65e265ff9210a951b952e76
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Wed Apr 2 23:31:11 2014 -0700

    MAINTAINERS: Update Peter Crosthwaite's email
    
    Change over to my proper Xilinx email. s/petalogix.com/xilinx.com.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: cdff0c388c70df06217c467dcfb89267b7911feb.1396506607.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/MAINTAINERS b/MAINTAINERS
index 4923b0f..34b8c3f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -304,7 +304,7 @@ S: Maintained
 F: hw/*/versatile*
 
 Xilinx Zynq
-M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+M: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
 S: Maintained
 F: hw/arm/xilinx_zynq.c
 F: hw/misc/zynq_slcr.c
@@ -353,7 +353,7 @@ S: Maintained
 F: hw/microblaze/petalogix_s3adsp1800_mmu.c
 
 petalogix_ml605
-M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+M: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
 S: Maintained
 F: hw/microblaze/petalogix_ml605_mmu.c
 
@@ -592,7 +592,7 @@ S: Orphan
 F: hw/scsi/lsi53c895a.c
 
 SSI
-M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+M: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
 S: Maintained
 F: hw/ssi/*
 F: hw/block/m25p80.c
@@ -652,7 +652,7 @@ F: hw/block/nvme*
 F: tests/nvme-test.c
 
 Xilinx EDK
-M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+M: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
 M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
 S: Maintained
 F: hw/*/xilinx_*
@@ -696,7 +696,7 @@ F: include/hw/cpu/icc_bus.h
 F: hw/cpu/icc_bus.c
 
 Device Tree
-M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+M: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
 M: Alexander Graf <agraf at suse.de>
 S: Maintained
 F: device_tree.[ch]
commit c97ca29db0a68deb281a901f535cec5ea4862244
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 2 15:30:29 2014 +0200

    iscsi: always query max WRITE SAME length
    
    Max WRITE SAME length is also used when the UNMAP bit is zero, so it
    should be queried even if LBPWS=0.  Same for the optimal transfer
    length.
    
    However, the write_zeroes_alignment only matters for UNMAP=1 so we
    still restrict it to LBPWS=1.
    
    Reviewed-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index e68aa0f..21c18a3 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1335,18 +1335,20 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
 
     /* We don't actually refresh here, but just return data queried in
      * iscsi_open(): iscsi targets don't change their limits. */
-    if (iscsilun->lbp.lbpu || iscsilun->lbp.lbpws) {
+    if (iscsilun->lbp.lbpu) {
         if (iscsilun->bl.max_unmap < 0xffffffff) {
             bs->bl.max_discard = sector_lun2qemu(iscsilun->bl.max_unmap,
                                                  iscsilun);
         }
         bs->bl.discard_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
                                                    iscsilun);
+    }
 
-        if (iscsilun->bl.max_ws_len < 0xffffffff) {
-            bs->bl.max_write_zeroes = sector_lun2qemu(iscsilun->bl.max_ws_len,
-                                                      iscsilun);
-        }
+    if (iscsilun->bl.max_ws_len < 0xffffffff) {
+        bs->bl.max_write_zeroes = sector_lun2qemu(iscsilun->bl.max_ws_len,
+                                                  iscsilun);
+    }
+    if (iscsilun->lbp.lbpws) {
         bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
                                                         iscsilun);
     }
commit b2f9c08a4f11f16ec101e95feab8e71d7cfcfee9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 2 15:04:41 2014 +0200

    iscsi: ignore flushes on scsi-generic devices
    
    Non-block SCSI devices do not support flushing, but we may still send
    them requests via bdrv_flush_all.  Just ignore them.
    
    Reviewed-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 2f96a8e..e68aa0f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -417,6 +417,10 @@ static int coroutine_fn iscsi_co_flush(BlockDriverState *bs)
     IscsiLun *iscsilun = bs->opaque;
     struct IscsiTask iTask;
 
+    if (bs->sg) {
+        return 0;
+    }
+
     iscsi_co_init_iscsitask(iscsilun, &iTask);
 
 retry:
commit 27898a5daa4c6d28adb32b401a011d7198494482
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 2 12:12:50 2014 +0200

    iscsi: recognize "invalid field" ASCQ from WRITE SAME command
    
    Some targets may return "invalid field" as the ASCQ from WRITE SAME
    if they support the command only without the UNMAP field.  Recognize
    that, and return ENOTSUP just like for "invalid operation code".
    
    Reviewed-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index b490e98..2f96a8e 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -838,7 +838,8 @@ retry:
 
     if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
         iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
-        iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
+        (iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE ||
+         iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB)) {
         /* WRITE SAME is not supported by the target */
         iscsilun->has_write_same = false;
         scsi_free_scsi_task(iTask.task);
commit d581eb7ca4b58649ade5fb7570ecf6b4b9a41879
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Apr 2 13:24:23 2014 +0200

    scsi-bus: remove bogus assertion
    
    This assertion is invalid, because get_sg_list can return an
    empty sg-list even for commands that transfer no data (such
    as SYNCHRONIZE CACHE).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index eaad925..ae921a6 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -101,7 +101,6 @@ static void scsi_dma_restart_bh(void *opaque)
                 scsi_req_continue(req);
                 break;
             case SCSI_XFER_NONE:
-                assert(!req->sg);
                 scsi_req_dequeue(req);
                 scsi_req_enqueue(req);
                 break;
commit 82c6f513735297ad76acaaf2e87f0c5a0b3647a7
Merge: 53e11bd 9bcec93
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 1 20:45:42 2014 +0100

    Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
    
    Tracing pull request
    
    # gpg: Signature made Tue 01 Apr 2014 19:08:48 BST using RSA key ID 81AB73C8
    # gpg: Good signature from "Stefan Hajnoczi <stefanha at redhat.com>"
    # gpg:                 aka "Stefan Hajnoczi <stefanha at gmail.com>"
    
    * remotes/stefanha/tags/tracing-pull-request:
      trace: add workaround for SystemTap PR13296
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 9bcec938aab22a1b7ced916a6895e5029d4ed04f
Author: Frank Ch. Eigler <fche at redhat.com>
Date:   Tue Mar 25 13:08:30 2014 +0100

    trace: add workaround for SystemTap PR13296
    
    SystemTap sdt.h sometimes results in compiled probes without sufficient
    information to extract arguments.  This can be solved in a slightly
    hacky way by encouraging the compiler to place arguments into registers.
    
    This patch fixes the apic_reset_irq_delivered() trace event on Fedora 20
    with gcc-4.8.2-7.fc20 and systemtap-sdt-devel-2.4-2.fc20 on x86_64.
    
    Signed-off-by: Frank Ch. Eigler <fche at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index c623fcc..7ecce2d 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -117,7 +117,12 @@ void apic_report_irq_delivered(int delivered)
 
 void apic_reset_irq_delivered(void)
 {
-    trace_apic_reset_irq_delivered(apic_irq_delivered);
+    /* Copy this into a local variable to encourage gcc to emit a plain
+     * register for a sys/sdt.h marker.  For details on this workaround, see:
+     * https://sourceware.org/bugzilla/show_bug.cgi?id=13296
+     */
+    volatile int a_i_d = apic_irq_delivered;
+    trace_apic_reset_irq_delivered(a_i_d);
 
     apic_irq_delivered = 0;
 }
commit 53e11bd384a799c03884bd7d8b5be53f025f8e2d
Merge: 507979a c792707
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 1 18:23:28 2014 +0100

    Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
    
    Block pull request
    
    # gpg: Signature made Tue 01 Apr 2014 18:11:16 BST using RSA key ID 81AB73C8
    # gpg: Good signature from "Stefan Hajnoczi <stefanha at redhat.com>"
    # gpg:                 aka "Stefan Hajnoczi <stefanha at gmail.com>"
    
    * remotes/stefanha/tags/block-pull-request: (51 commits)
      qcow2: link all L2 meta updates in preallocate()
      parallels: Sanity check for s->tracks (CVE-2014-0142)
      parallels: Fix catalog size integer overflow (CVE-2014-0143)
      qcow2: Limit snapshot table size
      qcow2: Check maximum L1 size in qcow2_snapshot_load_tmp() (CVE-2014-0143)
      qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145)
      qcow2: Fix NULL dereference in qcow2_open() error path (CVE-2014-0146)
      qcow2: Fix copy_sectors() with VM state
      block: Limit request size (CVE-2014-0143)
      block: vdi bounds check qemu-io tests
      dmg: prevent chunk buffer overflow (CVE-2014-0145)
      dmg: use uint64_t consistently for sectors and lengths
      dmg: sanitize chunk length and sectorcount (CVE-2014-0145)
      dmg: use appropriate types when reading chunks
      dmg: drop broken bdrv_pread() loop
      dmg: prevent out-of-bounds array access on terminator
      dmg: coding style and indentation cleanup
      qcow2: Fix new L1 table size check (CVE-2014-0143)
      qcow2: Protect against some integer overflows in bdrv_check
      qcow2: Fix types in qcow2_alloc_clusters and alloc_clusters_noref
      ...
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 507979a8bda895d56d02112907ccbca753dbbdce
Merge: 95224e8 bdcc3a2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Apr 1 16:58:04 2014 +0100

    Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-7' into staging
    
    input bugfixes for 2.0
    
    # gpg: Signature made Tue 01 Apr 2014 10:16:43 BST using RSA key ID D3E87138
    # gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
    # gpg:                 aka "Gerd Hoffmann <gerd at kraxel.org>"
    # gpg:                 aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
    
    * remotes/kraxel/tags/pull-input-7:
      input: add sanity check
      input: mouse_set should check input device type.
      input: fix input_event_key_number trace event
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit c792707f54aa445cfb63a42411c66594b52b8f79
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Tue Apr 1 11:12:57 2014 +0200

    qcow2: link all L2 meta updates in preallocate()
    
    preallocate() only links the first QCowL2Meta's data clusters into the
    L2 table and ignores any chained QCowL2Metas in the linked list.
    
    Chains of QCowL2Meta structs are built up when contiguous clusters span
    L2 tables.  Each QCowL2Meta describes one L2 table update.  This is a
    rare case in preallocate() but can happen.
    
    This patch fixes preallocate() by iterating over the whole list of
    QCowL2Metas.  Compare with the qcow2_co_writev() function's
    implementation, which is similar but also also handles request
    dependencies.  preallocate() only performs one allocation at a time so
    there can be no dependencies.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index bb6000f..333e26d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1531,7 +1531,9 @@ static int preallocate(BlockDriverState *bs)
             return ret;
         }
 
-        if (meta != NULL) {
+        while (meta) {
+            QCowL2Meta *next = meta->next;
+
             ret = qcow2_alloc_cluster_link_l2(bs, meta);
             if (ret < 0) {
                 qcow2_free_any_clusters(bs, meta->alloc_offset,
@@ -1542,6 +1544,9 @@ static int preallocate(BlockDriverState *bs)
             /* There are no dependent requests, but we need to remove our
              * request from the list of in-flight requests */
             QLIST_REMOVE(meta, next_in_flight);
+
+            g_free(meta);
+            meta = next;
         }
 
         /* TODO Preallocate data if requested */
commit 9302e863aa8baa5d932fc078967050c055fa1a7f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:09 2014 +0100

    parallels: Sanity check for s->tracks (CVE-2014-0142)
    
    This avoids a possible division by zero.
    
    Convert s->tracks to unsigned as well because it feels better than
    surviving just because the results of calculations with s->tracks are
    converted to unsigned anyway.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/parallels.c b/block/parallels.c
index fe47ecb..1a5bd35 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -51,7 +51,7 @@ typedef struct BDRVParallelsState {
     uint32_t *catalog_bitmap;
     unsigned int catalog_size;
 
-    int tracks;
+    unsigned int tracks;
 } BDRVParallelsState;
 
 static int parallels_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -93,6 +93,11 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
     bs->total_sectors = le32_to_cpu(ph.nb_sectors);
 
     s->tracks = le32_to_cpu(ph.tracks);
+    if (s->tracks == 0) {
+        error_setg(errp, "Invalid image: Zero sectors per track");
+        ret = -EINVAL;
+        goto fail;
+    }
 
     s->catalog_size = le32_to_cpu(ph.catalog_entries);
     if (s->catalog_size > INT_MAX / 4) {
diff --git a/tests/qemu-iotests/076 b/tests/qemu-iotests/076
index 6028ac5..b614a7d 100755
--- a/tests/qemu-iotests/076
+++ b/tests/qemu-iotests/076
@@ -42,6 +42,7 @@ _supported_fmt parallels
 _supported_proto generic
 _supported_os Linux
 
+tracks_offset=$((0x1c))
 catalog_entries_offset=$((0x20))
 nb_sectors_offset=$((0x24))
 
@@ -63,6 +64,12 @@ poke_file "$TEST_IMG" "$nb_sectors_offset" "\xff\xff\xff\xff"
 poke_file "$TEST_IMG" "$catalog_entries_offset" "\x01\x00\x00\x40"
 { $QEMU_IO -c "read 64M 64M" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Zero sectors per track =="
+_use_sample_img fake.parallels.bz2
+poke_file "$TEST_IMG" "$tracks_offset" "\x00\x00\x00\x00"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/076.out b/tests/qemu-iotests/076.out
index 12af42a..f7745d8 100644
--- a/tests/qemu-iotests/076.out
+++ b/tests/qemu-iotests/076.out
@@ -11,4 +11,8 @@ no file open, try 'help open'
 == Overflow in catalog allocation ==
 qemu-io: can't open device TEST_DIR/fake.parallels: Catalog too large
 no file open, try 'help open'
+
+== Zero sectors per track ==
+qemu-io: can't open device TEST_DIR/fake.parallels: Invalid image: Zero sectors per track
+no file open, try 'help open'
 *** done
commit afbcc40bee4ef51731102d7d4b499ee12fc182e1
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:08 2014 +0100

    parallels: Fix catalog size integer overflow (CVE-2014-0143)
    
    The first test case would cause a huge memory allocation, leading to a
    qemu abort; the second one to a too small malloc() for the catalog
    (smaller than s->catalog_size), which causes a read-only out-of-bounds
    array access and on big endian hosts an endianess conversion for an
    undefined memory area.
    
    The sample image used here is not an original Parallels image. It was
    created using an hexeditor on the basis of the struct that qemu uses.
    Good enough for trying to crash the driver, but not for ensuring
    compatibility.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/parallels.c b/block/parallels.c
index 3f588f5..fe47ecb 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -49,7 +49,7 @@ typedef struct BDRVParallelsState {
     CoMutex lock;
 
     uint32_t *catalog_bitmap;
-    int catalog_size;
+    unsigned int catalog_size;
 
     int tracks;
 } BDRVParallelsState;
@@ -95,6 +95,11 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
     s->tracks = le32_to_cpu(ph.tracks);
 
     s->catalog_size = le32_to_cpu(ph.catalog_entries);
+    if (s->catalog_size > INT_MAX / 4) {
+        error_setg(errp, "Catalog too large");
+        ret = -EFBIG;
+        goto fail;
+    }
     s->catalog_bitmap = g_malloc(s->catalog_size * 4);
 
     ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4);
diff --git a/tests/qemu-iotests/076 b/tests/qemu-iotests/076
new file mode 100755
index 0000000..6028ac5
--- /dev/null
+++ b/tests/qemu-iotests/076
@@ -0,0 +1,69 @@
+#!/bin/bash
+#
+# parallels format input validation tests
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt parallels
+_supported_proto generic
+_supported_os Linux
+
+catalog_entries_offset=$((0x20))
+nb_sectors_offset=$((0x24))
+
+echo
+echo "== Read from a valid (enough) image =="
+_use_sample_img fake.parallels.bz2
+{ $QEMU_IO -c "read -P 0x11 0 64k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Negative catalog size =="
+_use_sample_img fake.parallels.bz2
+poke_file "$TEST_IMG" "$catalog_entries_offset" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Overflow in catalog allocation =="
+_use_sample_img fake.parallels.bz2
+poke_file "$TEST_IMG" "$nb_sectors_offset" "\xff\xff\xff\xff"
+poke_file "$TEST_IMG" "$catalog_entries_offset" "\x01\x00\x00\x40"
+{ $QEMU_IO -c "read 64M 64M" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/076.out b/tests/qemu-iotests/076.out
new file mode 100644
index 0000000..12af42a
--- /dev/null
+++ b/tests/qemu-iotests/076.out
@@ -0,0 +1,14 @@
+QA output created by 076
+
+== Read from a valid (enough) image ==
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Negative catalog size ==
+qemu-io: can't open device TEST_DIR/fake.parallels: Catalog too large
+no file open, try 'help open'
+
+== Overflow in catalog allocation ==
+qemu-io: can't open device TEST_DIR/fake.parallels: Catalog too large
+no file open, try 'help open'
+*** done
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index a09d9c8..0aaf84d 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -139,6 +139,7 @@ check options
     -bochs              test bochs
     -cow                test cow
     -cloop              test cloop
+    -parallels          test parallels
     -qcow               test qcow
     -qcow2              test qcow2
     -qed                test qed
@@ -192,6 +193,12 @@ testlist options
             xpand=false
             ;;
 
+        -parallels)
+            IMGFMT=parallels
+            IMGFMT_GENERIC=false
+            xpand=false
+            ;;
+
         -qcow)
             IMGFMT=qcow
             xpand=false
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index c51640c..864643d 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -82,6 +82,7 @@
 073 rw auto quick
 074 rw auto quick
 075 rw auto
+076 auto
 077 rw auto quick
 078 rw auto
 079 rw auto
diff --git a/tests/qemu-iotests/sample_images/fake.parallels.bz2 b/tests/qemu-iotests/sample_images/fake.parallels.bz2
new file mode 100644
index 0000000..ffb5f13
Binary files /dev/null and b/tests/qemu-iotests/sample_images/fake.parallels.bz2 differ
commit 5dae6e30c531feb31eed99f9039b52bf70832ce3
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:07 2014 +0100

    qcow2: Limit snapshot table size
    
    Even with a limit of 64k snapshots, each snapshot could have a filename
    and an ID with up to 64k, which would still lead to pretty large
    allocations, which could potentially lead to qemu aborting. Limit the
    total size of the snapshot table to an average of 1k per entry when
    the limit of 64k snapshots is fully used. This should be plenty for any
    reasonable user.
    
    This also fixes potential integer overflows of s->snapshot_size.
    
    Suggested-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 5db4f30..0aa9def 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -116,8 +116,14 @@ int qcow2_read_snapshots(BlockDriverState *bs)
         }
         offset += name_size;
         sn->name[name_size] = '\0';
+
+        if (offset - s->snapshots_offset > QCOW_MAX_SNAPSHOTS_SIZE) {
+            ret = -EFBIG;
+            goto fail;
+        }
     }
 
+    assert(offset - s->snapshots_offset <= INT_MAX);
     s->snapshots_size = offset - s->snapshots_offset;
     return 0;
 
@@ -138,7 +144,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         uint32_t nb_snapshots;
         uint64_t snapshots_offset;
     } QEMU_PACKED header_data;
-    int64_t offset, snapshots_offset;
+    int64_t offset, snapshots_offset = 0;
     int ret;
 
     /* compute the size of the snapshots */
@@ -150,7 +156,14 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
         offset += sizeof(extra);
         offset += strlen(sn->id_str);
         offset += strlen(sn->name);
+
+        if (offset > QCOW_MAX_SNAPSHOTS_SIZE) {
+            ret = -EFBIG;
+            goto fail;
+        }
     }
+
+    assert(offset <= INT_MAX);
     snapshots_size = offset;
 
     /* Allocate space for the new snapshot list */
diff --git a/block/qcow2.h b/block/qcow2.h
index f28e7d9..b49424b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -48,6 +48,10 @@
  * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
 #define QCOW_MAX_L1_SIZE 0x2000000
 
+/* Allow for an average of 1k per snapshot table entry, should be plenty of
+ * space for snapshot names and IDs */
+#define QCOW_MAX_SNAPSHOTS_SIZE (1024 * QCOW_MAX_SNAPSHOTS)
+
 /* indicate that the refcount of the referenced cluster is exactly one. */
 #define QCOW_OFLAG_COPIED     (1ULL << 63)
 /* indicate that the cluster is compressed (they never have the copied flag) */
commit 6a83f8b5bec6f59e56cc49bd49e4c3f8f805d56f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:06 2014 +0100

    qcow2: Check maximum L1 size in qcow2_snapshot_load_tmp() (CVE-2014-0143)
    
    This avoids an unbounded allocation.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 715168e..5db4f30 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -680,6 +680,10 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
     sn = &s->snapshots[snapshot_index];
 
     /* Allocate and read in the snapshot's L1 table */
+    if (sn->l1_size > QCOW_MAX_L1_SIZE) {
+        error_setg(errp, "Snapshot L1 table too large");
+        return -EFBIG;
+    }
     new_l1_bytes = sn->l1_size * sizeof(uint64_t);
     new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
 
diff --git a/block/qcow2.c b/block/qcow2.c
index be48a27..bb6000f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -638,9 +638,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     /* read the level 1 table */
-    if (header.l1_size > 0x2000000) {
-        /* 32 MB L1 table is enough for 2 PB images at 64k cluster size
-         * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
+    if (header.l1_size > QCOW_MAX_L1_SIZE) {
         error_setg(errp, "Active L1 table too large");
         ret = -EFBIG;
         goto fail;
diff --git a/block/qcow2.h b/block/qcow2.h
index 3649465..f28e7d9 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -44,6 +44,10 @@
  * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
 #define QCOW_MAX_REFTABLE_SIZE 0x800000
 
+/* 32 MB L1 table is enough for 2 PB images at 64k cluster size
+ * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
+#define QCOW_MAX_L1_SIZE 0x2000000
+
 /* indicate that the refcount of the referenced cluster is exactly one. */
 #define QCOW_OFLAG_COPIED     (1ULL << 63)
 /* indicate that the cluster is compressed (they never have the copied flag) */
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 59e7a44..6b3a3e7 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -30,7 +30,8 @@ status=1	# failure is the default!
 
 _cleanup()
 {
-	_cleanup_test_img
+    rm -f $TEST_IMG.snap
+    _cleanup_test_img
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -58,6 +59,10 @@ offset_ext_size=$((header_size + 4))
 
 offset_l2_table_0=$((0x40000))
 
+offset_snap1=$((0x70000))
+offset_snap1_l1_offset=$((offset_snap1 + 0))
+offset_snap1_l1_size=$((offset_snap1 + 8))
+
 echo
 echo "== Huge header size =="
 _make_test_img 64M
@@ -161,6 +166,14 @@ poke_file "$TEST_IMG" "$offset_l2_table_0" "\xbf\xff\xff\xff\xff\xff\x00\x00"
 poke_file "$TEST_IMG" "$offset_l2_table_0" "\x80\x00\x00\xff\xff\xff\x00\x00"
 { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Invalid snapshot L1 table =="
+_make_test_img 64M
+{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
+poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
+{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 4d84fbf..f7a943c 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -74,4 +74,10 @@ wrote 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-img: Could not create snapshot 'test': -27 (File too large)
 qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unavailable)
+
+== Invalid snapshot L1 table ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Failed to load snapshot: Snapshot L1 table too large
 *** done
commit c05e4667be91b46ab42b5a11babf8e84d476cc6b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:05 2014 +0100

    qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp() (CVE-2014-0145)
    
    For the L1 table to loaded for an internal snapshot, the code allocated
    only enough memory to hold the currently active L1 table. If the
    snapshot's L1 table is actually larger than the current one, this leads
    to a buffer overflow.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 87fbfe1..715168e 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -680,7 +680,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
     sn = &s->snapshots[snapshot_index];
 
     /* Allocate and read in the snapshot's L1 table */
-    new_l1_bytes = s->l1_size * sizeof(uint64_t);
+    new_l1_bytes = sn->l1_size * sizeof(uint64_t);
     new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
 
     ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
index 567e071..fa46ace 100755
--- a/tests/qemu-iotests/029
+++ b/tests/qemu-iotests/029
@@ -30,7 +30,8 @@ status=1	# failure is the default!
 
 _cleanup()
 {
-	_cleanup_test_img
+    rm -f $TEST_IMG.snap
+    _cleanup_test_img
 }
 trap "_cleanup; exit \$status" 0 1 2 3 15
 
@@ -44,6 +45,9 @@ _supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
 
+offset_size=24
+offset_l1_size=36
+
 echo
 echo Test loading internal snapshots where the L1 table of the snapshot
 echo is smaller than the current L1 table.
@@ -77,6 +81,18 @@ _make_test_img 64M
 _check_test_img
 
 
+echo
+echo "qcow2_snapshot_load_tmp() should take the L1 size from the snapshot"
+echo
+
+CLUSTER_SIZE=512
+_make_test_img 64M
+{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_size" "\x00\x00\x00\x00\x00\x00\x02\x00"
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
+{ $QEMU_IMG convert -s foo $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out
index 9029698..ce0e64d 100644
--- a/tests/qemu-iotests/029.out
+++ b/tests/qemu-iotests/029.out
@@ -20,4 +20,8 @@ wrote 4096/4096 bytes at offset 1099511627776
 read 4096/4096 bytes at offset 1099511627776
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 No errors were found on the image.
+
+qcow2_snapshot_load_tmp() should take the L1 size from the snapshot
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 *** done
commit 11b128f4062dd7f89b14abc8877ff20d41b28be9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:04 2014 +0100

    qcow2: Fix NULL dereference in qcow2_open() error path (CVE-2014-0146)
    
    The qcow2 code assumes that s->snapshots is non-NULL if s->nb_snapshots
    != 0. By having the initialisation of both fields separated in
    qcow2_open(), any error occuring in between would cause the error path
    to dereference NULL in qcow2_free_snapshots() if the image had any
    snapshots.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index b64564d..be48a27 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -637,9 +637,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    s->snapshots_offset = header.snapshots_offset;
-    s->nb_snapshots = header.nb_snapshots;
-
     /* read the level 1 table */
     if (header.l1_size > 0x2000000) {
         /* 32 MB L1 table is enough for 2 PB images at 64k cluster size
@@ -734,6 +731,10 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         bs->backing_file[len] = '\0';
     }
 
+    /* Internal snapshots */
+    s->snapshots_offset = header.snapshots_offset;
+    s->nb_snapshots = header.nb_snapshots;
+
     ret = qcow2_read_snapshots(bs);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not read snapshots");
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 56f8903..59e7a44 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -139,6 +139,13 @@ poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
 echo
+echo "== Invalid L1 table (with internal snapshot in the image) =="
+_make_test_img 64M
+{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x00"
+_img_info
+
+echo
 echo "== Invalid backing file size =="
 _make_test_img 64M
 poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x10\x00"
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 303d6c3..4d84fbf 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -59,6 +59,10 @@ no file open, try 'help open'
 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
 no file open, try 'help open'
 
+== Invalid L1 table (with internal snapshot in the image) ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': L1 table is too small
+
 == Invalid backing file size ==
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long
commit 6b7d4c55586a849aa8313282d79432917eade3bf
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:03 2014 +0100

    qcow2: Fix copy_sectors() with VM state
    
    bs->total_sectors is not the highest possible sector number that could
    be involved in a copy on write operation: VM state is after the end of
    the virtual disk. This resulted in wrong values for the number of
    sectors to be copied (n).
    
    The code that checks for the end of the image isn't required any more
    because the code hasn't been calling the block layer's bdrv_read() for a
    long time; instead, it directly calls qcow2_readv(), which doesn't error
    out on VM state sector numbers.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 242e1f8..60a6910 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -359,15 +359,6 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
     struct iovec iov;
     int n, ret;
 
-    /*
-     * If this is the last cluster and it is only partially used, we must only
-     * copy until the end of the image, or bdrv_check_request will fail for the
-     * bdrv_read/write calls below.
-     */
-    if (start_sect + n_end > bs->total_sectors) {
-        n_end = bs->total_sectors - start_sect;
-    }
-
     n = n_end - n_start;
     if (n <= 0) {
         return 0;
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
index b424726..567e071 100755
--- a/tests/qemu-iotests/029
+++ b/tests/qemu-iotests/029
@@ -1,7 +1,6 @@
 #!/bin/bash
 #
-# Test loading internal snapshots where the L1 table of the snapshot
-# is smaller than the current L1 table.
+# qcow2 internal snapshots/VM state tests
 #
 # Copyright (C) 2011 Red Hat, Inc.
 #
@@ -45,6 +44,11 @@ _supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
 
+echo
+echo Test loading internal snapshots where the L1 table of the snapshot
+echo is smaller than the current L1 table.
+echo
+
 CLUSTER_SIZE=65536
 _make_test_img 64M
 $QEMU_IMG snapshot -c foo "$TEST_IMG"
@@ -59,6 +63,20 @@ $QEMU_IO -c 'write -b 0 4M' "$TEST_IMG" | _filter_qemu_io
 $QEMU_IMG snapshot -a foo "$TEST_IMG"
 _check_test_img
 
+
+echo
+echo Try using a huge VM state
+echo
+
+CLUSTER_SIZE=65536
+_make_test_img 64M
+{ $QEMU_IO -c "write -b -P 0x11 1T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IMG snapshot -c foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IMG snapshot -a foo $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IO -c "read -b -P 0x11 1T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+_check_test_img
+
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/029.out b/tests/qemu-iotests/029.out
index 0eedb3a..9029698 100644
--- a/tests/qemu-iotests/029.out
+++ b/tests/qemu-iotests/029.out
@@ -1,4 +1,8 @@
 QA output created by 029
+
+Test loading internal snapshots where the L1 table of the snapshot
+is smaller than the current L1 table.
+
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -7,4 +11,13 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216
 wrote 4194304/4194304 bytes at offset 0
 4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 No errors were found on the image.
+
+Try using a huge VM state
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+wrote 4096/4096 bytes at offset 1099511627776
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 1099511627776
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
 *** done
commit 8f4754ede56e3f9ea3fd7207f4a7c4453e59285b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:06:02 2014 +0100

    block: Limit request size (CVE-2014-0143)
    
    Limiting the size of a single request to INT_MAX not only fixes a
    direct integer overflow in bdrv_check_request() (which would only
    trigger bad behaviour with ridiculously huge images, as in close to
    2^64 bytes), but can also prevent overflows in all block drivers.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index acb70fd..7a90a1b 100644
--- a/block.c
+++ b/block.c
@@ -2588,6 +2588,10 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
 static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
                               int nb_sectors)
 {
+    if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
+        return -EIO;
+    }
+
     return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
                                    nb_sectors * BDRV_SECTOR_SIZE);
 }
commit 1e7226f70c9d944ae7f233b65fb4adda8f910dfe
Author: Jeff Cody <jcody at redhat.com>
Date:   Fri Mar 28 11:42:25 2014 -0400

    block: vdi bounds check qemu-io tests
    
    This test checks for proper bounds checking of some VDI input
    headers.  The following is checked:
    
    1. Max image size (1024TB) with the appropriate Blocks In Image
       value (0x3fffffff) is detected as valid.
    
    2. Image size exceeding max (1024TB) is seen as invalid
    
    3. Valid image size but with Blocks In Image value that is too
       small fails
    
    4. Blocks In Image size exceeding max (0x3fffffff) is seen as invalid
    
    5. 64MB image, with 64 Blocks In Image, and 1MB Block Size is seen
       as valid
    
    6. Block Size < 1MB not supported
    
    7. Block Size > 1MB not supported
    
    [Max Reitz <mreitz at redhat.com> pointed out that "1MB + 1" in the test
    case is wrong.  Change to "1MB + 64KB" to match the 0x110000 value.
    --Stefan]
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/084 b/tests/qemu-iotests/084
new file mode 100755
index 0000000..cb4d7b7
--- /dev/null
+++ b/tests/qemu-iotests/084
@@ -0,0 +1,104 @@
+#!/bin/bash
+#
+# Test case for VDI header corruption; image too large, and too many blocks
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# This tests vdi-specific header fields
+_supported_fmt vdi
+_supported_proto generic
+_supported_os Linux
+
+ds_offset=368  # disk image size field offset
+bs_offset=376  # block size field offset
+bii_offset=384 # block in image field offset
+
+echo
+echo "=== Testing image size bounds ==="
+echo
+_make_test_img 64M
+
+# check for image size too large
+# poke max image size, and appropriate blocks_in_image value
+echo "Test 1: Maximum size (1024 TB):"
+poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\xf0\xff\xff\xff\x03\x00"
+poke_file "$TEST_IMG" "$bii_offset" "\xff\xff\xff\x3f"
+_img_info
+
+echo
+echo "Test 2: Size too large (1024TB + 1)"
+# This should be too large (-EINVAL):
+poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\xf1\xff\xff\xff\x03\x00"
+_img_info
+
+echo
+echo "Test 3: Size valid (64M), but Blocks In Image too small (63)"
+# This sets the size to 64M, but with a blocks_in_image size that is
+# too small
+poke_file "$TEST_IMG" "$ds_offset" "\x00\x00\x00\x04\x00\x00\x00\x00"
+# For a 64M image, we would need a blocks_in_image value of at least 64,
+# so 63 should be too small and give us -ENOTSUP
+poke_file "$TEST_IMG" "$bii_offset" "\x3f\x00\x00\x00"
+_img_info
+
+echo
+echo "Test 4: Size valid (64M), but Blocks In Image exceeds max allowed"
+# Now check the bounds of blocks_in_image - 0x3fffffff should be the max
+# value here, and we should get -ENOTSUP
+poke_file "$TEST_IMG" "$bii_offset" "\x00\x00\x00\x40"
+_img_info
+
+# Finally, 1MB is the only block size supported.  Verify that
+# a value != 1MB results in error, both smaller and larger
+echo
+echo "Test 5: Valid Image: 64MB, Blocks In Image 64, Block Size 1MB"
+poke_file "$TEST_IMG" "$bii_offset" "\x40\x00\x00\x00" # reset bii to valid
+poke_file "$TEST_IMG" "$bs_offset" "\x00\x00\x10\x00"  # valid
+_img_info
+echo
+echo "Test 6: Block Size != 1MB; too small test (1MB - 1)"
+poke_file "$TEST_IMG" "$bs_offset" "\xff\xff\x0f\x00"  # invalid (too small)
+_img_info
+echo
+echo "Test 7: Block Size != 1MB; too large test (1MB + 64KB)"
+poke_file "$TEST_IMG" "$bs_offset" "\x00\x00\x11\x00"  # invalid (too large)
+_img_info
+# success, all done
+echo
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out
new file mode 100644
index 0000000..e681924
--- /dev/null
+++ b/tests/qemu-iotests/084.out
@@ -0,0 +1,33 @@
+QA output created by 084
+
+=== Testing image size bounds ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+Test 1: Maximum size (1024 TB):
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 1024T (1125899905794048 bytes)
+cluster_size: 1048576
+
+Test 2: Size too large (1024TB + 1)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000)
+
+Test 3: Size valid (64M), but Blocks In Image too small (63)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (disk size 67108864, image bitmap has room for 66060288)
+
+Test 4: Size valid (64M), but Blocks In Image exceeds max allowed
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (too many blocks 1073741824, max is 1073741823)
+
+Test 5: Valid Image: 64MB, Blocks In Image 64, Block Size 1MB
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+cluster_size: 1048576
+
+Test 6: Block Size != 1MB; too small test (1MB - 1)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (block size 1048575 is not 1048576)
+
+Test 7: Block Size != 1MB; too large test (1MB + 64KB)
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': unsupported VDI image (block size 1114112 is not 1048576)
+
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ed44f35..c51640c 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -89,6 +89,7 @@
 081 rw auto
 082 rw auto quick
 083 rw auto
+084 img auto
 085 rw auto
 086 rw auto quick
 087 rw auto
commit f0dce23475b5af5da6b17b97c1765271307734b6
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:06:00 2014 +0100

    dmg: prevent chunk buffer overflow (CVE-2014-0145)
    
    Both compressed and uncompressed I/O is buffered.  dmg_open() calculates
    the maximum buffer size needed from the metadata in the image file.
    
    There is currently a buffer overflow since ->lengths[] is accounted
    against the maximum compressed buffer size but actually uses the
    uncompressed buffer:
    
      switch (s->types[chunk]) {
      case 1: /* copy */
          ret = bdrv_pread(bs->file, s->offsets[chunk],
                           s->uncompressed_chunk, s->lengths[chunk]);
    
    We must account against the maximum uncompressed buffer size for type=1
    chunks.
    
    This patch fixes the maximum buffer size calculation to take into
    account the chunk type.  It is critical that we update the correct
    maximum since there are two buffers ->compressed_chunk and
    ->uncompressed_chunk.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index be0ee33..856402e 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -100,6 +100,37 @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
     return 0;
 }
 
+/* Increase max chunk sizes, if necessary.  This function is used to calculate
+ * the buffer sizes needed for compressed/uncompressed chunk I/O.
+ */
+static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
+                                  uint32_t *max_compressed_size,
+                                  uint32_t *max_sectors_per_chunk)
+{
+    uint32_t compressed_size = 0;
+    uint32_t uncompressed_sectors = 0;
+
+    switch (s->types[chunk]) {
+    case 0x80000005: /* zlib compressed */
+        compressed_size = s->lengths[chunk];
+        uncompressed_sectors = s->sectorcounts[chunk];
+        break;
+    case 1: /* copy */
+        uncompressed_sectors = (s->lengths[chunk] + 511) / 512;
+        break;
+    case 2: /* zero */
+        uncompressed_sectors = s->sectorcounts[chunk];
+        break;
+    }
+
+    if (compressed_size > *max_compressed_size) {
+        *max_compressed_size = compressed_size;
+    }
+    if (uncompressed_sectors > *max_sectors_per_chunk) {
+        *max_sectors_per_chunk = uncompressed_sectors;
+    }
+}
+
 static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                     Error **errp)
 {
@@ -245,12 +276,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                     goto fail;
                 }
 
-                if (s->lengths[i] > max_compressed_size) {
-                    max_compressed_size = s->lengths[i];
-                }
-                if (s->sectorcounts[i] > max_sectors_per_chunk) {
-                    max_sectors_per_chunk = s->sectorcounts[i];
-                }
+                update_max_chunk_size(s, i, &max_compressed_size,
+                                      &max_sectors_per_chunk);
             }
             s->n_chunks += chunk_count;
         }
commit 686d7148ec23402a172628c800022b3a95a022c9
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:59 2014 +0100

    dmg: use uint64_t consistently for sectors and lengths
    
    The DMG metadata is stored as uint64_t, so use the same type for
    sector_num.  int was a particularly poor choice since it is only 32-bit
    and would truncate large values.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index ad253fe..be0ee33 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -281,7 +281,7 @@ fail:
 }
 
 static inline int is_sector_in_chunk(BDRVDMGState* s,
-                uint32_t chunk_num, int sector_num)
+                uint32_t chunk_num, uint64_t sector_num)
 {
     if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num ||
             s->sectors[chunk_num] + s->sectorcounts[chunk_num] <= sector_num) {
@@ -291,7 +291,7 @@ static inline int is_sector_in_chunk(BDRVDMGState* s,
     }
 }
 
-static inline uint32_t search_chunk(BDRVDMGState *s, int sector_num)
+static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
 {
     /* binary search */
     uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
@@ -308,7 +308,7 @@ static inline uint32_t search_chunk(BDRVDMGState *s, int sector_num)
     return s->n_chunks; /* error */
 }
 
-static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num)
+static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
 {
     BDRVDMGState *s = bs->opaque;
 
commit c165f7758009a4f793c1fc19ebb69cf55313450b
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:58 2014 +0100

    dmg: sanitize chunk length and sectorcount (CVE-2014-0145)
    
    Chunk length and sectorcount are used for decompression buffers as well
    as the bdrv_pread() count argument.  Ensure that they have reasonable
    values so neither memory allocation nor conversion from uint64_t to int
    will cause problems.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index f98c94d..ad253fe 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -27,6 +27,14 @@
 #include "qemu/module.h"
 #include <zlib.h>
 
+enum {
+    /* Limit chunk sizes to prevent unreasonable amounts of memory being used
+     * or truncating when converting to 32-bit types
+     */
+    DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */
+    DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
+};
+
 typedef struct BDRVDMGState {
     CoMutex lock;
     /* each chunk contains a certain number of sectors,
@@ -208,6 +216,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                 }
                 offset += 8;
 
+                if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
+                    error_report("sector count %" PRIu64 " for chunk %u is "
+                                 "larger than max (%u)",
+                                 s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
+                    ret = -EINVAL;
+                    goto fail;
+                }
+
                 ret = read_uint64(bs, offset, &s->offsets[i]);
                 if (ret < 0) {
                     goto fail;
@@ -221,6 +237,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                 }
                 offset += 8;
 
+                if (s->lengths[i] > DMG_LENGTHS_MAX) {
+                    error_report("length %" PRIu64 " for chunk %u is larger "
+                                 "than max (%u)",
+                                 s->lengths[i], i, DMG_LENGTHS_MAX);
+                    ret = -EINVAL;
+                    goto fail;
+                }
+
                 if (s->lengths[i] > max_compressed_size) {
                     max_compressed_size = s->lengths[i];
                 }
commit eb71803b041f55779ea10d860c0f66df285c68de
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:57 2014 +0100

    dmg: use appropriate types when reading chunks
    
    Use the right types instead of signed int:
    
      size_t new_size;
    
      This is a byte count for g_realloc() that is calculated from uint32_t
      and size_t values.
    
      uint32_t chunk_count;
    
      Use the same type as s->n_chunks, which is used together with
      chunk_count.
    
    This patch is a cleanup and does not fix bugs.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index 1cc5426..f98c94d 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -161,7 +161,8 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
         }
 
         if (type == 0x6d697368 && count >= 244) {
-            int new_size, chunk_count;
+            size_t new_size;
+            uint32_t chunk_count;
 
             offset += 4;
             offset += 200;
commit b404bf854217dbe8a5649449eb3ad33777f7d900
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:56 2014 +0100

    dmg: drop broken bdrv_pread() loop
    
    It is not necessary to check errno for EINTR and the block layer does
    not produce short reads.  Therefore we can drop the loop that attempts
    to read a compressed chunk.
    
    The loop is buggy because it incorrectly adds the transferred bytes
    twice:
    
      do {
          ret = bdrv_pread(...);
          i += ret;
      } while (ret >= 0 && ret + i < s->lengths[chunk]);
    
    Luckily we can drop the loop completely and perform a single
    bdrv_pread().
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index f4f3e8e..1cc5426 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -298,21 +298,10 @@ static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num)
         s->current_chunk = s->n_chunks;
         switch (s->types[chunk]) {
         case 0x80000005: { /* zlib compressed */
-            int i;
-
             /* we need to buffer, because only the chunk as whole can be
              * inflated. */
-            i = 0;
-            do {
-                ret = bdrv_pread(bs->file, s->offsets[chunk] + i,
-                                 s->compressed_chunk + i,
-                                 s->lengths[chunk] - i);
-                if (ret < 0 && errno == EINTR) {
-                    ret = 0;
-                }
-                i += ret;
-            } while (ret >= 0 && ret + i < s->lengths[chunk]);
-
+            ret = bdrv_pread(bs->file, s->offsets[chunk],
+                             s->compressed_chunk, s->lengths[chunk]);
             if (ret != s->lengths[chunk]) {
                 return -1;
             }
commit 73ed27ec28a1dbebdd2ae792284151f029950fbe
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:55 2014 +0100

    dmg: prevent out-of-bounds array access on terminator
    
    When a terminator is reached the base for offsets and sectors is stored.
    The following records that are processed will use this base value.
    
    If the first record we encounter is a terminator, then calculating the
    base values would result in out-of-bounds array accesses.  Don't do
    that.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index be2f26e..f4f3e8e 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -182,7 +182,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                 offset += 4;
                 if (s->types[i] != 0x80000005 && s->types[i] != 1 &&
                     s->types[i] != 2) {
-                    if (s->types[i] == 0xffffffff) {
+                    if (s->types[i] == 0xffffffff && i > 0) {
                         last_in_offset = s->offsets[i - 1] + s->lengths[i - 1];
                         last_out_offset = s->sectors[i - 1] +
                                           s->sectorcounts[i - 1];
commit 2c1885adcf0312da80c7317b09f9adad97fa0fc6
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:54 2014 +0100

    dmg: coding style and indentation cleanup
    
    Clean up the mix of tabs and spaces, as well as the coding style
    violations in block/dmg.c.  There are no semantic changes since this
    patch simply reformats the code.
    
    This patch is necessary before we can make meaningful changes to this
    file, due to the inconsistent formatting and confusing indentation.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index d5e9b1f..be2f26e 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -96,9 +96,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                     Error **errp)
 {
     BDRVDMGState *s = bs->opaque;
-    uint64_t info_begin,info_end,last_in_offset,last_out_offset;
+    uint64_t info_begin, info_end, last_in_offset, last_out_offset;
     uint32_t count, tmp;
-    uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
+    uint32_t max_compressed_size = 1, max_sectors_per_chunk = 1, i;
     int64_t offset;
     int ret;
 
@@ -160,37 +160,39 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
             goto fail;
         }
 
-	if (type == 0x6d697368 && count >= 244) {
-	    int new_size, chunk_count;
+        if (type == 0x6d697368 && count >= 244) {
+            int new_size, chunk_count;
 
             offset += 4;
             offset += 200;
 
-	    chunk_count = (count-204)/40;
-	    new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
-	    s->types = g_realloc(s->types, new_size/2);
-	    s->offsets = g_realloc(s->offsets, new_size);
-	    s->lengths = g_realloc(s->lengths, new_size);
-	    s->sectors = g_realloc(s->sectors, new_size);
-	    s->sectorcounts = g_realloc(s->sectorcounts, new_size);
+            chunk_count = (count - 204) / 40;
+            new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
+            s->types = g_realloc(s->types, new_size / 2);
+            s->offsets = g_realloc(s->offsets, new_size);
+            s->lengths = g_realloc(s->lengths, new_size);
+            s->sectors = g_realloc(s->sectors, new_size);
+            s->sectorcounts = g_realloc(s->sectorcounts, new_size);
 
             for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) {
                 ret = read_uint32(bs, offset, &s->types[i]);
                 if (ret < 0) {
                     goto fail;
                 }
-		offset += 4;
-		if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
-		    if(s->types[i]==0xffffffff) {
-			last_in_offset = s->offsets[i-1]+s->lengths[i-1];
-			last_out_offset = s->sectors[i-1]+s->sectorcounts[i-1];
-		    }
-		    chunk_count--;
-		    i--;
-		    offset += 36;
-		    continue;
-		}
-		offset += 4;
+                offset += 4;
+                if (s->types[i] != 0x80000005 && s->types[i] != 1 &&
+                    s->types[i] != 2) {
+                    if (s->types[i] == 0xffffffff) {
+                        last_in_offset = s->offsets[i - 1] + s->lengths[i - 1];
+                        last_out_offset = s->sectors[i - 1] +
+                                          s->sectorcounts[i - 1];
+                    }
+                    chunk_count--;
+                    i--;
+                    offset += 36;
+                    continue;
+                }
+                offset += 4;
 
                 ret = read_uint64(bs, offset, &s->sectors[i]);
                 if (ret < 0) {
@@ -218,19 +220,21 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
                 }
                 offset += 8;
 
-		if(s->lengths[i]>max_compressed_size)
-		    max_compressed_size = s->lengths[i];
-		if(s->sectorcounts[i]>max_sectors_per_chunk)
-		    max_sectors_per_chunk = s->sectorcounts[i];
-	    }
-	    s->n_chunks+=chunk_count;
-	}
+                if (s->lengths[i] > max_compressed_size) {
+                    max_compressed_size = s->lengths[i];
+                }
+                if (s->sectorcounts[i] > max_sectors_per_chunk) {
+                    max_sectors_per_chunk = s->sectorcounts[i];
+                }
+            }
+            s->n_chunks += chunk_count;
+        }
     }
 
     /* initialize zlib engine */
-    s->compressed_chunk = g_malloc(max_compressed_size+1);
-    s->uncompressed_chunk = g_malloc(512*max_sectors_per_chunk);
-    if(inflateInit(&s->zstream) != Z_OK) {
+    s->compressed_chunk = g_malloc(max_compressed_size + 1);
+    s->uncompressed_chunk = g_malloc(512 * max_sectors_per_chunk);
+    if (inflateInit(&s->zstream) != Z_OK) {
         ret = -EINVAL;
         goto fail;
     }
@@ -252,27 +256,29 @@ fail:
 }
 
 static inline int is_sector_in_chunk(BDRVDMGState* s,
-		uint32_t chunk_num,int sector_num)
+                uint32_t chunk_num, int sector_num)
 {
-    if(chunk_num>=s->n_chunks || s->sectors[chunk_num]>sector_num ||
-	    s->sectors[chunk_num]+s->sectorcounts[chunk_num]<=sector_num)
-	return 0;
-    else
-	return -1;
+    if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num ||
+            s->sectors[chunk_num] + s->sectorcounts[chunk_num] <= sector_num) {
+        return 0;
+    } else {
+        return -1;
+    }
 }
 
-static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
+static inline uint32_t search_chunk(BDRVDMGState *s, int sector_num)
 {
     /* binary search */
-    uint32_t chunk1=0,chunk2=s->n_chunks,chunk3;
-    while(chunk1!=chunk2) {
-	chunk3 = (chunk1+chunk2)/2;
-	if(s->sectors[chunk3]>sector_num)
-	    chunk2 = chunk3;
-	else if(s->sectors[chunk3]+s->sectorcounts[chunk3]>sector_num)
-	    return chunk3;
-	else
-	    chunk1 = chunk3;
+    uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
+    while (chunk1 != chunk2) {
+        chunk3 = (chunk1 + chunk2) / 2;
+        if (s->sectors[chunk3] > sector_num) {
+            chunk2 = chunk3;
+        } else if (s->sectors[chunk3] + s->sectorcounts[chunk3] > sector_num) {
+            return chunk3;
+        } else {
+            chunk1 = chunk3;
+        }
     }
     return s->n_chunks; /* error */
 }
@@ -281,54 +287,62 @@ static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num)
 {
     BDRVDMGState *s = bs->opaque;
 
-    if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
-	int ret;
-	uint32_t chunk = search_chunk(s,sector_num);
+    if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) {
+        int ret;
+        uint32_t chunk = search_chunk(s, sector_num);
 
-	if(chunk>=s->n_chunks)
-	    return -1;
+        if (chunk >= s->n_chunks) {
+            return -1;
+        }
 
-	s->current_chunk = s->n_chunks;
-	switch(s->types[chunk]) {
-	case 0x80000005: { /* zlib compressed */
-	    int i;
+        s->current_chunk = s->n_chunks;
+        switch (s->types[chunk]) {
+        case 0x80000005: { /* zlib compressed */
+            int i;
 
-	    /* we need to buffer, because only the chunk as whole can be
-	     * inflated. */
-	    i=0;
-	    do {
+            /* we need to buffer, because only the chunk as whole can be
+             * inflated. */
+            i = 0;
+            do {
                 ret = bdrv_pread(bs->file, s->offsets[chunk] + i,
-                                 s->compressed_chunk+i, s->lengths[chunk]-i);
-		if(ret<0 && errno==EINTR)
-		    ret=0;
-		i+=ret;
-	    } while(ret>=0 && ret+i<s->lengths[chunk]);
-
-	    if (ret != s->lengths[chunk])
-		return -1;
-
-	    s->zstream.next_in = s->compressed_chunk;
-	    s->zstream.avail_in = s->lengths[chunk];
-	    s->zstream.next_out = s->uncompressed_chunk;
-	    s->zstream.avail_out = 512*s->sectorcounts[chunk];
-	    ret = inflateReset(&s->zstream);
-	    if(ret != Z_OK)
-		return -1;
-	    ret = inflate(&s->zstream, Z_FINISH);
-	    if(ret != Z_STREAM_END || s->zstream.total_out != 512*s->sectorcounts[chunk])
-		return -1;
-	    break; }
-	case 1: /* copy */
-	    ret = bdrv_pread(bs->file, s->offsets[chunk],
+                                 s->compressed_chunk + i,
+                                 s->lengths[chunk] - i);
+                if (ret < 0 && errno == EINTR) {
+                    ret = 0;
+                }
+                i += ret;
+            } while (ret >= 0 && ret + i < s->lengths[chunk]);
+
+            if (ret != s->lengths[chunk]) {
+                return -1;
+            }
+
+            s->zstream.next_in = s->compressed_chunk;
+            s->zstream.avail_in = s->lengths[chunk];
+            s->zstream.next_out = s->uncompressed_chunk;
+            s->zstream.avail_out = 512 * s->sectorcounts[chunk];
+            ret = inflateReset(&s->zstream);
+            if (ret != Z_OK) {
+                return -1;
+            }
+            ret = inflate(&s->zstream, Z_FINISH);
+            if (ret != Z_STREAM_END ||
+                s->zstream.total_out != 512 * s->sectorcounts[chunk]) {
+                return -1;
+            }
+            break; }
+        case 1: /* copy */
+            ret = bdrv_pread(bs->file, s->offsets[chunk],
                              s->uncompressed_chunk, s->lengths[chunk]);
-	    if (ret != s->lengths[chunk])
-		return -1;
-	    break;
-	case 2: /* zero */
-	    memset(s->uncompressed_chunk, 0, 512*s->sectorcounts[chunk]);
-	    break;
-	}
-	s->current_chunk = chunk;
+            if (ret != s->lengths[chunk]) {
+                return -1;
+            }
+            break;
+        case 2: /* zero */
+            memset(s->uncompressed_chunk, 0, 512 * s->sectorcounts[chunk]);
+            break;
+        }
+        s->current_chunk = chunk;
     }
     return 0;
 }
@@ -339,12 +353,14 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num,
     BDRVDMGState *s = bs->opaque;
     int i;
 
-    for(i=0;i<nb_sectors;i++) {
-	uint32_t sector_offset_in_chunk;
-	if(dmg_read_chunk(bs, sector_num+i) != 0)
-	    return -1;
-	sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk];
-	memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512);
+    for (i = 0; i < nb_sectors; i++) {
+        uint32_t sector_offset_in_chunk;
+        if (dmg_read_chunk(bs, sector_num + i) != 0) {
+            return -1;
+        }
+        sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk];
+        memcpy(buf + i * 512,
+               s->uncompressed_chunk + sector_offset_in_chunk * 512, 512);
     }
     return 0;
 }
@@ -376,12 +392,12 @@ static void dmg_close(BlockDriverState *bs)
 }
 
 static BlockDriver bdrv_dmg = {
-    .format_name	= "dmg",
-    .instance_size	= sizeof(BDRVDMGState),
-    .bdrv_probe		= dmg_probe,
-    .bdrv_open		= dmg_open,
-    .bdrv_read          = dmg_co_read,
-    .bdrv_close		= dmg_close,
+    .format_name    = "dmg",
+    .instance_size  = sizeof(BDRVDMGState),
+    .bdrv_probe     = dmg_probe,
+    .bdrv_open      = dmg_open,
+    .bdrv_read      = dmg_co_read,
+    .bdrv_close     = dmg_close,
 };
 
 static void bdrv_dmg_init(void)
commit cab60de930684c33f67d4e32c7509b567f8c445b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:53 2014 +0100

    qcow2: Fix new L1 table size check (CVE-2014-0143)
    
    The size in bytes is assigned to an int later, so check that instead of
    the number of entries.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9499df9..242e1f8 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -55,7 +55,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
         }
     }
 
-    if (new_l1_size > INT_MAX) {
+    if (new_l1_size > INT_MAX / sizeof(uint64_t)) {
         return -EFBIG;
     }
 
commit 0abe740f1de899737242bcba1fb4a9857f7a3087
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:52 2014 +0100

    qcow2: Protect against some integer overflows in bdrv_check
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 9130042..a37ee45 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1020,8 +1020,7 @@ static void inc_refcounts(BlockDriverState *bs,
                           int64_t offset, int64_t size)
 {
     BDRVQcowState *s = bs->opaque;
-    int64_t start, last, cluster_offset;
-    int k;
+    uint64_t start, last, cluster_offset, k;
 
     if (size <= 0)
         return;
@@ -1031,11 +1030,7 @@ static void inc_refcounts(BlockDriverState *bs,
     for(cluster_offset = start; cluster_offset <= last;
         cluster_offset += s->cluster_size) {
         k = cluster_offset >> s->cluster_bits;
-        if (k < 0) {
-            fprintf(stderr, "ERROR: invalid cluster offset=0x%" PRIx64 "\n",
-                cluster_offset);
-            res->corruptions++;
-        } else if (k >= refcount_table_size) {
+        if (k >= refcount_table_size) {
             fprintf(stderr, "Warning: cluster offset=0x%" PRIx64 " is after "
                 "the end of the image file, can't properly check refcounts.\n",
                 cluster_offset);
@@ -1478,14 +1473,19 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
                           BdrvCheckMode fix)
 {
     BDRVQcowState *s = bs->opaque;
-    int64_t size, i, highest_cluster;
-    int nb_clusters, refcount1, refcount2;
+    int64_t size, i, highest_cluster, nb_clusters;
+    int refcount1, refcount2;
     QCowSnapshot *sn;
     uint16_t *refcount_table;
     int ret;
 
     size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
+    if (nb_clusters > INT_MAX) {
+        res->check_errors++;
+        return -EFBIG;
+    }
+
     refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t));
 
     res->bfi.total_clusters =
commit bb572aefbdac290363bfa5ca0e810ccce0a14ed6
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:51 2014 +0100

    qcow2: Fix types in qcow2_alloc_clusters and alloc_clusters_noref
    
    In order to avoid integer overflows.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 1c78ff8..9130042 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -28,7 +28,7 @@
 #include "qemu/range.h"
 #include "qapi/qmp/types.h"
 
-static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size);
+static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size);
 static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
                             int64_t offset, int64_t length,
                             int addend, enum qcow2_discard_type type);
@@ -635,15 +635,16 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
 
 
 /* return < 0 if error */
-static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
+static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size)
 {
     BDRVQcowState *s = bs->opaque;
-    int i, nb_clusters, refcount;
+    uint64_t i, nb_clusters;
+    int refcount;
 
     nb_clusters = size_to_clusters(s, size);
 retry:
     for(i = 0; i < nb_clusters; i++) {
-        int64_t next_cluster_index = s->free_cluster_index++;
+        uint64_t next_cluster_index = s->free_cluster_index++;
         refcount = get_refcount(bs, next_cluster_index);
 
         if (refcount < 0) {
@@ -660,7 +661,7 @@ retry:
     return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
 }
 
-int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
+int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
 {
     int64_t offset;
     int ret;
diff --git a/block/qcow2.h b/block/qcow2.h
index 4015373..3649465 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -222,8 +222,8 @@ typedef struct BDRVQcowState {
     uint64_t *refcount_table;
     uint64_t refcount_table_offset;
     uint32_t refcount_table_size;
-    int64_t free_cluster_index;
-    int64_t free_byte_offset;
+    uint64_t free_cluster_index;
+    uint64_t free_byte_offset;
 
     CoMutex lock;
 
@@ -467,7 +467,7 @@ void qcow2_refcount_close(BlockDriverState *bs);
 int qcow2_update_cluster_refcount(BlockDriverState *bs, int64_t cluster_index,
                                   int addend, enum qcow2_discard_type type);
 
-int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size);
+int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size);
 int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
     int nb_clusters);
 int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size);
commit 2b5d5953eec0cc541857c3df812bdf8421596ab2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:50 2014 +0100

    qcow2: Check new refcount table size on growth
    
    If the size becomes larger than what qcow2_open() would accept, fail the
    growing operation.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 561d659..1c78ff8 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -311,6 +311,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
     uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
     uint64_t blocks_used = DIV_ROUND_UP(cluster_index, refcount_block_clusters);
 
+    if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {
+        return -EFBIG;
+    }
+
     /* And now we need at least one block more for the new metadata */
     uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);
     uint64_t last_table_size;
diff --git a/block/qcow2.c b/block/qcow2.c
index d4d991c..b64564d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -609,9 +609,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     s->refcount_table_size =
         header.refcount_table_clusters << (s->cluster_bits - 3);
 
-    if (header.refcount_table_clusters > (0x800000 >> s->cluster_bits)) {
-        /* 8 MB refcount table is enough for 2 PB images at 64k cluster size
-         * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
+    if (header.refcount_table_clusters > qcow2_max_refcount_clusters(s)) {
         error_setg(errp, "Reference count table too large");
         ret = -EINVAL;
         goto fail;
diff --git a/block/qcow2.h b/block/qcow2.h
index b153505..4015373 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -40,6 +40,10 @@
 #define QCOW_MAX_CRYPT_CLUSTERS 32
 #define QCOW_MAX_SNAPSHOTS 65536
 
+/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
+ * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
+#define QCOW_MAX_REFTABLE_SIZE 0x800000
+
 /* indicate that the refcount of the referenced cluster is exactly one. */
 #define QCOW_OFLAG_COPIED     (1ULL << 63)
 /* indicate that the cluster is compressed (they never have the copied flag) */
@@ -410,6 +414,11 @@ static inline int64_t qcow2_vm_state_offset(BDRVQcowState *s)
     return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
 }
 
+static inline uint64_t qcow2_max_refcount_clusters(BDRVQcowState *s)
+{
+    return QCOW_MAX_REFTABLE_SIZE >> s->cluster_bits;
+}
+
 static inline int qcow2_get_cluster_type(uint64_t l2_entry)
 {
     if (l2_entry & QCOW_OFLAG_COMPRESSED) {
commit db8a31d11d6a60f48d6817530640d75aa72a9a2f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:49 2014 +0100

    qcow2: Avoid integer overflow in get_refcount (CVE-2014-0143)
    
    This ensures that the checks catch all invalid cluster indexes
    instead of returning the refcount of a wrong cluster.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 220b322..561d659 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -89,7 +89,7 @@ static int load_refcount_block(BlockDriverState *bs,
 static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
 {
     BDRVQcowState *s = bs->opaque;
-    int refcount_table_index, block_index;
+    uint64_t refcount_table_index, block_index;
     int64_t refcount_block_offset;
     int ret;
     uint16_t *refcount_block;
commit b106ad9185f35fc4ad669555ad0e79e276083bd7
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 28 18:06:31 2014 +0100

    qcow2: Don't rely on free_cluster_index in alloc_refcount_block() (CVE-2014-0147)
    
    free_cluster_index is only correct if update_refcount() was called from
    an allocation function, and even there it's brittle because it's used to
    protect unfinished allocations which still have a refcount of 0 - if it
    moves in the wrong place, the unfinished allocation can be corrupted.
    
    So not using it any more seems to be a good idea. Instead, use the
    first requested cluster to do the calculations. Return -EAGAIN if
    unfinished allocations could become invalid and let the caller restart
    its search for some free clusters.
    
    The context of creating a snapsnot is one situation where
    update_refcount() is called outside of a cluster allocation. For this
    case, the change fixes a buffer overflow if a cluster is referenced in
    an L2 table that cannot be represented by an existing refcount block.
    (new_table[refcount_table_index] was out of bounds)
    
    [Bump the qemu-iotests 026 refblock_alloc.write leak count from 10 to
    11.
    --Stefan]
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index e3c7ecd..220b322 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -194,10 +194,11 @@ static int alloc_refcount_block(BlockDriverState *bs,
      *   they can describe them themselves.
      *
      * - We need to consider that at this point we are inside update_refcounts
-     *   and doing the initial refcount increase. This means that some clusters
-     *   have already been allocated by the caller, but their refcount isn't
-     *   accurate yet. free_cluster_index tells us where this allocation ends
-     *   as long as we don't overwrite it by freeing clusters.
+     *   and potentially doing an initial refcount increase. This means that
+     *   some clusters have already been allocated by the caller, but their
+     *   refcount isn't accurate yet. If we allocate clusters for metadata, we
+     *   need to return -EAGAIN to signal the caller that it needs to restart
+     *   the search for free clusters.
      *
      * - alloc_clusters_noref and qcow2_free_clusters may load a different
      *   refcount block into the cache
@@ -282,7 +283,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
         }
 
         s->refcount_table[refcount_table_index] = new_block;
-        return 0;
+
+        /* The new refcount block may be where the caller intended to put its
+         * data, so let it restart the search. */
+        return -EAGAIN;
     }
 
     ret = qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block);
@@ -305,8 +309,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
 
     /* Calculate the number of refcount blocks needed so far */
     uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
-    uint64_t blocks_used = (s->free_cluster_index +
-        refcount_block_clusters - 1) / refcount_block_clusters;
+    uint64_t blocks_used = DIV_ROUND_UP(cluster_index, refcount_block_clusters);
 
     /* And now we need at least one block more for the new metadata */
     uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);
@@ -339,8 +342,6 @@ static int alloc_refcount_block(BlockDriverState *bs,
     uint16_t *new_blocks = g_malloc0(blocks_clusters * s->cluster_size);
     uint64_t *new_table = g_malloc0(table_size * sizeof(uint64_t));
 
-    assert(meta_offset >= (s->free_cluster_index * s->cluster_size));
-
     /* Fill the new refcount table */
     memcpy(new_table, s->refcount_table,
         s->refcount_table_size * sizeof(uint64_t));
@@ -403,18 +404,19 @@ static int alloc_refcount_block(BlockDriverState *bs,
     s->refcount_table_size = table_size;
     s->refcount_table_offset = table_offset;
 
-    /* Free old table. Remember, we must not change free_cluster_index */
-    uint64_t old_free_cluster_index = s->free_cluster_index;
+    /* Free old table. */
     qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t),
                         QCOW2_DISCARD_OTHER);
-    s->free_cluster_index = old_free_cluster_index;
 
     ret = load_refcount_block(bs, new_block, (void**) refcount_block);
     if (ret < 0) {
         return ret;
     }
 
-    return 0;
+    /* If we were trying to do the initial refcount update for some cluster
+     * allocation, we might have used the same clusters to store newly
+     * allocated metadata. Make the caller search some new space. */
+    return -EAGAIN;
 
 fail_table:
     g_free(new_table);
@@ -660,12 +662,15 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
     int ret;
 
     BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
-    offset = alloc_clusters_noref(bs, size);
-    if (offset < 0) {
-        return offset;
-    }
+    do {
+        offset = alloc_clusters_noref(bs, size);
+        if (offset < 0) {
+            return offset;
+        }
+
+        ret = update_refcount(bs, offset, size, 1, QCOW2_DISCARD_NEVER);
+    } while (ret == -EAGAIN);
 
-    ret = update_refcount(bs, offset, size, 1, QCOW2_DISCARD_NEVER);
     if (ret < 0) {
         return ret;
     }
@@ -678,7 +683,6 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
 {
     BDRVQcowState *s = bs->opaque;
     uint64_t cluster_index;
-    uint64_t old_free_cluster_index;
     uint64_t i;
     int refcount, ret;
 
@@ -687,30 +691,28 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset,
         return 0;
     }
 
-    /* Check how many clusters there are free */
-    cluster_index = offset >> s->cluster_bits;
-    for(i = 0; i < nb_clusters; i++) {
-        refcount = get_refcount(bs, cluster_index++);
+    do {
+        /* Check how many clusters there are free */
+        cluster_index = offset >> s->cluster_bits;
+        for(i = 0; i < nb_clusters; i++) {
+            refcount = get_refcount(bs, cluster_index++);
 
-        if (refcount < 0) {
-            return refcount;
-        } else if (refcount != 0) {
-            break;
+            if (refcount < 0) {
+                return refcount;
+            } else if (refcount != 0) {
+                break;
+            }
         }
-    }
 
-    /* And then allocate them */
-    old_free_cluster_index = s->free_cluster_index;
-    s->free_cluster_index = cluster_index + i;
+        /* And then allocate them */
+        ret = update_refcount(bs, offset, i << s->cluster_bits, 1,
+                              QCOW2_DISCARD_NEVER);
+    } while (ret == -EAGAIN);
 
-    ret = update_refcount(bs, offset, i << s->cluster_bits, 1,
-                          QCOW2_DISCARD_NEVER);
     if (ret < 0) {
         return ret;
     }
 
-    s->free_cluster_index = old_free_cluster_index;
-
     return i;
 }
 
diff --git a/block/qcow2.c b/block/qcow2.c
index cc1bfeb..d4d991c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1602,7 +1602,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
      */
     BlockDriverState* bs;
     QCowHeader *header;
-    uint8_t* refcount_table;
+    uint64_t* refcount_table;
     Error *local_err = NULL;
     int ret;
 
@@ -1654,9 +1654,10 @@ static int qcow2_create2(const char *filename, int64_t total_size,
         goto out;
     }
 
-    /* Write an empty refcount table */
-    refcount_table = g_malloc0(cluster_size);
-    ret = bdrv_pwrite(bs, cluster_size, refcount_table, cluster_size);
+    /* Write a refcount table with one refcount block */
+    refcount_table = g_malloc0(2 * cluster_size);
+    refcount_table[0] = cpu_to_be64(2 * cluster_size);
+    ret = bdrv_pwrite(bs, cluster_size, refcount_table, 2 * cluster_size);
     g_free(refcount_table);
 
     if (ret < 0) {
@@ -1681,7 +1682,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
         goto out;
     }
 
-    ret = qcow2_alloc_clusters(bs, 2 * cluster_size);
+    ret = qcow2_alloc_clusters(bs, 3 * cluster_size);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not allocate clusters for qcow2 "
                          "header and refcount table");
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
index 1504579..f7c78e7 100644
--- a/tests/qemu-iotests/026.out
+++ b/tests/qemu-iotests/026.out
@@ -475,7 +475,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write 
 write failed: No space left on device
 
-10 leaked clusters were found on the image.
+11 leaked clusters were found on the image.
 This means waste of disk space, but no harm to data.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
@@ -499,7 +499,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write 
 write failed: No space left on device
 
-10 leaked clusters were found on the image.
+11 leaked clusters were found on the image.
 This means waste of disk space, but no harm to data.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
@@ -523,7 +523,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write 
 write failed: No space left on device
 
-10 leaked clusters were found on the image.
+11 leaked clusters were found on the image.
 This means waste of disk space, but no harm to data.
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
index 5c5aa92..4789a53 100644
--- a/tests/qemu-iotests/044.out
+++ b/tests/qemu-iotests/044.out
@@ -1,6 +1,6 @@
 No errors were found on the image.
 7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters
-Image end offset: 4296448000
+Image end offset: 4296152064
 .
 ----------------------------------------------------------------------
 Ran 1 tests
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index f3091a9..56f8903 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -56,6 +56,8 @@ offset_header_size=100
 offset_ext_magic=$header_size
 offset_ext_size=$((header_size + 4))
 
+offset_l2_table_0=$((0x40000))
+
 echo
 echo "== Huge header size =="
 _make_test_img 64M
@@ -143,6 +145,15 @@ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x1
 poke_file "$TEST_IMG" "$offset_backing_file_size" "\xff\xff\xff\xff"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Invalid L2 entry (huge physical offset) =="
+_make_test_img 64M
+{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_l2_table_0" "\xbf\xff\xff\xff\xff\xff\x00\x00"
+{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_l2_table_0" "\x80\x00\x00\xff\xff\xff\x00\x00"
+{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 8103211..303d6c3 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -63,4 +63,11 @@ no file open, try 'help open'
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long
 no file open, try 'help open'
+
+== Invalid L2 entry (huge physical offset) ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Could not create snapshot 'test': -27 (File too large)
+qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unavailable)
 *** done
commit 6d33e8e7dc9d40ea105feed4b39caa3e641569e8
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:47 2014 +0100

    qcow2: Fix backing file name length check
    
    len could become negative and would pass the check then. Nothing bad
    happened because bdrv_pread() happens to return an error for negative
    length values, but make variables for sizes unsigned anyway.
    
    This patch also changes the behaviour to error out on invalid lengths
    instead of silently truncating it to 1023.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 3639528..cc1bfeb 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -445,7 +445,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
                       Error **errp)
 {
     BDRVQcowState *s = bs->opaque;
-    int len, i, ret = 0;
+    unsigned int len, i;
+    int ret = 0;
     QCowHeader header;
     QemuOpts *opts;
     Error *local_err = NULL;
@@ -721,8 +722,10 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     /* read the backing file name */
     if (header.backing_file_offset != 0) {
         len = header.backing_file_size;
-        if (len > 1023) {
-            len = 1023;
+        if (len > MIN(1023, s->cluster_size - header.backing_file_offset)) {
+            error_setg(errp, "Backing file name too long");
+            ret = -EINVAL;
+            goto fail;
         }
         ret = bdrv_pread(bs->file, header.backing_file_offset,
                          bs->backing_file, len);
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 7255b6c..f3091a9 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -45,6 +45,7 @@ _supported_os Linux
 header_size=104
 
 offset_backing_file_offset=8
+offset_backing_file_size=16
 offset_l1_size=36
 offset_l1_table_offset=40
 offset_refcount_table_offset=48
@@ -135,6 +136,13 @@ poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xe
 poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Invalid backing file size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x10\x00"
+poke_file "$TEST_IMG" "$offset_backing_file_size" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 4ec2545..8103211 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -58,4 +58,9 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
 no file open, try 'help open'
 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
 no file open, try 'help open'
+
+== Invalid backing file size ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long
+no file open, try 'help open'
 *** done
commit 2d51c32c4b511db8bb9e58208f1e2c25e4c06c85
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:46 2014 +0100

    qcow2: Validate active L1 table offset and size (CVE-2014-0144)
    
    This avoids an unbounded allocation.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 8d0a09e..3639528 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -642,6 +642,13 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     s->nb_snapshots = header.nb_snapshots;
 
     /* read the level 1 table */
+    if (header.l1_size > 0x2000000) {
+        /* 32 MB L1 table is enough for 2 PB images at 64k cluster size
+         * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
+        error_setg(errp, "Active L1 table too large");
+        ret = -EFBIG;
+        goto fail;
+    }
     s->l1_size = header.l1_size;
 
     l1_vm_state_index = size_to_l1(s, header.size);
@@ -659,7 +666,16 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         ret = -EINVAL;
         goto fail;
     }
+
+    ret = validate_table_offset(bs, header.l1_table_offset,
+                                header.l1_size, sizeof(uint64_t));
+    if (ret < 0) {
+        error_setg(errp, "Invalid L1 table offset");
+        goto fail;
+    }
     s->l1_table_offset = header.l1_table_offset;
+
+
     if (s->l1_size > 0) {
         s->l1_table = g_malloc0(
             align_offset(s->l1_size * sizeof(uint64_t), 512));
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 8a8b460..7255b6c 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -45,6 +45,8 @@ _supported_os Linux
 header_size=104
 
 offset_backing_file_offset=8
+offset_l1_size=36
+offset_l1_table_offset=40
 offset_refcount_table_offset=48
 offset_refcount_table_clusters=56
 offset_nb_snapshots=60
@@ -117,6 +119,22 @@ poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x01\x00\x00"
 { $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Invalid L1 table =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_l1_size" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_l1_size" "\x7f\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x7f\xff\xff\xff\xff\xff\x00\x00"
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+poke_file "$TEST_IMG" "$offset_l1_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xef"
+poke_file "$TEST_IMG" "$offset_l1_size" "\x00\x00\x00\x01"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index b06f47f..4ec2545 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -47,4 +47,15 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 qemu-img: Could not create snapshot 'test': -27 (File too large)
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Invalid L1 table ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
+no file open, try 'help open'
 *** done
commit ce48f2f441ca98885267af6fd636a7cb804ee646
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:45 2014 +0100

    qcow2: Validate snapshot table offset/size (CVE-2014-0144)
    
    This avoid unbounded memory allocation and fixes a potential buffer
    overflow on 32 bit hosts.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 2fc6320..87fbfe1 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -26,31 +26,6 @@
 #include "block/block_int.h"
 #include "block/qcow2.h"
 
-typedef struct QEMU_PACKED QCowSnapshotHeader {
-    /* header is 8 byte aligned */
-    uint64_t l1_table_offset;
-
-    uint32_t l1_size;
-    uint16_t id_str_size;
-    uint16_t name_size;
-
-    uint32_t date_sec;
-    uint32_t date_nsec;
-
-    uint64_t vm_clock_nsec;
-
-    uint32_t vm_state_size;
-    uint32_t extra_data_size; /* for extension */
-    /* extra data follows */
-    /* id_str follows */
-    /* name follows  */
-} QCowSnapshotHeader;
-
-typedef struct QEMU_PACKED QCowSnapshotExtraData {
-    uint64_t vm_state_size_large;
-    uint64_t disk_size;
-} QCowSnapshotExtraData;
-
 void qcow2_free_snapshots(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
@@ -357,6 +332,10 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     uint64_t *l1_table = NULL;
     int64_t l1_table_offset;
 
+    if (s->nb_snapshots >= QCOW_MAX_SNAPSHOTS) {
+        return -EFBIG;
+    }
+
     memset(sn, 0, sizeof(*sn));
 
     /* Generate an ID if it wasn't passed */
diff --git a/block/qcow2.c b/block/qcow2.c
index 37a332f..8d0a09e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -623,6 +623,21 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
+    /* Snapshot table offset/length */
+    if (header.nb_snapshots > QCOW_MAX_SNAPSHOTS) {
+        error_setg(errp, "Too many snapshots");
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    ret = validate_table_offset(bs, header.snapshots_offset,
+                                header.nb_snapshots,
+                                sizeof(QCowSnapshotHeader));
+    if (ret < 0) {
+        error_setg(errp, "Invalid snapshot table offset");
+        goto fail;
+    }
+
     s->snapshots_offset = header.snapshots_offset;
     s->nb_snapshots = header.nb_snapshots;
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 0b0eac8..b153505 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -38,6 +38,7 @@
 #define QCOW_CRYPT_AES  1
 
 #define QCOW_MAX_CRYPT_CLUSTERS 32
+#define QCOW_MAX_SNAPSHOTS 65536
 
 /* indicate that the refcount of the referenced cluster is exactly one. */
 #define QCOW_OFLAG_COPIED     (1ULL << 63)
@@ -97,6 +98,32 @@ typedef struct QCowHeader {
     uint32_t header_length;
 } QEMU_PACKED QCowHeader;
 
+typedef struct QEMU_PACKED QCowSnapshotHeader {
+    /* header is 8 byte aligned */
+    uint64_t l1_table_offset;
+
+    uint32_t l1_size;
+    uint16_t id_str_size;
+    uint16_t name_size;
+
+    uint32_t date_sec;
+    uint32_t date_nsec;
+
+    uint64_t vm_clock_nsec;
+
+    uint32_t vm_state_size;
+    uint32_t extra_data_size; /* for extension */
+    /* extra data follows */
+    /* id_str follows */
+    /* name follows  */
+} QCowSnapshotHeader;
+
+typedef struct QEMU_PACKED QCowSnapshotExtraData {
+    uint64_t vm_state_size_large;
+    uint64_t disk_size;
+} QCowSnapshotExtraData;
+
+
 typedef struct QCowSnapshot {
     uint64_t l1_table_offset;
     uint32_t l1_size;
@@ -202,7 +229,7 @@ typedef struct BDRVQcowState {
     AES_KEY aes_decrypt_key;
     uint64_t snapshots_offset;
     int snapshots_size;
-    int nb_snapshots;
+    unsigned int nb_snapshots;
     QCowSnapshot *snapshots;
 
     int flags;
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index f58ac73..8a8b460 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -47,6 +47,8 @@ header_size=104
 offset_backing_file_offset=8
 offset_refcount_table_offset=48
 offset_refcount_table_clusters=56
+offset_nb_snapshots=60
+offset_snapshots_offset=64
 offset_header_size=100
 offset_ext_magic=$header_size
 offset_ext_size=$((header_size + 4))
@@ -90,6 +92,31 @@ poke_file "$TEST_IMG" "$offset_refcount_table_offset" "\xff\xff\xff\xff\xff\xff\
 poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x00\x00\x7f"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Invalid snapshot table =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_nb_snapshots" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x7f\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+poke_file "$TEST_IMG" "$offset_snapshots_offset" "\xff\xff\xff\xff\xff\xff\x00\x00"
+poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x00\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+poke_file "$TEST_IMG" "$offset_snapshots_offset" "\x12\x34\x56\x78\x90\xab\xcd\xef"
+poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x00\x00\x00"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Hitting snapshot table size limit =="
+_make_test_img 64M
+# Put the refcount table in a more or less safe place (16 MB)
+poke_file "$TEST_IMG" "$offset_snapshots_offset" "\x00\x00\x00\x00\x01\x00\x00\x00"
+poke_file "$TEST_IMG" "$offset_nb_snapshots" "\x00\x01\x00\x00"
+{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index f919b58..b06f47f 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -30,4 +30,21 @@ no file open, try 'help open'
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
 qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
 no file open, try 'help open'
+
+== Invalid snapshot table ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
+no file open, try 'help open'
+
+== Hitting snapshot table size limit ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-img: Could not create snapshot 'test': -27 (File too large)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 *** done
commit 8c7de28305a514d7f879fdfc677ca11fbf60d2e9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:44 2014 +0100

    qcow2: Validate refcount table offset
    
    The end of the refcount table must not exceed INT64_MAX so that integer
    overflows are avoided.
    
    Also check for misaligned refcount table. Such images are invalid and
    probably the result of data corruption. Error out to avoid further
    corruption.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index b9b6e70..37a332f 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -329,6 +329,32 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
     return ret;
 }
 
+static int validate_table_offset(BlockDriverState *bs, uint64_t offset,
+                                 uint64_t entries, size_t entry_len)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint64_t size;
+
+    /* Use signed INT64_MAX as the maximum even for uint64_t header fields,
+     * because values will be passed to qemu functions taking int64_t. */
+    if (entries > INT64_MAX / entry_len) {
+        return -EINVAL;
+    }
+
+    size = entries * entry_len;
+
+    if (INT64_MAX - size < offset) {
+        return -EINVAL;
+    }
+
+    /* Tables must be cluster aligned */
+    if (offset & (s->cluster_size - 1)) {
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 static QemuOptsList qcow2_runtime_opts = {
     .name = "qcow2",
     .head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head),
@@ -590,6 +616,13 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
+    ret = validate_table_offset(bs, s->refcount_table_offset,
+                                s->refcount_table_size, sizeof(uint64_t));
+    if (ret < 0) {
+        error_setg(errp, "Invalid reference count table offset");
+        goto fail;
+    }
+
     s->snapshots_offset = header.snapshots_offset;
     s->nb_snapshots = header.nb_snapshots;
 
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 6179e05..f58ac73 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -45,6 +45,7 @@ _supported_os Linux
 header_size=104
 
 offset_backing_file_offset=8
+offset_refcount_table_offset=48
 offset_refcount_table_clusters=56
 offset_header_size=100
 offset_ext_magic=$header_size
@@ -76,6 +77,18 @@ poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\xff\xff\xff\xff"
 poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x02\x00\x01"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Misaligned refcount table =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_refcount_table_offset" "\x12\x34\x56\x78\x90\xab\xcd\xef"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Huge refcount offset =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_refcount_table_offset" "\xff\xff\xff\xff\xff\xff\x00\x00"
+poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x00\x00\x7f"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
 # success, all done
 echo "*** done"
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 6fef6d9..f919b58 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -20,4 +20,14 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large
 no file open, try 'help open'
 qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large
 no file open, try 'help open'
+
+== Misaligned refcount table ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
+no file open, try 'help open'
+
+== Huge refcount offset ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
+no file open, try 'help open'
 *** done
commit 5dab2faddc8eaa1fb1abdbe2f502001fc13a1b21
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:43 2014 +0100

    qcow2: Check refcount table size (CVE-2014-0144)
    
    Limit the in-memory reference count table size to 8 MB, it's enough in
    practice. This fixes an unbounded allocation as well as a buffer
    overflow in qcow2_refcount_init().
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4a2df5f..e3c7ecd 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -40,8 +40,10 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
 int qcow2_refcount_init(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
-    int ret, refcount_table_size2, i;
+    unsigned int refcount_table_size2, i;
+    int ret;
 
+    assert(s->refcount_table_size <= INT_MAX / sizeof(uint64_t));
     refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
     s->refcount_table = g_malloc(refcount_table_size2);
     if (s->refcount_table_size > 0) {
diff --git a/block/qcow2.c b/block/qcow2.c
index f0411a9..b9b6e70 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -577,10 +577,19 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     s->csize_shift = (62 - (s->cluster_bits - 8));
     s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
     s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
+
     s->refcount_table_offset = header.refcount_table_offset;
     s->refcount_table_size =
         header.refcount_table_clusters << (s->cluster_bits - 3);
 
+    if (header.refcount_table_clusters > (0x800000 >> s->cluster_bits)) {
+        /* 8 MB refcount table is enough for 2 PB images at 64k cluster size
+         * (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
+        error_setg(errp, "Reference count table too large");
+        ret = -EINVAL;
+        goto fail;
+    }
+
     s->snapshots_offset = header.snapshots_offset;
     s->nb_snapshots = header.nb_snapshots;
 
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 6d588dd..6179e05 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -45,6 +45,7 @@ _supported_os Linux
 header_size=104
 
 offset_backing_file_offset=8
+offset_refcount_table_clusters=56
 offset_header_size=100
 offset_ext_magic=$header_size
 offset_ext_size=$((header_size + 4))
@@ -67,6 +68,15 @@ poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff"
 poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Huge refcount table size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_refcount_table_clusters" "\x00\x02\x00\x01"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 48c40aa..6fef6d9 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -13,4 +13,11 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset
 no file open, try 'help open'
 qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
 no file open, try 'help open'
+
+== Huge refcount table size ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large
+no file open, try 'help open'
 *** done
commit a1b3955c9415b1e767c130a2f59fee6aa28e575b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:42 2014 +0100

    qcow2: Check backing_file_offset (CVE-2014-0144)
    
    Header, header extension and the backing file name must all be stored in
    the first cluster. Setting the backing file to a much higher value
    allowed header extensions to become much bigger than we want them to be
    (unbounded allocation).
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 7809f5c..f0411a9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -511,6 +511,12 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         }
     }
 
+    if (header.backing_file_offset > s->cluster_size) {
+        error_setg(errp, "Invalid backing file offset");
+        ret = -EINVAL;
+        goto fail;
+    }
+
     if (header.backing_file_offset) {
         ext_end = header.backing_file_offset;
     } else {
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index 6512701..6d588dd 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -43,6 +43,8 @@ _supported_proto generic
 _supported_os Linux
 
 header_size=104
+
+offset_backing_file_offset=8
 offset_header_size=100
 offset_ext_magic=$header_size
 offset_ext_size=$((header_size + 4))
@@ -55,6 +57,16 @@ poke_file "$TEST_IMG" "$offset_header_size" "\xff\xff\xff\xff"
 poke_file "$TEST_IMG" "$offset_header_size" "\x7f\xff\xff\xff"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Huge unknown header extension =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_backing_file_offset" "\xff\xff\xff\xff\xff\xff\xff\xff"
+poke_file "$TEST_IMG" "$offset_ext_magic" "\x12\x34\x56\x78"
+poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index 41a166a..48c40aa 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -6,4 +6,11 @@ qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
 no file open, try 'help open'
 qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
 no file open, try 'help open'
+
+== Huge unknown header extension ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
+no file open, try 'help open'
 *** done
commit 24342f2cae47d03911e346fe1e520b00dc2818e0
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:41 2014 +0100

    qcow2: Check header_length (CVE-2014-0144)
    
    This fixes an unbounded allocation for s->unknown_header_fields.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 10eccf9..7809f5c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -460,6 +460,18 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
 
     s->qcow_version = header.version;
 
+    /* Initialise cluster size */
+    if (header.cluster_bits < MIN_CLUSTER_BITS ||
+        header.cluster_bits > MAX_CLUSTER_BITS) {
+        error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    s->cluster_bits = header.cluster_bits;
+    s->cluster_size = 1 << s->cluster_bits;
+    s->cluster_sectors = 1 << (s->cluster_bits - 9);
+
     /* Initialise version 3 header fields */
     if (header.version == 2) {
         header.incompatible_features    = 0;
@@ -473,6 +485,18 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         be64_to_cpus(&header.autoclear_features);
         be32_to_cpus(&header.refcount_order);
         be32_to_cpus(&header.header_length);
+
+        if (header.header_length < 104) {
+            error_setg(errp, "qcow2 header too short");
+            ret = -EINVAL;
+            goto fail;
+        }
+    }
+
+    if (header.header_length > s->cluster_size) {
+        error_setg(errp, "qcow2 header exceeds cluster size");
+        ret = -EINVAL;
+        goto fail;
     }
 
     if (header.header_length > sizeof(header)) {
@@ -530,12 +554,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     }
     s->refcount_order = header.refcount_order;
 
-    if (header.cluster_bits < MIN_CLUSTER_BITS ||
-        header.cluster_bits > MAX_CLUSTER_BITS) {
-        error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits);
-        ret = -EINVAL;
-        goto fail;
-    }
     if (header.crypt_method > QCOW_CRYPT_AES) {
         error_setg(errp, "Unsupported encryption method: %i",
                    header.crypt_method);
@@ -546,9 +564,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     if (s->crypt_method_header) {
         bs->encrypted = 1;
     }
-    s->cluster_bits = header.cluster_bits;
-    s->cluster_size = 1 << s->cluster_bits;
-    s->cluster_sectors = 1 << (s->cluster_bits - 9);
+
     s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
     s->l2_size = 1 << s->l2_bits;
     bs->total_sectors = header.size / 512;
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
new file mode 100755
index 0000000..6512701
--- /dev/null
+++ b/tests/qemu-iotests/080
@@ -0,0 +1,61 @@
+#!/bin/bash
+#
+# qcow2 format input validation tests
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+header_size=104
+offset_header_size=100
+offset_ext_magic=$header_size
+offset_ext_size=$((header_size + 4))
+
+echo
+echo "== Huge header size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_header_size" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_header_size" "\x7f\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
new file mode 100644
index 0000000..41a166a
--- /dev/null
+++ b/tests/qemu-iotests/080.out
@@ -0,0 +1,9 @@
+QA output created by 080
+
+== Huge header size ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
+no file open, try 'help open'
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 9c99edc..ed44f35 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -85,6 +85,7 @@
 077 rw auto quick
 078 rw auto
 079 rw auto
+080 rw auto
 081 rw auto
 082 rw auto quick
 083 rw auto
commit 6d4b9e55fc625514a38d27cff4b9933f617fa7dc
Author: Fam Zheng <famz at redhat.com>
Date:   Wed Mar 26 13:05:40 2014 +0100

    curl: check data size before memcpy to local buffer. (CVE-2014-0144)
    
    curl_read_cb is callback function for libcurl when data arrives. The
    data size passed in here is not guaranteed to be within the range of
    request we submitted, so we may overflow the guest IO buffer. Check the
    real size we have before memcpy to buffer to avoid overflow.
    
    Signed-off-by: Fam Zheng <famz at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/curl.c b/block/curl.c
index 3494c6d..1b9b1f6 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -157,6 +157,11 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
     if (!s || !s->orig_buf)
         goto read_end;
 
+    if (s->buf_off >= s->buf_len) {
+        /* buffer full, read nothing */
+        return 0;
+    }
+    realsize = MIN(realsize, s->buf_len - s->buf_off);
     memcpy(s->orig_buf + s->buf_off, ptr, realsize);
     s->buf_off += realsize;
 
commit 1d7678dec4761acdc43439da6ceda41a703ba1a6
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Mar 26 13:05:39 2014 +0100

    vhdx: Bounds checking for block_size and logical_sector_size (CVE-2014-0148)
    
    Other variables (e.g. sectors_per_block) are calculated using these
    variables, and if not range-checked illegal values could be obtained
    causing infinite loops and other potential issues when calculating
    BAT entries.
    
    The 1.00 VHDX spec requires BlockSize to be min 1MB, max 256MB.
    LogicalSectorSize is required to be either 512 or 4096 bytes.
    
    Reported-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vhdx.c b/block/vhdx.c
index 5390ba6..509baaf 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -780,12 +780,20 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
     le32_to_cpus(&s->logical_sector_size);
     le32_to_cpus(&s->physical_sector_size);
 
-    if (s->logical_sector_size == 0 || s->params.block_size == 0) {
+    if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
+        s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
         ret = -EINVAL;
         goto exit;
     }
 
-    /* both block_size and sector_size are guaranteed powers of 2 */
+    /* only 2 supported sector sizes */
+    if (s->logical_sector_size != 512 && s->logical_sector_size != 4096) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    /* Both block_size and sector_size are guaranteed powers of 2, below.
+       Due to range checks above, s->sectors_per_block can never be < 256 */
     s->sectors_per_block = s->params.block_size / s->logical_sector_size;
     s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
                      (uint64_t)s->logical_sector_size /
commit 63fa06dc978f3669dbfd9443b33cde9e2a7f4b41
Author: Jeff Cody <jcody at redhat.com>
Date:   Fri Mar 28 11:42:24 2014 -0400

    vdi: add bounds checks for blocks_in_image and disk_size header fields (CVE-2014-0144)
    
    The maximum blocks_in_image is 0xffffffff / 4, which also limits the
    maximum disk_size for a VDI image to 1024TB.  Note that this is the maximum
    size that QEMU will currently support with this driver, not necessarily the
    maximum size allowed by the image format.
    
    This also fixes an incorrect error message, a bug introduced by commit
    5b7aa9b56d1bfc79916262f380c3fc7961becb50 (Reported by Stefan Weil)
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index ac9a025..820cd37 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -120,6 +120,11 @@ typedef unsigned char uuid_t[16];
 
 #define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED)
 
+/* max blocks in image is (0xffffffff / 4) */
+#define VDI_BLOCKS_IN_IMAGE_MAX  0x3fffffff
+#define VDI_DISK_SIZE_MAX        ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
+                                  (uint64_t)DEFAULT_CLUSTER_SIZE)
+
 #if !defined(CONFIG_UUID)
 static inline void uuid_generate(uuid_t out)
 {
@@ -385,6 +390,14 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
     vdi_header_print(&header);
 #endif
 
+    if (header.disk_size > VDI_DISK_SIZE_MAX) {
+        error_setg(errp, "Unsupported VDI image size (size is 0x%" PRIx64
+                          ", max supported is 0x%" PRIx64 ")",
+                          header.disk_size, VDI_DISK_SIZE_MAX);
+        ret = -ENOTSUP;
+        goto fail;
+    }
+
     if (header.disk_size % SECTOR_SIZE != 0) {
         /* 'VBoxManage convertfromraw' can create images with odd disk sizes.
            We accept them but round the disk size to the next multiple of
@@ -420,9 +433,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
                    header.sector_size, SECTOR_SIZE);
         ret = -ENOTSUP;
         goto fail;
-    } else if (header.block_size != 1 * MiB) {
-        error_setg(errp, "unsupported VDI image (sector size %u is not %u)",
-                   header.block_size, 1 * MiB);
+    } else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
+        error_setg(errp, "unsupported VDI image (block size %u is not %u)",
+                   header.block_size, DEFAULT_CLUSTER_SIZE);
         ret = -ENOTSUP;
         goto fail;
     } else if (header.disk_size >
@@ -441,6 +454,12 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
         error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
         ret = -ENOTSUP;
         goto fail;
+    } else if (header.blocks_in_image > VDI_BLOCKS_IN_IMAGE_MAX) {
+        error_setg(errp, "unsupported VDI image "
+                         "(too many blocks %u, max is %u)",
+                          header.blocks_in_image, VDI_BLOCKS_IN_IMAGE_MAX);
+        ret = -ENOTSUP;
+        goto fail;
     }
 
     bs->total_sectors = header.disk_size / SECTOR_SIZE;
@@ -689,11 +708,20 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
         options++;
     }
 
+    if (bytes > VDI_DISK_SIZE_MAX) {
+        result = -ENOTSUP;
+        error_setg(errp, "Unsupported VDI image size (size is 0x%" PRIx64
+                          ", max supported is 0x%" PRIx64 ")",
+                          bytes, VDI_DISK_SIZE_MAX);
+        goto exit;
+    }
+
     fd = qemu_open(filename,
                    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
                    0644);
     if (fd < 0) {
-        return -errno;
+        result = -errno;
+        goto exit;
     }
 
     /* We need enough blocks to store the given disk size,
@@ -754,6 +782,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options,
         result = -errno;
     }
 
+exit:
     return result;
 }
 
commit 5e71dfad763d67bb64be79e20e93411c0c30ad25
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:37 2014 +0100

    vpc: Validate block size (CVE-2014-0142)
    
    This fixes some cases of division by zero crashes.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index ba82d48..2e25f57 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -245,6 +245,11 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
         }
 
         s->block_size = be32_to_cpu(dyndisk_header->block_size);
+        if (!is_power_of_2(s->block_size) || s->block_size < BDRV_SECTOR_SIZE) {
+            error_setg(errp, "Invalid block size %" PRIu32, s->block_size);
+            ret = -EINVAL;
+            goto fail;
+        }
         s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
 
         s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
diff --git a/tests/qemu-iotests/088 b/tests/qemu-iotests/088
new file mode 100755
index 0000000..c09adf8
--- /dev/null
+++ b/tests/qemu-iotests/088
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+# vpc (VHD) format input validation tests
+#
+# Copyright (C) 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+    rm -f $TEST_IMG.snap
+    _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt vpc
+_supported_proto generic
+_supported_os Linux
+
+offset_block_size=$((512 + 32))
+
+echo
+echo "== Invalid block size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_block_size" "\x00\x00\x00\x00"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_block_size" "\x00\x00\x00\x80"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_block_size" "\x12\x34\x56\x78"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/088.out b/tests/qemu-iotests/088.out
new file mode 100644
index 0000000..d961609
--- /dev/null
+++ b/tests/qemu-iotests/088.out
@@ -0,0 +1,17 @@
+QA output created by 088
+
+== Invalid block size ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 128
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 128
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 305419896
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 305419896
+no file open, try 'help open'
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ecba432..9c99edc 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -91,3 +91,4 @@
 085 rw auto
 086 rw auto quick
 087 rw auto
+088 rw auto
commit 97f1c45c6f456572e5b504b8614e4a69e23b8e3a
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Mar 26 13:05:36 2014 +0100

    vpc/vhd: add bounds check for max_table_entries and block_size (CVE-2014-0144)
    
    This adds checks to make sure that max_table_entries and block_size
    are in sane ranges.  Memory is allocated based on max_table_entries,
    and block_size is used to calculate indices into that allocated
    memory, so if these values are incorrect that can lead to potential
    unbounded memory allocation, or invalid memory accesses.
    
    Also, the allocation of the pagetable is changed from g_malloc0()
    to qemu_blockalign().
    
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vpc.c b/block/vpc.c
index 82bf248..ba82d48 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -45,6 +45,8 @@ enum vhd_type {
 // Seconds since Jan 1, 2000 0:00:00 (UTC)
 #define VHD_TIMESTAMP_BASE 946684800
 
+#define VHD_MAX_SECTORS       (65535LL * 255 * 255)
+
 // always big-endian
 typedef struct vhd_footer {
     char        creator[8]; // "conectix"
@@ -164,6 +166,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
     VHDDynDiskHeader *dyndisk_header;
     uint8_t buf[HEADER_SIZE];
     uint32_t checksum;
+    uint64_t computed_size;
     int disk_type = VHD_DYNAMIC;
     int ret;
 
@@ -222,7 +225,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     /* Allow a maximum disk size of approximately 2 TB */
-    if (bs->total_sectors >= 65535LL * 255 * 255) {
+    if (bs->total_sectors >= VHD_MAX_SECTORS) {
         ret = -EFBIG;
         goto fail;
     }
@@ -245,7 +248,23 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
         s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
 
         s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
-        s->pagetable = g_malloc(s->max_table_entries * 4);
+
+        if ((bs->total_sectors * 512) / s->block_size > 0xffffffffU) {
+            ret = -EINVAL;
+            goto fail;
+        }
+        if (s->max_table_entries > (VHD_MAX_SECTORS * 512) / s->block_size) {
+            ret = -EINVAL;
+            goto fail;
+        }
+
+        computed_size = (uint64_t) s->max_table_entries * s->block_size;
+        if (computed_size < bs->total_sectors * 512) {
+            ret = -EINVAL;
+            goto fail;
+        }
+
+        s->pagetable = qemu_blockalign(bs, s->max_table_entries * 4);
 
         s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
 
@@ -298,7 +317,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
     return 0;
 
 fail:
-    g_free(s->pagetable);
+    qemu_vfree(s->pagetable);
 #ifdef CACHE
     g_free(s->pageentry_u8);
 #endif
@@ -833,7 +852,7 @@ static int vpc_has_zero_init(BlockDriverState *bs)
 static void vpc_close(BlockDriverState *bs)
 {
     BDRVVPCState *s = bs->opaque;
-    g_free(s->pagetable);
+    qemu_vfree(s->pagetable);
 #ifdef CACHE
     g_free(s->pageentry_u8);
 #endif
commit a9ba36a45dfac645a810c31ce15ab393b69d820a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:35 2014 +0100

    bochs: Fix bitmap offset calculation
    
    32 bit truncation could let us access the wrong offset in the image.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index a922782..826ec12 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -186,8 +186,9 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 	return -1; /* not allocated */
     }
 
-    bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
-	(s->extent_blocks + s->bitmap_blocks));
+    bitmap_offset = s->data_offset +
+        (512 * (uint64_t) s->catalog_bitmap[extent_index] *
+        (s->extent_blocks + s->bitmap_blocks));
 
     /* read in bitmap for current extent */
     if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
commit 8e53abbc20d08ae3ec30c2054e1161314ad9501d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:34 2014 +0100

    bochs: Check extent_size header field (CVE-2014-0142)
    
    This fixes two possible division by zero crashes: In bochs_open() and in
    seek_to_sector().
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index 0ffa9c1..a922782 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -148,6 +148,14 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
     s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
 
     s->extent_size = le32_to_cpu(bochs.extent);
+    if (s->extent_size == 0) {
+        error_setg(errp, "Extent size may not be zero");
+        return -EINVAL;
+    } else if (s->extent_size > 0x800000) {
+        error_setg(errp, "Extent size %" PRIu32 " is too large",
+                   s->extent_size);
+        return -EINVAL;
+    }
 
     if (s->catalog_size < bs->total_sectors / s->extent_size) {
         error_setg(errp, "Catalog size is too small for this disk size");
diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078
index 902ef0f..872e734 100755
--- a/tests/qemu-iotests/078
+++ b/tests/qemu-iotests/078
@@ -43,6 +43,7 @@ _supported_proto generic
 _supported_os Linux
 
 catalog_size_offset=$((0x48))
+extent_size_offset=$((0x50))
 disk_size_offset=$((0x58))
 
 echo
@@ -68,6 +69,18 @@ _use_sample_img empty.bochs.bz2
 poke_file "$TEST_IMG" "$disk_size_offset" "\x00\xc0\x0f\x00\x00\x00\x00\x7f"
 { $QEMU_IO -c "read 2T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Negative extent size =="
+_use_sample_img empty.bochs.bz2
+poke_file "$TEST_IMG" "$extent_size_offset" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 768k 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Zero extent size =="
+_use_sample_img empty.bochs.bz2
+poke_file "$TEST_IMG" "$extent_size_offset" "\x00\x00\x00\x00"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out
index 7254693..ea95ffd 100644
--- a/tests/qemu-iotests/078.out
+++ b/tests/qemu-iotests/078.out
@@ -15,4 +15,12 @@ no file open, try 'help open'
 == Too small catalog bitmap for image size ==
 qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
 no file open, try 'help open'
+
+== Negative extent size ==
+qemu-io: can't open device TEST_DIR/empty.bochs: Extent size 4294967295 is too large
+no file open, try 'help open'
+
+== Zero extent size ==
+qemu-io: can't open device TEST_DIR/empty.bochs: Extent size may not be zero
+no file open, try 'help open'
 *** done
commit e3737b820b45e54b059656dc3f914f895ac7a88b
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:33 2014 +0100

    bochs: Check catalog_size header field (CVE-2014-0143)
    
    It should neither become negative nor allow unbounded memory
    allocations. This fixes aborts in g_malloc() and an s->catalog_bitmap
    buffer overflow on big endian hosts.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index e923eed..0ffa9c1 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -123,7 +123,14 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
         bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
     }
 
+    /* Limit to 1M entries to avoid unbounded allocation. This is what is
+     * needed for the largest image that bximage can create (~8 TB). */
     s->catalog_size = le32_to_cpu(bochs.catalog);
+    if (s->catalog_size > 0x100000) {
+        error_setg(errp, "Catalog size is too large");
+        return -EFBIG;
+    }
+
     s->catalog_bitmap = g_malloc(s->catalog_size * 4);
 
     ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
@@ -142,6 +149,12 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
 
     s->extent_size = le32_to_cpu(bochs.extent);
 
+    if (s->catalog_size < bs->total_sectors / s->extent_size) {
+        error_setg(errp, "Catalog size is too small for this disk size");
+        ret = -EINVAL;
+        goto fail;
+    }
+
     qemu_co_mutex_init(&s->lock);
     return 0;
 
diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078
index 73b573a..902ef0f 100755
--- a/tests/qemu-iotests/078
+++ b/tests/qemu-iotests/078
@@ -43,6 +43,7 @@ _supported_proto generic
 _supported_os Linux
 
 catalog_size_offset=$((0x48))
+disk_size_offset=$((0x58))
 
 echo
 echo "== Read from a valid image =="
@@ -55,6 +56,18 @@ _use_sample_img empty.bochs.bz2
 poke_file "$TEST_IMG" "$catalog_size_offset" "\xff\xff\xff\xff"
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Overflow for catalog size * sizeof(uint32_t) =="
+_use_sample_img empty.bochs.bz2
+poke_file "$TEST_IMG" "$catalog_size_offset" "\x00\x00\x00\x40"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Too small catalog bitmap for image size =="
+_use_sample_img empty.bochs.bz2
+poke_file "$TEST_IMG" "$disk_size_offset" "\x00\xc0\x0f\x00\x00\x00\x00\x7f"
+{ $QEMU_IO -c "read 2T 4k" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out
index ef8c42d..7254693 100644
--- a/tests/qemu-iotests/078.out
+++ b/tests/qemu-iotests/078.out
@@ -5,6 +5,14 @@ read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
 == Negative catalog size ==
-qemu-io: can't open device TEST_DIR/empty.bochs: Could not open 'TEST_DIR/empty.bochs': Interrupted system call
+qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too large
+no file open, try 'help open'
+
+== Overflow for catalog size * sizeof(uint32_t) ==
+qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too large
+no file open, try 'help open'
+
+== Too small catalog bitmap for image size ==
+qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
 no file open, try 'help open'
 *** done
commit 246f65838d19db6db55bfb41117c35645a2c4789
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:32 2014 +0100

    bochs: Use unsigned variables for offsets and sizes (CVE-2014-0147)
    
    Gets us rid of integer overflows resulting in negative sizes which
    aren't correctly checked.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index ef8e381..e923eed 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -67,13 +67,13 @@ struct bochs_header {
 typedef struct BDRVBochsState {
     CoMutex lock;
     uint32_t *catalog_bitmap;
-    int catalog_size;
+    uint32_t catalog_size;
 
-    int data_offset;
+    uint32_t data_offset;
 
-    int bitmap_blocks;
-    int extent_blocks;
-    int extent_size;
+    uint32_t bitmap_blocks;
+    uint32_t extent_blocks;
+    uint32_t extent_size;
 } BDRVBochsState;
 
 static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -97,7 +97,7 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
                       Error **errp)
 {
     BDRVBochsState *s = bs->opaque;
-    int i;
+    uint32_t i;
     struct bochs_header bochs;
     int ret;
 
@@ -153,8 +153,8 @@ fail:
 static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
 {
     BDRVBochsState *s = bs->opaque;
-    int64_t offset = sector_num * 512;
-    int64_t extent_index, extent_offset, bitmap_offset;
+    uint64_t offset = sector_num * 512;
+    uint64_t extent_index, extent_offset, bitmap_offset;
     char bitmap_entry;
 
     // seek to sector
diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078
index f55f46d..73b573a 100755
--- a/tests/qemu-iotests/078
+++ b/tests/qemu-iotests/078
@@ -42,11 +42,19 @@ _supported_fmt bochs
 _supported_proto generic
 _supported_os Linux
 
+catalog_size_offset=$((0x48))
+
 echo
 echo "== Read from a valid image =="
 _use_sample_img empty.bochs.bz2
 { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== Negative catalog size =="
+_use_sample_img empty.bochs.bz2
+poke_file "$TEST_IMG" "$catalog_size_offset" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out
index 25d37c5..ef8c42d 100644
--- a/tests/qemu-iotests/078.out
+++ b/tests/qemu-iotests/078.out
@@ -3,4 +3,8 @@ QA output created by 078
 == Read from a valid image ==
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Negative catalog size ==
+qemu-io: can't open device TEST_DIR/empty.bochs: Could not open 'TEST_DIR/empty.bochs': Interrupted system call
+no file open, try 'help open'
 *** done
commit 3dd8a6763bcc50dfc3de8da9279b741c0dea9fb1
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:31 2014 +0100

    bochs: Unify header structs and make them QEMU_PACKED
    
    This is an on-disk structure, so offsets must be accurate.
    
    Before this patch, sizeof(bochs) != sizeof(header_v1), which makes the
    memcpy() between both invalid. We're lucky enough that the destination
    buffer happened to be the larger one, and the memcpy size to be taken
    from the smaller one, so we didn't get a buffer overflow in practice.
    
    This patch unifies the both structures, eliminating the need to do a
    memcpy in the first place. The common fields are extracted to the top
    level of the struct and the actually differing part gets a union of the
    two versions.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/bochs.c b/block/bochs.c
index 4d6403f..ef8e381 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -39,45 +39,30 @@
 // not allocated: 0xffffffff
 
 // always little-endian
-struct bochs_header_v1 {
-    char magic[32]; // "Bochs Virtual HD Image"
-    char type[16]; // "Redolog"
-    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
-    uint32_t version;
-    uint32_t header; // size of header
-
-    union {
-	struct {
-	    uint32_t catalog; // num of entries
-	    uint32_t bitmap; // bitmap size
-	    uint32_t extent; // extent size
-	    uint64_t disk; // disk size
-	    char padding[HEADER_SIZE - 64 - 8 - 20];
-	} redolog;
-	char padding[HEADER_SIZE - 64 - 8];
-    } extra;
-};
-
-// always little-endian
 struct bochs_header {
-    char magic[32]; // "Bochs Virtual HD Image"
-    char type[16]; // "Redolog"
-    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
+    char magic[32];     /* "Bochs Virtual HD Image" */
+    char type[16];      /* "Redolog" */
+    char subtype[16];   /* "Undoable" / "Volatile" / "Growing" */
     uint32_t version;
-    uint32_t header; // size of header
+    uint32_t header;    /* size of header */
+
+    uint32_t catalog;   /* num of entries */
+    uint32_t bitmap;    /* bitmap size */
+    uint32_t extent;    /* extent size */
 
     union {
-	struct {
-	    uint32_t catalog; // num of entries
-	    uint32_t bitmap; // bitmap size
-	    uint32_t extent; // extent size
-	    uint32_t reserved; // for ???
-	    uint64_t disk; // disk size
-	    char padding[HEADER_SIZE - 64 - 8 - 24];
-	} redolog;
-	char padding[HEADER_SIZE - 64 - 8];
+        struct {
+            uint32_t reserved;  /* for ??? */
+            uint64_t disk;      /* disk size */
+            char padding[HEADER_SIZE - 64 - 20 - 12];
+        } QEMU_PACKED redolog;
+        struct {
+            uint64_t disk;      /* disk size */
+            char padding[HEADER_SIZE - 64 - 20 - 8];
+        } QEMU_PACKED redolog_v1;
+        char padding[HEADER_SIZE - 64 - 20];
     } extra;
-};
+} QEMU_PACKED;
 
 typedef struct BDRVBochsState {
     CoMutex lock;
@@ -114,7 +99,6 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
     BDRVBochsState *s = bs->opaque;
     int i;
     struct bochs_header bochs;
-    struct bochs_header_v1 header_v1;
     int ret;
 
     bs->read_only = 1; // no write support yet
@@ -134,13 +118,12 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     if (le32_to_cpu(bochs.version) == HEADER_V1) {
-      memcpy(&header_v1, &bochs, sizeof(bochs));
-      bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
+        bs->total_sectors = le64_to_cpu(bochs.extra.redolog_v1.disk) / 512;
     } else {
-      bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
+        bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
     }
 
-    s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
+    s->catalog_size = le32_to_cpu(bochs.catalog);
     s->catalog_bitmap = g_malloc(s->catalog_size * 4);
 
     ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
@@ -154,10 +137,10 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
 
     s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
 
-    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
-    s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
+    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.bitmap) - 1) / 512;
+    s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
 
-    s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
+    s->extent_size = le32_to_cpu(bochs.extent);
 
     qemu_co_mutex_init(&s->lock);
     return 0;
commit 24f3078a049c52070adfc659fc3a1a71a11a7765
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 26 13:05:30 2014 +0100

    qemu-iotests: Support for bochs format
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/078 b/tests/qemu-iotests/078
new file mode 100755
index 0000000..f55f46d
--- /dev/null
+++ b/tests/qemu-iotests/078
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# bochs format input validation tests
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt bochs
+_supported_proto generic
+_supported_os Linux
+
+echo
+echo "== Read from a valid image =="
+_use_sample_img empty.bochs.bz2
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out
new file mode 100644
index 0000000..25d37c5
--- /dev/null
+++ b/tests/qemu-iotests/078.out
@@ -0,0 +1,6 @@
+QA output created by 078
+
+== Read from a valid image ==
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 37e3bed..a09d9c8 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -136,6 +136,7 @@ common options
 
 check options
     -raw                test raw (default)
+    -bochs              test bochs
     -cow                test cow
     -cloop              test cloop
     -qcow               test qcow
@@ -174,6 +175,12 @@ testlist options
             xpand=false
             ;;
 
+        -bochs)
+            IMGFMT=bochs
+            IMGFMT_GENERIC=false
+            xpand=false
+            ;;
+
         -cow)
             IMGFMT=cow
             xpand=false
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 633e82d..ecba432 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -83,6 +83,7 @@
 074 rw auto quick
 075 rw auto
 077 rw auto quick
+078 rw auto
 079 rw auto
 081 rw auto
 082 rw auto quick
diff --git a/tests/qemu-iotests/sample_images/empty.bochs.bz2 b/tests/qemu-iotests/sample_images/empty.bochs.bz2
new file mode 100644
index 0000000..7a29c6e
Binary files /dev/null and b/tests/qemu-iotests/sample_images/empty.bochs.bz2 differ
commit 42d43d35d907579179a39c924d169da924786f65
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:29 2014 +0100

    block/cloop: fix offsets[] size off-by-one
    
    cloop stores the number of compressed blocks in the n_blocks header
    field.  The file actually contains n_blocks + 1 offsets, where the extra
    offset is the end-of-file offset.
    
    The following line in cloop_read_block() results in an out-of-bounds
    offsets[] access:
    
        uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
    
    This patch allocates and loads the extra offset so that
    cloop_read_block() works correctly when the last block is accessed.
    
    Notice that we must free s->offsets[] unconditionally now since there is
    always an end-of-file offset.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index 55a804f..b6ad50f 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -99,14 +99,14 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
     s->n_blocks = be32_to_cpu(s->n_blocks);
 
     /* read offsets */
-    if (s->n_blocks > UINT32_MAX / sizeof(uint64_t)) {
+    if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
         /* Prevent integer overflow */
         error_setg(errp, "n_blocks %u must be %zu or less",
                    s->n_blocks,
-                   UINT32_MAX / sizeof(uint64_t));
+                   (UINT32_MAX - 1) / sizeof(uint64_t));
         return -EINVAL;
     }
-    offsets_size = s->n_blocks * sizeof(uint64_t);
+    offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
     if (offsets_size > 512 * 1024 * 1024) {
         /* Prevent ridiculous offsets_size which causes memory allocation to
          * fail or overflows bdrv_pread() size.  In practice the 512 MB
@@ -123,7 +123,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    for(i=0;i<s->n_blocks;i++) {
+    for (i = 0; i < s->n_blocks + 1; i++) {
         uint64_t size;
 
         s->offsets[i] = be64_to_cpu(s->offsets[i]);
@@ -243,9 +243,7 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
 static void cloop_close(BlockDriverState *bs)
 {
     BDRVCloopState *s = bs->opaque;
-    if (s->n_blocks > 0) {
-        g_free(s->offsets);
-    }
+    g_free(s->offsets);
     g_free(s->compressed_block);
     g_free(s->uncompressed_block);
     inflateEnd(&s->zstream);
diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075
index d74fb33..40032c5 100755
--- a/tests/qemu-iotests/075
+++ b/tests/qemu-iotests/075
@@ -52,6 +52,11 @@ _use_sample_img simple-pattern.cloop.bz2
 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
 
 echo
+echo "== check that the last sector can be read =="
+_use_sample_img simple-pattern.cloop.bz2
+$QEMU_IO -c "read $((1024 * 1024 - 512)) 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
 echo "== block_size must be a multiple of 512 =="
 _use_sample_img simple-pattern.cloop.bz2
 poke_file "$TEST_IMG" "$block_size_offset" "\x00\x00\x02\x01"
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
index 911cd3b..5f1d6c1 100644
--- a/tests/qemu-iotests/075.out
+++ b/tests/qemu-iotests/075.out
@@ -4,6 +4,10 @@ QA output created by 075
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
+== check that the last sector can be read ==
+read 512/512 bytes at offset 1048064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
 == block_size must be a multiple of 512 ==
 qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512
 no file open, try 'help open'
commit f56b9bc3ae20fc93815b34aa022be919941406ce
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:28 2014 +0100

    block/cloop: refuse images with bogus offsets (CVE-2014-0144)
    
    The offsets[] array allows efficient seeking and tells us the maximum
    compressed data size.  If the offsets are bogus the maximum compressed
    data size will be unrealistic.
    
    This could cause g_malloc() to abort and bogus offsets mean the image is
    broken anyway.  Therefore we should refuse such images.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index 844665e..55a804f 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -124,12 +124,36 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     for(i=0;i<s->n_blocks;i++) {
+        uint64_t size;
+
         s->offsets[i] = be64_to_cpu(s->offsets[i]);
-        if (i > 0) {
-            uint32_t size = s->offsets[i] - s->offsets[i - 1];
-            if (size > max_compressed_block_size) {
-                max_compressed_block_size = size;
-            }
+        if (i == 0) {
+            continue;
+        }
+
+        if (s->offsets[i] < s->offsets[i - 1]) {
+            error_setg(errp, "offsets not monotonically increasing at "
+                       "index %u, image file is corrupt", i);
+            ret = -EINVAL;
+            goto fail;
+        }
+
+        size = s->offsets[i] - s->offsets[i - 1];
+
+        /* Compressed blocks should be smaller than the uncompressed block size
+         * but maybe compression performed poorly so the compressed block is
+         * actually bigger.  Clamp down on unrealistic values to prevent
+         * ridiculous s->compressed_block allocation.
+         */
+        if (size > 2 * MAX_BLOCK_SIZE) {
+            error_setg(errp, "invalid compressed block size at index %u, "
+                       "image file is corrupt", i);
+            ret = -EINVAL;
+            goto fail;
+        }
+
+        if (size > max_compressed_block_size) {
+            max_compressed_block_size = size;
         }
     }
 
diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075
index 9c00fa8..d74fb33 100755
--- a/tests/qemu-iotests/075
+++ b/tests/qemu-iotests/075
@@ -44,6 +44,7 @@ _supported_os Linux
 
 block_size_offset=128
 n_blocks_offset=132
+offsets_offset=136
 
 echo
 echo "== check that the first sector can be read =="
@@ -80,6 +81,20 @@ _use_sample_img simple-pattern.cloop.bz2
 poke_file "$TEST_IMG" "$n_blocks_offset" "\x04\x00\x00\x01"
 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== refuse images with non-monotonically increasing offsets =="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$offsets_offset" "\x00\x00\x00\x00\xff\xff\xff\xff"
+poke_file "$TEST_IMG" $((offsets_offset + 8)) "\x00\x00\x00\x00\xff\xfe\x00\x00"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== refuse images with invalid compressed block size =="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$offsets_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
+poke_file "$TEST_IMG" $((offsets_offset + 8)) "\xff\xff\xff\xff\xff\xff\xff\xff"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
index 7cdaee1..911cd3b 100644
--- a/tests/qemu-iotests/075.out
+++ b/tests/qemu-iotests/075.out
@@ -23,4 +23,12 @@ no file open, try 'help open'
 == refuse images that require too many offsets ===
 qemu-io: can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size
 no file open, try 'help open'
+
+== refuse images with non-monotonically increasing offsets ==
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: offsets not monotonically increasing at index 1, image file is corrupt
+no file open, try 'help open'
+
+== refuse images with invalid compressed block size ==
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: invalid compressed block size at index 1, image file is corrupt
+no file open, try 'help open'
 *** done
commit 7b103b36d6ef3b11827c203d3a793bf7da50ecd6
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:27 2014 +0100

    block/cloop: refuse images with huge offsets arrays (CVE-2014-0144)
    
    Limit offsets_size to 512 MB so that:
    
    1. g_malloc() does not abort due to an unreasonable size argument.
    
    2. offsets_size does not overflow the bdrv_pread() int size argument.
    
    This limit imposes a maximum image size of 16 TB at 256 KB block size.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index 563e916..844665e 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -107,6 +107,15 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
         return -EINVAL;
     }
     offsets_size = s->n_blocks * sizeof(uint64_t);
+    if (offsets_size > 512 * 1024 * 1024) {
+        /* Prevent ridiculous offsets_size which causes memory allocation to
+         * fail or overflows bdrv_pread() size.  In practice the 512 MB
+         * offsets[] limit supports 16 TB images at 256 KB block size.
+         */
+        error_setg(errp, "image requires too many offsets, "
+                   "try increasing block size");
+        return -EINVAL;
+    }
     s->offsets = g_malloc(offsets_size);
 
     ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075
index 9ce6b1f..9c00fa8 100755
--- a/tests/qemu-iotests/075
+++ b/tests/qemu-iotests/075
@@ -74,6 +74,12 @@ _use_sample_img simple-pattern.cloop.bz2
 poke_file "$TEST_IMG" "$n_blocks_offset" "\xff\xff\xff\xff"
 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== refuse images that require too many offsets ==="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$n_blocks_offset" "\x04\x00\x00\x01"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
index a771789..7cdaee1 100644
--- a/tests/qemu-iotests/075.out
+++ b/tests/qemu-iotests/075.out
@@ -19,4 +19,8 @@ no file open, try 'help open'
 == offsets_size overflow ===
 qemu-io: can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less
 no file open, try 'help open'
+
+== refuse images that require too many offsets ===
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size
+no file open, try 'help open'
 *** done
commit 509a41bab5306181044b5fff02eadf96d9c8676a
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:26 2014 +0100

    block/cloop: prevent offsets_size integer overflow (CVE-2014-0143)
    
    The following integer overflow in offsets_size can lead to out-of-bounds
    memory stores when n_blocks has a huge value:
    
        uint32_t n_blocks, offsets_size;
        [...]
        ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
        [...]
        s->n_blocks = be32_to_cpu(s->n_blocks);
    
        /* read offsets */
        offsets_size = s->n_blocks * sizeof(uint64_t);
        s->offsets = g_malloc(offsets_size);
    
        [...]
    
        for(i=0;i<s->n_blocks;i++) {
            s->offsets[i] = be64_to_cpu(s->offsets[i]);
    
    offsets_size can be smaller than n_blocks due to integer overflow.
    Therefore s->offsets[] is too small when the for loop byteswaps offsets.
    
    This patch refuses to open files if offsets_size would overflow.
    
    Note that changing the type of offsets_size is not a fix since 32-bit
    hosts still only have 32-bit size_t.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index f021663..563e916 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -99,6 +99,13 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
     s->n_blocks = be32_to_cpu(s->n_blocks);
 
     /* read offsets */
+    if (s->n_blocks > UINT32_MAX / sizeof(uint64_t)) {
+        /* Prevent integer overflow */
+        error_setg(errp, "n_blocks %u must be %zu or less",
+                   s->n_blocks,
+                   UINT32_MAX / sizeof(uint64_t));
+        return -EINVAL;
+    }
     offsets_size = s->n_blocks * sizeof(uint64_t);
     s->offsets = g_malloc(offsets_size);
 
diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075
index 8f54a99..9ce6b1f 100755
--- a/tests/qemu-iotests/075
+++ b/tests/qemu-iotests/075
@@ -43,6 +43,7 @@ _supported_proto generic
 _supported_os Linux
 
 block_size_offset=128
+n_blocks_offset=132
 
 echo
 echo "== check that the first sector can be read =="
@@ -67,6 +68,12 @@ _use_sample_img simple-pattern.cloop.bz2
 poke_file "$TEST_IMG" "$block_size_offset" "\xff\xff\xfe\x00"
 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== offsets_size overflow ==="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$n_blocks_offset" "\xff\xff\xff\xff"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
index d362c95..a771789 100644
--- a/tests/qemu-iotests/075.out
+++ b/tests/qemu-iotests/075.out
@@ -15,4 +15,8 @@ no file open, try 'help open'
 == huge block_size ===
 qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less
 no file open, try 'help open'
+
+== offsets_size overflow ===
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less
+no file open, try 'help open'
 *** done
commit d65f97a82c4ed48374a764c769d4ba1ea9724e97
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:25 2014 +0100

    block/cloop: validate block_size header field (CVE-2014-0144)
    
    Avoid unbounded s->uncompressed_block memory allocation by checking that
    the block_size header field has a reasonable value.  Also enforce the
    assumption that the value is a non-zero multiple of 512.
    
    These constraints conform to cloop 2.639's code so we accept existing
    image files.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/cloop.c b/block/cloop.c
index b907023..f021663 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -26,6 +26,9 @@
 #include "qemu/module.h"
 #include <zlib.h>
 
+/* Maximum compressed block size */
+#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
+
 typedef struct BDRVCloopState {
     CoMutex lock;
     uint32_t block_size;
@@ -68,6 +71,26 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
         return ret;
     }
     s->block_size = be32_to_cpu(s->block_size);
+    if (s->block_size % 512) {
+        error_setg(errp, "block_size %u must be a multiple of 512",
+                   s->block_size);
+        return -EINVAL;
+    }
+    if (s->block_size == 0) {
+        error_setg(errp, "block_size cannot be zero");
+        return -EINVAL;
+    }
+
+    /* cloop's create_compressed_fs.c warns about block sizes beyond 256 KB but
+     * we can accept more.  Prevent ridiculous values like 4 GB - 1 since we
+     * need a buffer this big.
+     */
+    if (s->block_size > MAX_BLOCK_SIZE) {
+        error_setg(errp, "block_size %u must be %u MB or less",
+                   s->block_size,
+                   MAX_BLOCK_SIZE / (1024 * 1024));
+        return -EINVAL;
+    }
 
     ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
     if (ret < 0) {
diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075
index 88ae8bb..8f54a99 100755
--- a/tests/qemu-iotests/075
+++ b/tests/qemu-iotests/075
@@ -42,11 +42,31 @@ _supported_fmt cloop
 _supported_proto generic
 _supported_os Linux
 
+block_size_offset=128
+
 echo
 echo "== check that the first sector can be read =="
 _use_sample_img simple-pattern.cloop.bz2
 $QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
 
+echo
+echo "== block_size must be a multiple of 512 =="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$block_size_offset" "\x00\x00\x02\x01"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== block_size cannot be zero =="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$block_size_offset" "\x00\x00\x00\x00"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== huge block_size ==="
+_use_sample_img simple-pattern.cloop.bz2
+poke_file "$TEST_IMG" "$block_size_offset" "\xff\xff\xfe\x00"
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
index 26661fa..d362c95 100644
--- a/tests/qemu-iotests/075.out
+++ b/tests/qemu-iotests/075.out
@@ -3,4 +3,16 @@ QA output created by 075
 == check that the first sector can be read ==
 read 512/512 bytes at offset 0
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== block_size must be a multiple of 512 ==
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512
+no file open, try 'help open'
+
+== block_size cannot be zero ==
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size cannot be zero
+no file open, try 'help open'
+
+== huge block_size ===
+qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less
+no file open, try 'help open'
 *** done
commit 05560fcebb1528f4354f6f24d1eb8cdbcdf2c4b2
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:24 2014 +0100

    qemu-iotests: add cloop input validation tests
    
    Add a cloop format-specific test case.  Later patches add tests for
    input validation to the script.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/075 b/tests/qemu-iotests/075
new file mode 100755
index 0000000..88ae8bb
--- /dev/null
+++ b/tests/qemu-iotests/075
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# cloop format input validation tests
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=stefanha at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt cloop
+_supported_proto generic
+_supported_os Linux
+
+echo
+echo "== check that the first sector can be read =="
+_use_sample_img simple-pattern.cloop.bz2
+$QEMU_IO -c "read 0 512" $TEST_IMG 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out
new file mode 100644
index 0000000..26661fa
--- /dev/null
+++ b/tests/qemu-iotests/075.out
@@ -0,0 +1,6 @@
+QA output created by 075
+
+== check that the first sector can be read ==
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ee09ebc..633e82d 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -81,6 +81,7 @@
 072 rw auto quick
 073 rw auto quick
 074 rw auto quick
+075 rw auto
 077 rw auto quick
 079 rw auto
 081 rw auto
diff --git a/tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 b/tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2
new file mode 100644
index 0000000..a02d2ee
Binary files /dev/null and b/tests/qemu-iotests/sample_images/simple-pattern.cloop.bz2 differ
commit 47f73da0a7d36e399eaa353d93afce90de9b599d
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 26 13:05:23 2014 +0100

    qemu-iotests: add ./check -cloop support
    
    Add the cloop block driver to qemu-iotests.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 5795358..37e3bed 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -137,6 +137,7 @@ common options
 check options
     -raw                test raw (default)
     -cow                test cow
+    -cloop              test cloop
     -qcow               test qcow
     -qcow2              test qcow2
     -qed                test qed
@@ -178,6 +179,12 @@ testlist options
             xpand=false
             ;;
 
+        -cloop)
+            IMGFMT=cloop
+            IMGFMT_GENERIC=false
+            xpand=false
+            ;;
+
         -qcow)
             IMGFMT=qcow
             xpand=false
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 881079b..7f00883 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -364,6 +364,9 @@ _fail()
 #
 _supported_fmt()
 {
+    # "generic" is suitable for most image formats. For some formats it doesn't
+    # work, however (most notably read-only formats), so they can opt out by
+    # setting IMGFMT_GENERIC to false.
     for f; do
         if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then
             return
commit c5a33ee9eee031c9bae362b9bd7045cd8ff24d86
Author: Prasad Joshi <prasadjoshi.linux at gmail.com>
Date:   Fri Mar 28 23:08:58 2014 +0530

    qcow2: fix two memory leaks in qcow2_open error code path
    
    Signed-off-by: Prasad Joshi <prasadjoshi.linux at gmail.com>
    Reviewed-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index b9dc960..10eccf9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -506,6 +506,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
                                    s->incompatible_features &
                                    ~QCOW2_INCOMPAT_MASK);
         ret = -ENOTSUP;
+        g_free(feature_table);
         goto fail;
     }
 
@@ -745,6 +746,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     if (s->l2_table_cache) {
         qcow2_cache_destroy(bs, s->l2_table_cache);
     }
+    if (s->refcount_block_cache) {
+        qcow2_cache_destroy(bs, s->refcount_block_cache);
+    }
     g_free(s->cluster_cache);
     qemu_vfree(s->cluster_data);
     return ret;
commit 4c7096607d0378de8d999c996802a73e601b2722
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 27 13:35:31 2014 +0100

    vvfat: Fix :floppy: option to suppress partition table
    
    Regressed in commit 7ad9be6, v1.5.0.
    
    Reported-by: Kiyokazu SUTO <suto at ks-and-ks.ne.jp>
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/vvfat.c b/block/vvfat.c
index f966ea5..1978c9e 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1119,6 +1119,7 @@ DLOG(if (stderr == NULL) {
         if (!s->fat_type) {
             s->fat_type = 16;
         }
+        s->first_sectors_number = 0x40;
         cyls = s->fat_type == 12 ? 64 : 1024;
         heads = 16;
         secs = 63;
@@ -1146,7 +1147,6 @@ DLOG(if (stderr == NULL) {
 
     s->current_cluster=0xffffffff;
 
-    s->first_sectors_number=0x40;
     /* read only is the default for safety */
     bs->read_only = 1;
     s->qcow = s->write_target = NULL;
commit bdf866fe6cce1f949227c32fcc9b7320fcdc60c6
Author: Prasad Joshi <prasadjoshi.linux at gmail.com>
Date:   Wed Mar 26 01:55:53 2014 +0530

    qemu-img: Release reference to BlockDriverState
    
    Signed-off-by: Prasad Joshi <prasadjoshi.linux at gmail.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/qemu-img.c b/qemu-img.c
index 77d946b..8455994 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1809,6 +1809,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         if (err) {
             error_report("%s", error_get_pretty(err));
             error_free(err);
+            bdrv_unref(bs);
             goto err;
         }
 
commit bdcc3a28b7f6ed6b90ad8b8af7b5d17e0d3f1f06
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 31 16:07:30 2014 +0200

    input: add sanity check
    
    Check we've actually found a input handler before trying to call it.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/input.c b/ui/input.c
index 6e6a924..1ed0e78 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -143,6 +143,9 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt)
 
     /* send event */
     s = qemu_input_find_handler(1 << evt->kind);
+    if (!s) {
+        return;
+    }
     s->handler->event(s->dev, src, evt);
     s->events++;
 }
commit 0419f78fae1d70bb5de0d44be62ec9741c5a742b
Author: Hani Benhabiles <kroosec at gmail.com>
Date:   Mon Mar 31 23:09:06 2014 +0100

    input: mouse_set should check input device type.
    
    Otherwise, the index of an input device like a usb-kbd is silently accepted.
    
    (qemu) info mice
      Mouse #2: QEMU PS/2 Mouse
    * Mouse #3: QEMU HID Mouse
    (qemu) mouse_set 1
    (qemu) info mice
      Mouse #2: QEMU PS/2 Mouse
    * Mouse #3: QEMU HID Mouse
    
    Also replace monitor_printf() call in do_mouse_set() with error_report() and
    adjust error message.
    
    Signed-off-by: Hani Benhabiles <hani at linux.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/input.c b/ui/input.c
index 2761911..6e6a924 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -342,15 +342,21 @@ void do_mouse_set(Monitor *mon, const QDict *qdict)
     int found = 0;
 
     QTAILQ_FOREACH(s, &handlers, node) {
-        if (s->id == index) {
-            found = 1;
-            qemu_input_handler_activate(s);
-            break;
+        if (s->id != index) {
+            continue;
         }
+        if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
+                                  INPUT_EVENT_MASK_ABS))) {
+            error_report("Input device '%s' is not a mouse", s->handler->name);
+            return;
+        }
+        found = 1;
+        qemu_input_handler_activate(s);
+        break;
     }
 
     if (!found) {
-        monitor_printf(mon, "Mouse at given index not found\n");
+        error_report("Mouse at index '%d' not found", index);
     }
 
     qemu_input_check_mode_change();
commit e82597f6f83bf872677cde37e540882880dcbafe
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 25 12:41:46 2014 +0100

    input: fix input_event_key_number trace event
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/trace-events b/trace-events
index 3df3f32..9303245 100644
--- a/trace-events
+++ b/trace-events
@@ -1022,7 +1022,7 @@ gd_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d"
 gd_key_event(int gdk_keycode, int qemu_keycode, const char *action) "translated GDK keycode %d to QEMU keycode %d (%s)"
 
 # ui/input.c
-input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%d, down %d"
+input_event_key_number(int conidx, int number, bool down) "con %d, key number 0x%x, down %d"
 input_event_key_qcode(int conidx, const char *qcode, bool down) "con %d, key qcode %s, down %d"
 input_event_btn(int conidx, const char *btn, bool down) "con %d, button %s, down %d"
 input_event_rel(int conidx, const char *axis, int value) "con %d, axis %s, value %d"
commit d25295d4efc53bf8521adf967445b8d087fe8d39
Author: Petar Jovanovic <petar.jovanovic at imgtec.com>
Date:   Mon Mar 31 17:41:23 2014 +0200

    linux-user: pass correct host flags to accept4()
    
    Flags NONBLOCK and CLOEXEC can have different values on the host and the
    guest, so set correct host values before calling accept4().
    
    This fixes several issues with accept4 system call and user-mode of QEMU.
    
    Signed-off-by: Petar Jovanovic <petar.jovanovic at imgtec.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2eac6d5..9864813 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2062,9 +2062,12 @@ static abi_long do_accept4(int fd, abi_ulong target_addr,
     socklen_t addrlen;
     void *addr;
     abi_long ret;
+    int host_flags;
+
+    host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
 
     if (target_addr == 0) {
-        return get_errno(accept4(fd, NULL, NULL, flags));
+        return get_errno(accept4(fd, NULL, NULL, host_flags));
     }
 
     /* linux returns EINVAL if addrlen pointer is invalid */
@@ -2080,7 +2083,7 @@ static abi_long do_accept4(int fd, abi_ulong target_addr,
 
     addr = alloca(addrlen);
 
-    ret = get_errno(accept4(fd, addr, &addrlen, flags));
+    ret = get_errno(accept4(fd, addr, &addrlen, host_flags));
     if (!is_error(ret)) {
         host_to_target_sockaddr(target_addr, addr, addrlen);
         if (put_user_u32(addrlen, target_addrlen_addr))
commit 95224e87a71d3190f46bf543ec9bc59ae36050eb
Merge: 63678e1 7373fc7
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 31 22:11:29 2014 +0100

    Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-2.0' into staging
    
    QOM/QTest infrastructure fixes
    
    * Revised QTest SIGABRT fix
    * Test cleanups for non-POSIX hosts
    * QTest test cases for NVMe, virtio-9p, pvpanic, i82801b11
    * QTest API addition for reading events
    * TMP105 fix and regression test
    
    # gpg: Signature made Mon 31 Mar 2014 22:08:10 BST using RSA key ID 3E7E013F
    # gpg: Good signature from "Andreas Färber <afaerber at suse.de>"
    # gpg:                 aka "Andreas Färber <afaerber at suse.com>"
    
    * remotes/afaerber/tags/qom-devices-for-2.0:
      tmp105-test: Test QOM property and precision
      tmp105-test: Add a second sensor and test that one
      tmp105-test: Wrap simple building blocks for testing
      tmp105: Read temperature in milli-celsius
      tests: Add i82801b11 qtest
      pvpanic-test: Assert pause event
      qtest: Factor out qtest_qmp_receive()
      tests: Add pvpanic qtest
      tests: Add virtio-9p qtest
      tests: Add nvme qtest
      nvme: Permit zero-length block devices
      tests: Correctly skip qtest on non-POSIX hosts
      tests: Skip POSIX-only tests on Windows
      tests: Remove unsupported tests for MinGW
      qtest: Keep list of qtest instances for SIGABRT handler
      Revert "qtest: Fix crash if SIGABRT during qtest_init()"
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 7373fc76930fc0994bab1bc2defd1d3a2b2adaa3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 31 18:26:35 2014 +0200

    tmp105-test: Test QOM property and precision
    
    This adds a regression test for commit
    efdf6a56a7c73753dd135ed085a223a119b5d805 (tmp105: Read temperature in
    milli-celsius).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 4e640b4..15ddaf3 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -20,6 +20,14 @@
 
 static I2CAdapter *i2c;
 
+static uint16_t tmp105_get8(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
+{
+    uint8_t resp[1];
+    i2c_send(i2c, addr, &reg, 1);
+    i2c_recv(i2c, addr, resp, 1);
+    return resp[0];
+}
+
 static uint16_t tmp105_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
 {
     uint8_t resp[2];
@@ -56,16 +64,81 @@ static void tmp105_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
     g_assert_cmphex(resp[1], ==, cmd[2]);
 }
 
+static int qmp_tmp105_get_temperature(const char *id)
+{
+    QDict *response;
+    int ret;
 
+    response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': '%s', "
+                   "'property': 'temperature' } }", id);
+    g_assert(qdict_haskey(response, "return"));
+    ret = qdict_get_int(response, "return");
+    QDECREF(response);
+    return ret;
+}
+
+static void qmp_tmp105_set_temperature(const char *id, int value)
+{
+    QDict *response;
+
+    response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': '%s', "
+                   "'property': 'temperature', 'value': %d } }", id, value);
+    g_assert(qdict_haskey(response, "return"));
+    QDECREF(response);
+}
+
+#define TMP105_PRECISION (1000/16)
 static void send_and_receive(void)
 {
     uint16_t value;
 
-    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    value = qmp_tmp105_get_temperature(TMP105_TEST_ID);
     g_assert_cmpuint(value, ==, 0);
 
-    /* reset */
-    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0);
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0);
+
+    qmp_tmp105_set_temperature(TMP105_TEST_ID, 20000);
+    value = qmp_tmp105_get_temperature(TMP105_TEST_ID);
+    g_assert_cmpuint(value, ==, 20000);
+
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0x1400);
+
+    qmp_tmp105_set_temperature(TMP105_TEST_ID, 20938); /* 20 + 15/16 */
+    value = qmp_tmp105_get_temperature(TMP105_TEST_ID);
+    g_assert_cmpuint(value, >=, 20938 - TMP105_PRECISION/2);
+    g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2);
+
+    /* Set config */
+    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60);
+    value = tmp105_get8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG);
+    g_assert_cmphex(value, ==, 0x60);
+
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0x14f0);
+
+    /* Set precision to 9, 10, 11 bits.  */
+    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x00);
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0x1480);
+
+    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x20);
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0x14c0);
+
+    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x40);
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0x14e0);
+
+    /* stored precision remains the same */
+    value = qmp_tmp105_get_temperature(TMP105_TEST_ID);
+    g_assert_cmpuint(value, >=, 20938 - TMP105_PRECISION/2);
+    g_assert_cmpuint(value, <, 20938 + TMP105_PRECISION/2);
+
+    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0x60);
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
+    g_assert_cmphex(value, ==, 0x14f0);
 
     tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234);
     tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231);
commit a4ec5bb7188490ad65b916a4a2e6ea7129602b60
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 31 18:26:34 2014 +0200

    tmp105-test: Add a second sensor and test that one
    
    This will make it easier to reach the device under test via QOM.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 20a1894..4e640b4 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -15,10 +15,10 @@
 
 #define OMAP2_I2C_1_BASE 0x48070000
 
-#define N8X0_ADDR 0x48
+#define TMP105_TEST_ID   "tmp105-test"
+#define TMP105_TEST_ADDR 0x49
 
 static I2CAdapter *i2c;
-static uint8_t addr;
 
 static uint16_t tmp105_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
 {
@@ -61,14 +61,14 @@ static void send_and_receive(void)
 {
     uint16_t value;
 
-    value = tmp105_get16(i2c, addr, TMP105_REG_TEMPERATURE);
+    value = tmp105_get16(i2c, TMP105_TEST_ADDR, TMP105_REG_TEMPERATURE);
     g_assert_cmpuint(value, ==, 0);
 
     /* reset */
-    tmp105_set8(i2c, addr, TMP105_REG_CONFIG, 0);
+    tmp105_set8(i2c, TMP105_TEST_ADDR, TMP105_REG_CONFIG, 0);
 
-    tmp105_set16(i2c, addr, TMP105_REG_T_LOW, 0x1234);
-    tmp105_set16(i2c, addr, TMP105_REG_T_HIGH, 0x4231);
+    tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_LOW, 0x1234);
+    tmp105_set16(i2c, TMP105_TEST_ADDR, TMP105_REG_T_HIGH, 0x4231);
 }
 
 int main(int argc, char **argv)
@@ -78,9 +78,10 @@ int main(int argc, char **argv)
 
     g_test_init(&argc, &argv, NULL);
 
-    s = qtest_start("-machine n800");
+    s = qtest_start("-machine n800 "
+                    "-device tmp105,bus=i2c-bus.0,id=" TMP105_TEST_ID
+                    ",address=0x49");
     i2c = omap_i2c_create(OMAP2_I2C_1_BASE);
-    addr = N8X0_ADDR;
 
     qtest_add_func("/tmp105/tx-rx", send_and_receive);
 
commit cebac614983a7479f2cd3b903e2127edd865c013
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 31 18:26:33 2014 +0200

    tmp105-test: Wrap simple building blocks for testing
    
    The next patches will add more reads and writes.  Add a simple testing
    API for this.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 0834219..20a1894 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -20,39 +20,57 @@
 static I2CAdapter *i2c;
 static uint8_t addr;
 
-static void send_and_receive(void)
+static uint16_t tmp105_get16(I2CAdapter *i2c, uint8_t addr, uint8_t reg)
 {
-    uint8_t cmd[3];
     uint8_t resp[2];
-
-    cmd[0] = TMP105_REG_TEMPERATURE;
-    i2c_send(i2c, addr, cmd, 1);
+    i2c_send(i2c, addr, &reg, 1);
     i2c_recv(i2c, addr, resp, 2);
-    g_assert_cmpuint(((uint16_t)resp[0] << 8) | resp[1], ==, 0);
+    return (resp[0] << 8) | resp[1];
+}
+
+static void tmp105_set8(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
+                        uint8_t value)
+{
+    uint8_t cmd[2];
+    uint8_t resp[1];
 
-    cmd[0] = TMP105_REG_CONFIG;
-    cmd[1] = 0x0; /* matches the reset value */
+    cmd[0] = reg;
+    cmd[1] = value;
     i2c_send(i2c, addr, cmd, 2);
     i2c_recv(i2c, addr, resp, 1);
     g_assert_cmphex(resp[0], ==, cmd[1]);
+}
 
-    cmd[0] = TMP105_REG_T_LOW;
-    cmd[1] = 0x12;
-    cmd[2] = 0x34;
-    i2c_send(i2c, addr, cmd, 3);
-    i2c_recv(i2c, addr, resp, 2);
-    g_assert_cmphex(resp[0], ==, cmd[1]);
-    g_assert_cmphex(resp[1], ==, cmd[2]);
+static void tmp105_set16(I2CAdapter *i2c, uint8_t addr, uint8_t reg,
+                         uint16_t value)
+{
+    uint8_t cmd[3];
+    uint8_t resp[2];
 
-    cmd[0] = TMP105_REG_T_HIGH;
-    cmd[1] = 0x42;
-    cmd[2] = 0x31;
+    cmd[0] = reg;
+    cmd[1] = value >> 8;
+    cmd[2] = value & 255;
     i2c_send(i2c, addr, cmd, 3);
     i2c_recv(i2c, addr, resp, 2);
     g_assert_cmphex(resp[0], ==, cmd[1]);
     g_assert_cmphex(resp[1], ==, cmd[2]);
 }
 
+
+static void send_and_receive(void)
+{
+    uint16_t value;
+
+    value = tmp105_get16(i2c, addr, TMP105_REG_TEMPERATURE);
+    g_assert_cmpuint(value, ==, 0);
+
+    /* reset */
+    tmp105_set8(i2c, addr, TMP105_REG_CONFIG, 0);
+
+    tmp105_set16(i2c, addr, TMP105_REG_T_LOW, 0x1234);
+    tmp105_set16(i2c, addr, TMP105_REG_T_HIGH, 0x4231);
+}
+
 int main(int argc, char **argv)
 {
     QTestState *s = NULL;
commit efdf6a56a7c73753dd135ed085a223a119b5d805
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 31 18:26:32 2014 +0200

    tmp105: Read temperature in milli-celsius
    
    Right now, the temperature property must be written in milli-celsius,
    but it reads back the value in 8.8 fixed point.  Fix this by letting the
    property read back the original value (possibly rounded).  Also simplify
    the code that does the conversion.
    
    Before:
    
        (QEMU) qom-set path=/machine/peripheral/sensor property=temperature value=20000
        {u'return': {}}
        (QEMU) qom-get path=sensor property=temperature
        {u'return': 5120}
    
    After:
    
        (QEMU) qom-set path=/machine/peripheral/sensor property=temperature value=20000
        {u'return': {}}
        (QEMU) qom-get path=sensor property=temperature
        {u'return': 20000}
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c
index 155e03d..63aa3d6 100644
--- a/hw/misc/tmp105.c
+++ b/hw/misc/tmp105.c
@@ -56,12 +56,14 @@ static void tmp105_get_temperature(Object *obj, Visitor *v, void *opaque,
                                    const char *name, Error **errp)
 {
     TMP105State *s = TMP105(obj);
-    int64_t value = s->temperature;
+    int64_t value = s->temperature * 1000 / 256;
 
     visit_type_int(v, &value, name, errp);
 }
 
-/* Units are 0.001 centigrades relative to 0 C.  */
+/* Units are 0.001 centigrades relative to 0 C.  s->temperature is 8.8
+ * fixed point, so units are 1/256 centigrades.  A simple ratio will do.
+ */
 static void tmp105_set_temperature(Object *obj, Visitor *v, void *opaque,
                                    const char *name, Error **errp)
 {
@@ -78,7 +80,7 @@ static void tmp105_set_temperature(Object *obj, Visitor *v, void *opaque,
         return;
     }
 
-    s->temperature = ((int16_t) (temp * 0x800 / 128000)) << 4;
+    s->temperature = (int16_t) (temp * 256 / 1000);
 
     tmp105_alarm_update(s);
 }
commit e683eb9ecc5cb72a6e89ddacaf097cb8fa839584
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 22:43:43 2014 +0100

    tests: Add i82801b11 qtest
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/Makefile b/tests/Makefile
index e4f7c07..6086f68 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -135,6 +135,8 @@ gcov-files-i386-y += hw/net/vmxnet_rx_pkt.c
 gcov-files-i386-y += hw/net/vmxnet_tx_pkt.c
 check-qtest-i386-y += tests/pvpanic-test$(EXESUF)
 gcov-files-i386-y += i386-softmmu/hw/misc/pvpanic.c
+check-qtest-i386-y += tests/i82801b11-test$(EXESUF)
+gcov-files-i386-y += hw/pci-bridge/i82801b11.c
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -284,6 +286,7 @@ tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
 tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
 tests/nvme-test$(EXESUF): tests/nvme-test.o
 tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
+tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 
 # QTest rules
diff --git a/tests/i82801b11-test.c b/tests/i82801b11-test.c
new file mode 100644
index 0000000..78d9ce0
--- /dev/null
+++ b/tests/i82801b11-test.c
@@ -0,0 +1,33 @@
+/*
+ * QTest testcase for i82801b11
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include "libqtest.h"
+#include "qemu/osdep.h"
+
+/* Tests only initialization so far. TODO: Replace with functional tests */
+static void nop(void)
+{
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/i82801b11/nop", nop);
+
+    qtest_start("-machine q35 -device i82801b11-bridge,bus=pcie.0,addr=1e.0");
+    ret = g_test_run();
+
+    qtest_end();
+
+    return ret;
+}
commit 627b1a17ced89e13df34a85feef54a50e9b94191
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 21:17:17 2014 +0100

    pvpanic-test: Assert pause event
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/pvpanic-test.c b/tests/pvpanic-test.c
index 7bb4d06..a7ad6b3 100644
--- a/tests/pvpanic-test.c
+++ b/tests/pvpanic-test.c
@@ -15,11 +15,20 @@
 static void test_panic(void)
 {
     uint8_t val;
+    QDict *response, *data;
 
     val = inb(0x505);
     g_assert_cmpuint(val, ==, 1);
 
     outb(0x505, 0x1);
+
+    response = qmp_receive();
+    g_assert(qdict_haskey(response, "event"));
+    g_assert_cmpstr(qdict_get_str(response, "event"), ==, "GUEST_PANICKED");
+    g_assert(qdict_haskey(response, "data"));
+    data = qdict_get_qdict(response, "data");
+    g_assert(qdict_haskey(data, "action"));
+    g_assert_cmpstr(qdict_get_str(data, "action"), ==, "pause");
 }
 
 int main(int argc, char **argv)
commit 66e0c7b187e130f5059e45e12832951deda31668
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 20:55:30 2014 +0100

    qtest: Factor out qtest_qmp_receive()
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/libqtest.c b/tests/libqtest.c
index d9e3a33..8155695 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -345,14 +345,10 @@ static void qmp_response(JSONMessageParser *parser, QList *tokens)
     qmp->response = (QDict *)obj;
 }
 
-QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
+QDict *qtest_qmp_receive(QTestState *s)
 {
     QMPResponseParser qmp;
 
-    /* Send QMP request */
-    socket_sendf(s->qmp_fd, fmt, ap);
-
-    /* Receive reply */
     qmp.response = NULL;
     json_message_parser_init(&qmp.parser, qmp_response);
     while (!qmp.response) {
@@ -376,6 +372,15 @@ QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
     return qmp.response;
 }
 
+QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
+{
+    /* Send QMP request */
+    socket_sendf(s->qmp_fd, fmt, ap);
+
+    /* Receive reply */
+    return qtest_qmp_receive(s);
+}
+
 QDict *qtest_qmp(QTestState *s, const char *fmt, ...)
 {
     va_list ap;
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 8268c09..8f323c7 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -83,6 +83,14 @@ void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap);
 QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap);
 
 /**
+ * qtest_receive:
+ * @s: #QTestState instance to operate on.
+ *
+ * Reads a QMP message from QEMU and returns the response.
+ */
+QDict *qtest_qmp_receive(QTestState *s);
+
+/**
  * qtest_get_irq:
  * @s: #QTestState instance to operate on.
  * @num: Interrupt to observe.
@@ -367,6 +375,16 @@ QDict *qmp(const char *fmt, ...);
 void qmp_discard_response(const char *fmt, ...);
 
 /**
+ * qmp_receive:
+ *
+ * Reads a QMP message from QEMU and returns the response.
+ */
+static inline QDict *qmp_receive(void)
+{
+    return qtest_qmp_receive(global_qtest);
+}
+
+/**
  * get_irq:
  * @num: Interrupt to observe.
  *
commit abc53733f34a8a29cc49c1ecb6475a11a44dcb7a
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 20:38:48 2014 +0100

    tests: Add pvpanic qtest
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/Makefile b/tests/Makefile
index 843429b..e4f7c07 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -133,6 +133,8 @@ check-qtest-i386-y += tests/vmxnet3-test$(EXESUF)
 gcov-files-i386-y += hw/net/vmxnet3.c
 gcov-files-i386-y += hw/net/vmxnet_rx_pkt.c
 gcov-files-i386-y += hw/net/vmxnet_tx_pkt.c
+check-qtest-i386-y += tests/pvpanic-test$(EXESUF)
+gcov-files-i386-y += i386-softmmu/hw/misc/pvpanic.c
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -281,6 +283,7 @@ tests/qom-test$(EXESUF): tests/qom-test.o
 tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
 tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
 tests/nvme-test$(EXESUF): tests/nvme-test.o
+tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 
 # QTest rules
diff --git a/tests/pvpanic-test.c b/tests/pvpanic-test.c
new file mode 100644
index 0000000..7bb4d06
--- /dev/null
+++ b/tests/pvpanic-test.c
@@ -0,0 +1,38 @@
+/*
+ * QTest testcase for PV Panic
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include "libqtest.h"
+#include "qemu/osdep.h"
+
+static void test_panic(void)
+{
+    uint8_t val;
+
+    val = inb(0x505);
+    g_assert_cmpuint(val, ==, 1);
+
+    outb(0x505, 0x1);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/pvpanic/panic", test_panic);
+
+    qtest_start("-device pvpanic");
+    ret = g_test_run();
+
+    qtest_end();
+
+    return ret;
+}
commit 2d888c099cb89eea0c5329d66abf6cd2865eed8a
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 17:15:21 2014 +0100

    tests: Add virtio-9p qtest
    
    Make it conditional to 9p availability.
    Create a temporary directory to share.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/MAINTAINERS b/MAINTAINERS
index 4d8eefc..4923b0f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -623,6 +623,7 @@ M: Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
 S: Supported
 F: hw/9pfs/
 F: fsdev/
+F: tests/virtio-9p-test.c
 T: git git://github.com/kvaneesh/QEMU.git
 
 virtio-blk
diff --git a/tests/Makefile b/tests/Makefile
index 01a3463..843429b 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -84,6 +84,11 @@ check-qtest-virtio-y += tests/virtio-rng-test$(EXESUF)
 gcov-files-virtio-y += hw/virtio/virtio-rng.c
 check-qtest-virtio-y += tests/virtio-scsi-test$(EXESUF)
 gcov-files-virtio-y += i386-softmmu/hw/scsi/virtio-scsi.c
+ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
+check-qtest-virtio-y += tests/virtio-9p-test$(EXESUF)
+gcov-files-virtio-y += hw/9pfs/virtio-9p.c
+gcov-files-virtio-y += i386-softmmu/hw/9pfs/virtio-9p-device.c
+endif
 check-qtest-virtio-y += tests/virtio-serial-test$(EXESUF)
 gcov-files-virtio-y += i386-softmmu/hw/char/virtio-serial-bus.c
 check-qtest-virtio-y += $(check-qtest-virtioserial-y)
@@ -267,6 +272,7 @@ tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o
 tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o
 tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o
 tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o
+tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
 tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
 tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
 tests/tpci200-test$(EXESUF): tests/tpci200-test.o
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
new file mode 100644
index 0000000..1fae477
--- /dev/null
+++ b/tests/virtio-9p-test.c
@@ -0,0 +1,46 @@
+/*
+ * QTest testcase for VirtIO 9P
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "libqtest.h"
+#include "qemu-common.h"
+#include "qemu/osdep.h"
+
+/* Tests only initialization so far. TODO: Replace with functional tests */
+static void pci_nop(void)
+{
+}
+
+static char test_share[] = "/tmp/qtest.XXXXXX";
+
+int main(int argc, char **argv)
+{
+    char *args;
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/virtio/9p/pci/nop", pci_nop);
+
+    g_assert(mkdtemp(test_share));
+
+    args = g_strdup_printf("-fsdev local,id=fsdev0,security_model=none,path=%s "
+                           "-device virtio-9p-pci,fsdev=fsdev0,mount_tag=qtest",
+                           test_share);
+    qtest_start(args);
+    g_free(args);
+
+    ret = g_test_run();
+
+    qtest_end();
+    rmdir(test_share);
+
+    return ret;
+}
commit fc9677915cc1273b4757a911f27f2f5038168053
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 22:19:43 2014 +0100

    tests: Add nvme qtest
    
    Acked-by: Keith Busch <keith.busch at intel.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/MAINTAINERS b/MAINTAINERS
index 7d17f83..4d8eefc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -648,6 +648,7 @@ nvme
 M: Keith Busch <keith.busch at intel.com>
 S: Supported
 F: hw/block/nvme*
+F: tests/nvme-test.c
 
 Xilinx EDK
 M: Peter Crosthwaite <peter.crosthwaite at petalogix.com>
diff --git a/tests/Makefile b/tests/Makefile
index 0e3eb44..01a3463 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -100,6 +100,8 @@ check-qtest-pci-y += tests/eepro100-test$(EXESUF)
 gcov-files-pci-y += hw/net/eepro100.c
 check-qtest-pci-y += tests/ne2000-test$(EXESUF)
 gcov-files-pci-y += hw/net/ne2000.c
+check-qtest-pci-y += tests/nvme-test$(EXESUF)
+gcov-files-pci-y += hw/block/nvme.c
 check-qtest-pci-y += $(check-qtest-virtio-y)
 gcov-files-pci-y += $(gcov-files-virtio-y) hw/virtio/virtio-pci.c
 check-qtest-pci-y += tests/tpci200-test$(EXESUF)
@@ -272,6 +274,7 @@ tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
 tests/qom-test$(EXESUF): tests/qom-test.o
 tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
 tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
+tests/nvme-test$(EXESUF): tests/nvme-test.o
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 
 # QTest rules
diff --git a/tests/nvme-test.c b/tests/nvme-test.c
new file mode 100644
index 0000000..85768e8
--- /dev/null
+++ b/tests/nvme-test.c
@@ -0,0 +1,34 @@
+/*
+ * QTest testcase for NVMe
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include "libqtest.h"
+#include "qemu/osdep.h"
+
+/* Tests only initialization so far. TODO: Replace with functional tests */
+static void nop(void)
+{
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/nvme/nop", nop);
+
+    qtest_start("-drive id=drv0,if=none,file=/dev/null "
+                "-device nvme,drive=drv0,serial=foo");
+    ret = g_test_run();
+
+    qtest_end();
+
+    return ret;
+}
commit 592408b8cab08bb4ec4771d7b1e20343b7f072fc
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 21 22:18:31 2014 +0100

    nvme: Permit zero-length block devices
    
    It may not be sensible for normal use cases, but it allows to use
    /dev/null in QTest.
    
    Acked-by: Keith Busch <keith.busch at intel.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 2882ffe..5fd8f89 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -752,8 +752,8 @@ static int nvme_init(PCIDevice *pci_dev)
         return -1;
     }
 
-    bs_size =  bdrv_getlength(n->conf.bs);
-    if (bs_size <= 0) {
+    bs_size = bdrv_getlength(n->conf.bs);
+    if (bs_size < 0) {
         return -1;
     }
 
commit 5c4e24c1516b6b8c21b6defcd4ffcf05f21202f7
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 28 10:55:54 2014 +0100

    tests: Correctly skip qtest on non-POSIX hosts
    
    qtest test cases only work on POSIX hosts.  The following line only
    defines dependencies for qtest binaries on POSIX hosts:
    
      check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS),$(check-qtest-$(TARGET)-y))
    
    But the QTEST_TARGETS definition earlier in the Makefile fails to check
    CONFIG_POSIX.  This causes make targets to be generated for qtest test
    cases even though we don't know how to build the binaries.
    
    The following error message is printed when trying to run gtester on a
    binary that was never built:
    
      GLib-WARNING **: Failed to execute test binary: tests/endianness-test.exe: Failed to execute child process "tests/endianness-test.exe" (No such file or directory)
    
    This patch makes QTEST_TARGETS empty on non-POSIX hosts.  This prevents
    the targets from being generated.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/Makefile b/tests/Makefile
index ef286e7..0e3eb44 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -277,8 +277,10 @@ tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_hel
 # QTest rules
 
 TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
+ifeq ($(CONFIG_POSIX),y)
 QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
-check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
+check-qtest-y=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
+endif
 
 qtest-obj-y = tests/libqtest.o libqemuutil.a libqemustub.a
 $(check-qtest-y): $(qtest-obj-y)
commit d597a32a6dc5b2ef58b280100cd551b7fb30c963
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 28 10:55:53 2014 +0100

    tests: Skip POSIX-only tests on Windows
    
    test-rfifolock and test-vmstate only build on POSIX hosts.  Exclude them
    if building for Windows.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/Makefile b/tests/Makefile
index 2d021fb..ef286e7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -35,7 +35,7 @@ check-unit-y += tests/test-visitor-serialization$(EXESUF)
 check-unit-y += tests/test-iov$(EXESUF)
 gcov-files-test-iov-y = util/iov.c
 check-unit-y += tests/test-aio$(EXESUF)
-check-unit-y += tests/test-rfifolock$(EXESUF)
+check-unit-$(CONFIG_POSIX) += tests/test-rfifolock$(EXESUF)
 check-unit-y += tests/test-throttle$(EXESUF)
 gcov-files-test-aio-$(CONFIG_WIN32) = aio-win32.c
 gcov-files-test-aio-$(CONFIG_POSIX) = aio-posix.c
@@ -59,7 +59,7 @@ check-unit-y += tests/test-bitops$(EXESUF)
 check-unit-y += tests/test-qdev-global-props$(EXESUF)
 check-unit-y += tests/check-qom-interface$(EXESUF)
 gcov-files-check-qom-interface-y = qom/object.c
-check-unit-y += tests/test-vmstate$(EXESUF)
+check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
commit 087570942994db2550b0aa377fedca2235373004
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 28 10:55:52 2014 +0100

    tests: Remove unsupported tests for MinGW
    
    test_timer_schedule and test_source_timer_schedule don't compile for MinGW
    because some functions are not implemented for MinGW (qemu_pipe,
    aio_set_fd_handler).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/test-aio.c b/tests/test-aio.c
index 56f4288..e5f8b55 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -65,6 +65,8 @@ static void bh_test_cb(void *opaque)
     }
 }
 
+#if !defined(_WIN32)
+
 static void timer_test_cb(void *opaque)
 {
     TimerTestData *data = opaque;
@@ -78,6 +80,8 @@ static void dummy_io_handler_read(void *opaque)
 {
 }
 
+#endif /* !_WIN32 */
+
 static void bh_delete_cb(void *opaque)
 {
     BHTestData *data = opaque;
@@ -423,6 +427,8 @@ static void test_wait_event_notifier_noflush(void)
     event_notifier_cleanup(&data.e);
 }
 
+#if !defined(_WIN32)
+
 static void test_timer_schedule(void)
 {
     TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
@@ -484,6 +490,8 @@ static void test_timer_schedule(void)
     timer_del(&data.timer);
 }
 
+#endif /* !_WIN32 */
+
 /* Now the same tests, using the context as a GSource.  They are
  * very similar to the ones above, with g_main_context_iteration
  * replacing aio_poll.  However:
@@ -766,6 +774,8 @@ static void test_source_wait_event_notifier_noflush(void)
     event_notifier_cleanup(&data.e);
 }
 
+#if !defined(_WIN32)
+
 static void test_source_timer_schedule(void)
 {
     TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
@@ -815,6 +825,8 @@ static void test_source_timer_schedule(void)
     timer_del(&data.timer);
 }
 
+#endif /* !_WIN32 */
+
 
 /* End of tests.  */
 
@@ -845,7 +857,9 @@ int main(int argc, char **argv)
     g_test_add_func("/aio/event/wait",              test_wait_event_notifier);
     g_test_add_func("/aio/event/wait/no-flush-cb",  test_wait_event_notifier_noflush);
     g_test_add_func("/aio/event/flush",             test_flush_event_notifier);
+#if !defined(_WIN32)
     g_test_add_func("/aio/timer/schedule",          test_timer_schedule);
+#endif
 
     g_test_add_func("/aio-gsource/notify",                  test_source_notify);
     g_test_add_func("/aio-gsource/flush",                   test_source_flush);
@@ -860,6 +874,8 @@ int main(int argc, char **argv)
     g_test_add_func("/aio-gsource/event/wait",              test_source_wait_event_notifier);
     g_test_add_func("/aio-gsource/event/wait/no-flush-cb",  test_source_wait_event_notifier_noflush);
     g_test_add_func("/aio-gsource/event/flush",             test_source_flush_event_notifier);
+#if !defined(_WIN32)
     g_test_add_func("/aio-gsource/timer/schedule",          test_source_timer_schedule);
+#endif
     return g_test_run();
 }
commit d766825190615bc0b1b57d2837475cdec1a075de
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 27 15:09:50 2014 +0100

    qtest: Keep list of qtest instances for SIGABRT handler
    
    Keep track of active qtest instances so we can kill them when the test
    aborts.  This ensures no QEMU processes are left running after test
    failure.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/libqtest.c b/tests/libqtest.c
index 2b90e4a..d9e3a33 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -48,6 +48,9 @@ struct QTestState
     struct sigaction sigact_old; /* restored on exit */
 };
 
+static GList *qtest_instances;
+static struct sigaction sigact_old;
+
 #define g_assert_no_errno(ret) do { \
     g_assert_cmpint(ret, !=, -1); \
 } while (0)
@@ -104,7 +107,28 @@ static void kill_qemu(QTestState *s)
 
 static void sigabrt_handler(int signo)
 {
-    kill_qemu(global_qtest);
+    GList *elem;
+    for (elem = qtest_instances; elem; elem = elem->next) {
+        kill_qemu(elem->data);
+    }
+}
+
+static void setup_sigabrt_handler(void)
+{
+    struct sigaction sigact;
+
+    /* Catch SIGABRT to clean up on g_assert() failure */
+    sigact = (struct sigaction){
+        .sa_handler = sigabrt_handler,
+        .sa_flags = SA_RESETHAND,
+    };
+    sigemptyset(&sigact.sa_mask);
+    sigaction(SIGABRT, &sigact, &sigact_old);
+}
+
+static void cleanup_sigabrt_handler(void)
+{
+    sigaction(SIGABRT, &sigact_old, NULL);
 }
 
 QTestState *qtest_init(const char *extra_args)
@@ -115,7 +139,6 @@ QTestState *qtest_init(const char *extra_args)
     gchar *qmp_socket_path;
     gchar *command;
     const char *qemu_binary;
-    struct sigaction sigact;
 
     qemu_binary = getenv("QTEST_QEMU_BINARY");
     g_assert(qemu_binary != NULL);
@@ -128,13 +151,12 @@ QTestState *qtest_init(const char *extra_args)
     sock = init_socket(socket_path);
     qmpsock = init_socket(qmp_socket_path);
 
-    /* Catch SIGABRT to clean up on g_assert() failure */
-    sigact = (struct sigaction){
-        .sa_handler = sigabrt_handler,
-        .sa_flags = SA_RESETHAND,
-    };
-    sigemptyset(&sigact.sa_mask);
-    sigaction(SIGABRT, &sigact, &s->sigact_old);
+    /* Only install SIGABRT handler once */
+    if (!qtest_instances) {
+        setup_sigabrt_handler();
+    }
+
+    qtest_instances = g_list_prepend(qtest_instances, s);
 
     s->qemu_pid = fork();
     if (s->qemu_pid == 0) {
@@ -180,7 +202,12 @@ QTestState *qtest_init(const char *extra_args)
 
 void qtest_quit(QTestState *s)
 {
-    sigaction(SIGABRT, &s->sigact_old, NULL);
+    /* Uninstall SIGABRT handler on last instance */
+    if (qtest_instances && !qtest_instances->next) {
+        cleanup_sigabrt_handler();
+    }
+
+    qtest_instances = g_list_remove(qtest_instances, s);
 
     kill_qemu(s);
     close(s->fd);
commit 96b8ca47f8f21ba32a60930cddbf5da27d36b20d
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 27 15:09:49 2014 +0100

    Revert "qtest: Fix crash if SIGABRT during qtest_init()"
    
    It turns out there are test cases that use multiple libqtest instances.
    We cannot use a global qtest instance in the SIGABRT handler.
    
    This reverts commit cb201b4872f16dfbce63f8648b2584631e2e965f.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Marcel Apfelbaum <marcel.a at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/tests/libqtest.c b/tests/libqtest.c
index b03b57a..2b90e4a 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -120,7 +120,7 @@ QTestState *qtest_init(const char *extra_args)
     qemu_binary = getenv("QTEST_QEMU_BINARY");
     g_assert(qemu_binary != NULL);
 
-    global_qtest = s = g_malloc(sizeof(*s));
+    s = g_malloc(sizeof(*s));
 
     socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
     qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
@@ -181,7 +181,6 @@ QTestState *qtest_init(const char *extra_args)
 void qtest_quit(QTestState *s)
 {
     sigaction(SIGABRT, &s->sigact_old, NULL);
-    global_qtest = NULL;
 
     kill_qemu(s);
     close(s->fd);
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 27a58fd..8268c09 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -335,7 +335,8 @@ void qtest_add_func(const char *str, void (*fn));
  */
 static inline QTestState *qtest_start(const char *args)
 {
-    return qtest_init(args);
+    global_qtest = qtest_init(args);
+    return global_qtest;
 }
 
 /**
@@ -346,6 +347,7 @@ static inline QTestState *qtest_start(const char *args)
 static inline void qtest_end(void)
 {
     qtest_quit(global_qtest);
+    global_qtest = NULL;
 }
 
 /**


More information about the Spice-commits mailing list