qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Max Reitz <mreitz@redhat.com>
Subject: [Qemu-devel] [PULL 63/65] block: Clamp BlockBackend requests
Date: Fri, 13 Feb 2015 16:24:59 +0000	[thread overview]
Message-ID: <1423844701-21041-64-git-send-email-stefanha@redhat.com> (raw)
In-Reply-To: <1423844701-21041-1-git-send-email-stefanha@redhat.com>

From: Max Reitz <mreitz@redhat.com>

BlockBackend is used as the interface between the block layer and guest
devices. It should therefore assure that all requests are clamped to the
image size.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1423162705-32065-15-git-send-email-mreitz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/block-backend.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/block/block-backend.c b/block/block-backend.c
index d083b85..aabe569 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -31,6 +31,16 @@ struct BlockBackend {
     void *dev_opaque;
 };
 
+typedef struct BlockBackendAIOCB {
+    BlockAIOCB common;
+    QEMUBH *bh;
+    int ret;
+} BlockBackendAIOCB;
+
+static const AIOCBInfo block_backend_aiocb_info = {
+    .aiocb_size = sizeof(BlockBackendAIOCB),
+};
+
 static void drive_info_del(DriveInfo *dinfo);
 
 /* All the BlockBackends (except for hidden ones) */
@@ -428,39 +438,137 @@ void blk_iostatus_enable(BlockBackend *blk)
     bdrv_iostatus_enable(blk->bs);
 }
 
+static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
+                                  size_t size)
+{
+    int64_t len;
+
+    if (size > INT_MAX) {
+        return -EIO;
+    }
+
+    if (!blk_is_inserted(blk)) {
+        return -ENOMEDIUM;
+    }
+
+    len = blk_getlength(blk);
+    if (len < 0) {
+        return len;
+    }
+
+    if (offset < 0) {
+        return -EIO;
+    }
+
+    if (offset > len || len - offset < size) {
+        return -EIO;
+    }
+
+    return 0;
+}
+
+static int blk_check_request(BlockBackend *blk, int64_t sector_num,
+                             int nb_sectors)
+{
+    if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
+        return -EIO;
+    }
+
+    if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
+        return -EIO;
+    }
+
+    return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
+                                  nb_sectors * BDRV_SECTOR_SIZE);
+}
+
 int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
              int nb_sectors)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_read(blk->bs, sector_num, buf, nb_sectors);
 }
 
 int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
                          int nb_sectors)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_read_unthrottled(blk->bs, sector_num, buf, nb_sectors);
 }
 
 int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf,
               int nb_sectors)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_write(blk->bs, sector_num, buf, nb_sectors);
 }
 
+static void error_callback_bh(void *opaque)
+{
+    struct BlockBackendAIOCB *acb = opaque;
+    qemu_bh_delete(acb->bh);
+    acb->common.cb(acb->common.opaque, acb->ret);
+    qemu_aio_unref(acb);
+}
+
+static BlockAIOCB *abort_aio_request(BlockBackend *blk, BlockCompletionFunc *cb,
+                                     void *opaque, int ret)
+{
+    struct BlockBackendAIOCB *acb;
+    QEMUBH *bh;
+
+    acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
+    acb->ret = ret;
+
+    bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb);
+    acb->bh = bh;
+    qemu_bh_schedule(bh);
+
+    return &acb->common;
+}
+
 BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num,
                                  int nb_sectors, BdrvRequestFlags flags,
                                  BlockCompletionFunc *cb, void *opaque)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return abort_aio_request(blk, cb, opaque, ret);
+    }
+
     return bdrv_aio_write_zeroes(blk->bs, sector_num, nb_sectors, flags,
                                  cb, opaque);
 }
 
 int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
 {
+    int ret = blk_check_byte_request(blk, offset, count);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_pread(blk->bs, offset, buf, count);
 }
 
 int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count)
 {
+    int ret = blk_check_byte_request(blk, offset, count);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_pwrite(blk->bs, offset, buf, count);
 }
 
@@ -483,6 +591,11 @@ BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num,
                           QEMUIOVector *iov, int nb_sectors,
                           BlockCompletionFunc *cb, void *opaque)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return abort_aio_request(blk, cb, opaque, ret);
+    }
+
     return bdrv_aio_readv(blk->bs, sector_num, iov, nb_sectors, cb, opaque);
 }
 
@@ -490,6 +603,11 @@ BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
                            QEMUIOVector *iov, int nb_sectors,
                            BlockCompletionFunc *cb, void *opaque)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return abort_aio_request(blk, cb, opaque, ret);
+    }
+
     return bdrv_aio_writev(blk->bs, sector_num, iov, nb_sectors, cb, opaque);
 }
 
@@ -503,6 +621,11 @@ BlockAIOCB *blk_aio_discard(BlockBackend *blk,
                             int64_t sector_num, int nb_sectors,
                             BlockCompletionFunc *cb, void *opaque)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return abort_aio_request(blk, cb, opaque, ret);
+    }
+
     return bdrv_aio_discard(blk->bs, sector_num, nb_sectors, cb, opaque);
 }
 
@@ -518,6 +641,15 @@ void blk_aio_cancel_async(BlockAIOCB *acb)
 
 int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs)
 {
+    int i, ret;
+
+    for (i = 0; i < num_reqs; i++) {
+        ret = blk_check_request(blk, reqs[i].sector, reqs[i].nb_sectors);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
     return bdrv_aio_multiwrite(blk->bs, reqs, num_reqs);
 }
 
@@ -534,6 +666,11 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
 
 int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_co_discard(blk->bs, sector_num, nb_sectors);
 }
 
@@ -711,12 +848,22 @@ void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
 int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t sector_num,
                                      int nb_sectors, BdrvRequestFlags flags)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_co_write_zeroes(blk->bs, sector_num, nb_sectors, flags);
 }
 
 int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_write_compressed(blk->bs, sector_num, buf, nb_sectors);
 }
 
@@ -727,6 +874,11 @@ int blk_truncate(BlockBackend *blk, int64_t offset)
 
 int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
 {
+    int ret = blk_check_request(blk, sector_num, nb_sectors);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_discard(blk->bs, sector_num, nb_sectors);
 }
 
-- 
2.1.0

  parent reply	other threads:[~2015-02-13 16:35 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-13 16:23 [Qemu-devel] [PULL 00/65] Block patches Stefan Hajnoczi
2015-02-13 16:23 ` [Qemu-devel] [PULL 01/65] nbd: Drop BDS backpointer Stefan Hajnoczi
2015-02-13 16:23 ` [Qemu-devel] [PULL 02/65] iotests: Add "wait" functionality to _cleanup_qemu Stefan Hajnoczi
2015-02-13 16:23 ` [Qemu-devel] [PULL 03/65] iotests: Add test for drive-mirror with NBD target Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 04/65] libqos: Split apart pc_alloc_init Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 05/65] qtest/ahci: Create ahci.h Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 06/65] libqos: create libqos.c Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 07/65] libqos: add qtest_vboot Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 08/65] libqos: add alloc_init_flags Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 09/65] libqos: Update QGuestAllocator to be opaque Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 10/65] libqos: add pc specific interface Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 11/65] qtest/ahci: Store hba_base in AHCIQState Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 12/65] qtest/ahci: finalize AHCIQState consolidation Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 13/65] qtest/ahci: remove pcibus global Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 14/65] qtest/ahci: remove guest_malloc global Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 15/65] libqos/ahci: Functional register helpers Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 16/65] qtest/ahci: remove getter/setter macros Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 17/65] qtest/ahci: Bookmark FB and CLB pointers Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 18/65] libqos/ahci: create libqos/ahci.c Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 19/65] dataplane: endianness-aware accesses Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 20/65] libqos/ahci: Add ahci_port_select helper Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 21/65] libqos/ahci: Add ahci_port_clear helper Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 22/65] qtest/ahci: rename 'Command' to 'CommandHeader' Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 23/65] libqos/ahci: Add command header helpers Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 24/65] libqos/ahci: Add ahci_port_check_error helper Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 25/65] libqos/ahci: Add ahci_port_check_interrupts helper Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 26/65] libqos/ahci: Add port_check_nonbusy helper Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 27/65] libqos/ahci: Add cmd response sanity check helpers Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 28/65] qtest/ahci: Demagic ahci tests Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 29/65] qtest/ahci: add ahci_write_fis Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 30/65] libqos/ahci: Add ide cmd properties Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 31/65] libqos/ahci: add ahci command functions Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 32/65] libqos/ahci: add ahci command verify Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 33/65] libqos/ahci: add ahci command size setters Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 34/65] libqos/ahci: Add ahci_guest_io Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 35/65] libqos/ahci: add ahci_io Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 36/65] libqos/ahci: Add ahci_clean_mem Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 37/65] qtest/ahci: Assert sector size in identify test Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 38/65] qtest/ahci: Adding simple dma read-write test Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 39/65] nbd: fix the co_queue multi-adding bug Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 40/65] savevm: Improve error message for blocked migration Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 41/65] block: vmdk - fixed sizeof() error Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 42/65] qtest: Fix deadloop by running main loop AIO context's timers Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 43/65] qemu-io: Account IO by aio_read and aio_write Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 44/65] qtest: Add scripts/qtest.py Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 45/65] qemu-iotests: Add VM method qtest() to iotests.py Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 46/65] qemu-iotests: Allow caller to disable underscore convertion for qmp Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 47/65] qemu-iotests: Add 093 for IO throttling Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 48/65] qemu-img: Fix qemu-img convert -n Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 49/65] iotests: Add test for qemu-img convert to NBD Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 50/65] block: Lift some BDS functions to the BlockBackend Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 51/65] block: Add blk_new_open() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 52/65] block: Add Error parameter to bdrv_find_protocol() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 53/65] iotests: Add test for driver=qcow2, format=qcow2 Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 54/65] blockdev: Use blk_new_open() in blockdev_init() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 55/65] block/xen: Use blk_new_open() in blk_connect() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 56/65] qemu-img: Use blk_new_open() in img_open() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 57/65] qemu-img: Use blk_new_open() in img_rebase() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 58/65] qemu-img: Use BlockBackend as far as possible Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 59/65] qemu-nbd: Use blk_new_open() in main() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 60/65] qemu-io: Use blk_new_open() in openfile() Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 61/65] qemu-io: Remove "growable" option Stefan Hajnoczi
2015-02-13 16:24 ` [Qemu-devel] [PULL 62/65] qemu-io: Use BlockBackend Stefan Hajnoczi
2015-02-13 16:24 ` Stefan Hajnoczi [this message]
2015-02-13 16:25 ` [Qemu-devel] [PULL 64/65] block: Remove "growable" from BDS Stefan Hajnoczi
2015-02-13 16:25 ` [Qemu-devel] [PULL 65/65] block: Keep bdrv_check*_request()'s return value Stefan Hajnoczi
2015-02-14  0:50 ` [Qemu-devel] [PULL 00/65] Block patches Peter Maydell
2015-02-16 14:12   ` Stefan Hajnoczi

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=1423844701-21041-64-git-send-email-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=peter.maydell@linaro.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).