From: Max Reitz <mreitz@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
Max Reitz <mreitz@redhat.com>
Subject: [Qemu-devel] [PATCH v4 14/16] block: Clamp BlockBackend requests
Date: Thu, 5 Feb 2015 13:58:23 -0500 [thread overview]
Message-ID: <1423162705-32065-15-git-send-email-mreitz@redhat.com> (raw)
In-Reply-To: <1423162705-32065-1-git-send-email-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>
---
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
next prev parent reply other threads:[~2015-02-05 18:58 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-05 18:58 [Qemu-devel] [PATCH v4 00/16] block: Remove "growable", add blk_new_open() Max Reitz
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 01/16] block: Lift some BDS functions to the BlockBackend Max Reitz
2015-02-05 19:52 ` Eric Blake
2015-02-13 11:34 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 02/16] block: Add blk_new_open() Max Reitz
2015-02-13 11:36 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 03/16] block: Add Error parameter to bdrv_find_protocol() Max Reitz
2015-02-05 20:15 ` Eric Blake
2015-02-13 12:58 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 04/16] iotests: Add test for driver=qcow2, format=qcow2 Max Reitz
2015-02-05 20:17 ` Eric Blake
2015-02-13 12:59 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 05/16] blockdev: Use blk_new_open() in blockdev_init() Max Reitz
2015-02-05 20:23 ` Eric Blake
2015-02-13 13:01 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 06/16] block/xen: Use blk_new_open() in blk_connect() Max Reitz
2015-02-05 20:42 ` Eric Blake
2015-02-13 13:04 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 07/16] qemu-img: Use blk_new_open() in img_open() Max Reitz
2015-02-05 20:43 ` Eric Blake
2015-02-13 13:20 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 08/16] qemu-img: Use blk_new_open() in img_rebase() Max Reitz
2015-02-05 20:47 ` Eric Blake
2015-02-13 13:21 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 09/16] qemu-img: Use BlockBackend as far as possible Max Reitz
2015-02-05 21:03 ` Eric Blake
2015-02-13 13:22 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 10/16] qemu-nbd: Use blk_new_open() in main() Max Reitz
2015-02-13 13:23 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 11/16] qemu-io: Use blk_new_open() in openfile() Max Reitz
2015-02-05 21:10 ` Eric Blake
2015-02-13 13:25 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 12/16] qemu-io: Remove "growable" option Max Reitz
2015-02-05 21:15 ` Eric Blake
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 13/16] qemu-io: Use BlockBackend Max Reitz
2015-02-05 21:56 ` Eric Blake
2015-02-05 18:58 ` Max Reitz [this message]
2015-02-13 14:14 ` [Qemu-devel] [PATCH v4 14/16] block: Clamp BlockBackend requests Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 15/16] block: Remove "growable" from BDS Max Reitz
2015-02-05 22:05 ` Eric Blake
2015-02-13 14:15 ` Stefan Hajnoczi
2015-02-05 18:58 ` [Qemu-devel] [PATCH v4 16/16] block: Keep bdrv_check*_request()'s return value Max Reitz
2015-02-13 14:16 ` Stefan Hajnoczi
2015-02-13 16:47 ` [Qemu-devel] [PATCH v4 00/16] block: Remove "growable", add blk_new_open() 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=1423162705-32065-15-git-send-email-mreitz@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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).