From: Fam Zheng <famz@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
"Ronnie Sahlberg" <ronniesahlberg@gmail.com>,
qemu-block@nongnu.org, "Peter Lieven" <pl@kamp.de>,
"Fam Zheng" <famz@redhat.com>, "Kevin Wolf" <kwolf@redhat.com>,
"Max Reitz" <mreitz@redhat.com>,
"Stefan Hajnoczi" <stefanha@redhat.com>,
"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
"Alex Bennée" <alex.bennee@linaro.org>,
eblake@redhat.com
Subject: [Qemu-devel] [PATCH v9 02/10] raw: Check byte range uniformly
Date: Fri, 1 Jun 2018 17:26:40 +0800 [thread overview]
Message-ID: <20180601092648.24614-3-famz@redhat.com> (raw)
In-Reply-To: <20180601092648.24614-1-famz@redhat.com>
We don't verify the request range against s->size in the I/O callbacks
except for raw_co_pwritev. This is inconsistent (especially for
raw_co_pwrite_zeroes and raw_co_pdiscard), so fix them, in the meanwhile
make the helper reusable by the coming new callbacks.
Note that in most cases the block layer already verifies the request
byte range against our reported image length, before invoking the driver
callbacks. The exception is during image creating, after
blk_set_allow_write_beyond_eof(blk, true) is called. But in that case,
the requests are not directly from the user or guest. So there is no
visible behavior change in adding the check code.
The int64_t -> uint64_t inconsistency, as shown by the type casting, is
pre-existing due to the interface.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
---
block/raw-format.c | 64 ++++++++++++++++++++++++++++------------------
1 file changed, 39 insertions(+), 25 deletions(-)
diff --git a/block/raw-format.c b/block/raw-format.c
index fe33693a2d..b69a0674b3 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -167,16 +167,37 @@ static void raw_reopen_abort(BDRVReopenState *state)
state->opaque = NULL;
}
+/* Check and adjust the offset, against 'offset' and 'size' options. */
+static inline int raw_adjust_offset(BlockDriverState *bs, uint64_t *offset,
+ uint64_t bytes, bool is_write)
+{
+ BDRVRawState *s = bs->opaque;
+
+ if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) {
+ /* There's not enough space for the write, or the read request is
+ * out-of-range. Don't read/write anything to prevent leaking out of
+ * the size specified in options. */
+ return is_write ? -ENOSPC : -EINVAL;;
+ }
+
+ if (*offset > INT64_MAX - s->offset) {
+ return -EINVAL;
+ }
+ *offset += s->offset;
+
+ return 0;
+}
+
static int coroutine_fn raw_co_preadv(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov,
int flags)
{
- BDRVRawState *s = bs->opaque;
+ int ret;
- if (offset > UINT64_MAX - s->offset) {
- return -EINVAL;
+ ret = raw_adjust_offset(bs, &offset, bytes, false);
+ if (ret) {
+ return ret;
}
- offset += s->offset;
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
@@ -186,23 +207,11 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov,
int flags)
{
- BDRVRawState *s = bs->opaque;
void *buf = NULL;
BlockDriver *drv;
QEMUIOVector local_qiov;
int ret;
- if (s->has_size && (offset > s->size || bytes > (s->size - offset))) {
- /* There's not enough space for the data. Don't write anything and just
- * fail to prevent leaking out of the size specified in options. */
- return -ENOSPC;
- }
-
- if (offset > UINT64_MAX - s->offset) {
- ret = -EINVAL;
- goto fail;
- }
-
if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
/* Handling partial writes would be a pain - so we just
* require that guests have 512-byte request alignment if
@@ -237,7 +246,10 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset,
qiov = &local_qiov;
}
- offset += s->offset;
+ ret = raw_adjust_offset(bs, &offset, bytes, true);
+ if (ret) {
+ goto fail;
+ }
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
@@ -267,22 +279,24 @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
int64_t offset, int bytes,
BdrvRequestFlags flags)
{
- BDRVRawState *s = bs->opaque;
- if (offset > UINT64_MAX - s->offset) {
- return -EINVAL;
+ int ret;
+
+ ret = raw_adjust_offset(bs, (uint64_t *)&offset, bytes, true);
+ if (ret) {
+ return ret;
}
- offset += s->offset;
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
}
static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
int64_t offset, int bytes)
{
- BDRVRawState *s = bs->opaque;
- if (offset > UINT64_MAX - s->offset) {
- return -EINVAL;
+ int ret;
+
+ ret = raw_adjust_offset(bs, (uint64_t *)&offset, bytes, true);
+ if (ret) {
+ return ret;
}
- offset += s->offset;
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
}
--
2.17.0
next prev parent reply other threads:[~2018-06-01 9:27 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-01 9:26 [Qemu-devel] [PATCH v9 00/10] qemu-img convert with copy offloading Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 01/10] block: Introduce API for " Fam Zheng
2018-06-01 9:26 ` Fam Zheng [this message]
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 03/10] raw: Implement " Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 04/10] qcow2: " Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 05/10] file-posix: Implement bdrv_co_copy_range Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 06/10] iscsi: Query and save device designator when opening Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 07/10] iscsi: Create and use iscsi_co_wait_for_task Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 08/10] iscsi: Implement copy offloading Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 09/10] block-backend: Add blk_co_copy_range Fam Zheng
2018-06-01 9:26 ` [Qemu-devel] [PATCH v9 10/10] qemu-img: Convert with copy offloading Fam Zheng
2018-06-04 9:28 ` [Qemu-devel] [Qemu-block] [PATCH v9 00/10] qemu-img convert " 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=20180601092648.24614-3-famz@redhat.com \
--to=famz@redhat.com \
--cc=alex.bennee@linaro.org \
--cc=eblake@redhat.com \
--cc=f4bug@amsat.org \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=pbonzini@redhat.com \
--cc=pl@kamp.de \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=ronniesahlberg@gmail.com \
--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).