All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: anthony@codemonkey.ws
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 02/11] QCOW2: bug fix - read base image beyond its size
Date: Thu, 10 Feb 2011 16:51:17 +0100	[thread overview]
Message-ID: <1297353086-4844-3-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1297353086-4844-1-git-send-email-kwolf@redhat.com>

From: Chunqiang Tang <ctang@us.ibm.com>

This patch fixes the following bug in QCOW2. For a QCOW2 image that is larger
than its base image, when handling a read request straddling over the end of the
base image, the QCOW2 driver attempts to read beyond the end of the base image
and the request would fail.

This bug was found by Fast Virtual Disk (FVD)'s fully automated testing tool.
The following test triggered the bug.

dd if=/dev/zero of=/var/ramdisk/truth.raw count=0 bs=1 seek=1098561536
dd if=/dev/zero of=/var/ramdisk/zero-500M.raw count=0 bs=1 seek=593099264
./qemu-img create -f qcow2 -ocluster_size=65536,backing_fmt=blksim -b /var/ramdisk/zero-500M.raw /var/ramdisk/test.qcow2 1098561536
./qemu-io --auto --seed=30477694 --truth=/var/ramdisk/truth.raw --format=qcow2 --test=blksim:/var/ramdisk/test.qcow2 --verify_write=true --compare_before=false --compare_after=true --round=100000 --parallel=100 --io_size=10485760 --fail_prob=0 --cancel_prob=0 --instant_qemubh=true

Signed-off-by: Chunqiang Tang <ctang@us.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2.c |    5 ++---
 cutils.c      |   31 +++++++++++++++++++++++++++++++
 qemu-common.h |    2 ++
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index a1773e4..28338bf 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -355,7 +355,7 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
     else
         n1 = bs->total_sectors - sector_num;
 
-    qemu_iovec_memset(qiov, 0, 512 * (nb_sectors - n1));
+    qemu_iovec_memset_skip(qiov, 0, 512 * (nb_sectors - n1), 512 * n1);
 
     return n1;
 }
@@ -478,8 +478,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
             if (n1 > 0) {
                 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
                 acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
-                                    &acb->hd_qiov, acb->cur_nr_sectors,
-				    qcow2_aio_read_cb, acb);
+                                    &acb->hd_qiov, n1, qcow2_aio_read_cb, acb);
                 if (acb->hd_aiocb == NULL)
                     goto done;
             } else {
diff --git a/cutils.c b/cutils.c
index 8d562b2..f9a7e36 100644
--- a/cutils.c
+++ b/cutils.c
@@ -267,6 +267,37 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count)
     }
 }
 
+void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
+                            size_t skip)
+{
+    int i;
+    size_t done;
+    void *iov_base;
+    uint64_t iov_len;
+
+    done = 0;
+    for (i = 0; (i < qiov->niov) && (done != count); i++) {
+        if (skip >= qiov->iov[i].iov_len) {
+            /* Skip the whole iov */
+            skip -= qiov->iov[i].iov_len;
+            continue;
+        } else {
+            /* Skip only part (or nothing) of the iov */
+            iov_base = (uint8_t*) qiov->iov[i].iov_base + skip;
+            iov_len = qiov->iov[i].iov_len - skip;
+            skip = 0;
+        }
+
+        if (done + iov_len > count) {
+            memset(iov_base, c, count - done);
+            break;
+        } else {
+            memset(iov_base, c, iov_len);
+        }
+        done += iov_len;
+    }
+}
+
 #ifndef _WIN32
 /* Sets a specific flag */
 int fcntl_setfl(int fd, int flag)
diff --git a/qemu-common.h b/qemu-common.h
index c7ff280..cb4b7e0 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -322,6 +322,8 @@ void qemu_iovec_reset(QEMUIOVector *qiov);
 void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf);
 void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
 void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
+void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
+                            size_t skip);
 
 struct Monitor;
 typedef struct Monitor Monitor;
-- 
1.7.2.3

  parent reply	other threads:[~2011-02-10 15:49 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-10 15:51 [Qemu-devel] [PULL 00/11] Block patches for master Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 01/11] Change snapshot_blkdev hmp to use correct argument type for device Kevin Wolf
2011-02-10 15:51 ` Kevin Wolf [this message]
2011-02-10 15:51 ` [Qemu-devel] [PATCH 03/11] qcow2: Fix error handling for immediate backing file read failure Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 04/11] qcow2: Fix error handling for reading compressed clusters Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 05/11] qerror: Add QERR_UNKNOWN_BLOCK_FORMAT_FEATURE Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 06/11] qcow2: Report error for version > 2 Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 07/11] qed: Report error for unsupported features Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 08/11] qemu-img: Improve error messages for failed bdrv_open Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 09/11] blockdev: Plug memory leak in drive_uninit() Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 10/11] blockdev: Plug memory leak in drive_init() error paths Kevin Wolf
2011-02-10 15:51 ` [Qemu-devel] [PATCH 11/11] qcow2: Fix order in L2 table COW Kevin Wolf
2011-02-14 20:17 ` [Qemu-devel] [PULL 00/11] Block patches for master Anthony Liguori
2011-02-16 11:30   ` Kevin Wolf
2011-02-16 12:00     ` [Qemu-devel] " Paolo Bonzini
2011-02-16 14:47       ` Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1297353086-4844-3-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.