Blame SOURCES/kvm-raw-Check-byte-range-uniformly.patch

357786
From f0714015bbe871d1f0c1fe9d8b8c7bd2afc2a0a0 Mon Sep 17 00:00:00 2001
357786
From: Fam Zheng <famz@redhat.com>
357786
Date: Fri, 29 Jun 2018 06:11:42 +0200
357786
Subject: [PATCH 38/57] raw: Check byte range uniformly
357786
357786
RH-Author: Fam Zheng <famz@redhat.com>
357786
Message-id: <20180629061153.12687-3-famz@redhat.com>
357786
Patchwork-id: 81152
357786
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH v2 02/13] raw: Check byte range uniformly
357786
Bugzilla: 1482537
357786
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
357786
RH-Acked-by: Max Reitz <mreitz@redhat.com>
357786
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
357786
357786
We don't verify the request range against s->size in the I/O callbacks
357786
except for raw_co_pwritev. This is inconsistent (especially for
357786
raw_co_pwrite_zeroes and raw_co_pdiscard), so fix them, in the meanwhile
357786
make the helper reusable by the coming new callbacks.
357786
357786
Note that in most cases the block layer already verifies the request
357786
byte range against our reported image length, before invoking the driver
357786
callbacks.  The exception is during image creating, after
357786
blk_set_allow_write_beyond_eof(blk, true) is called. But in that case,
357786
the requests are not directly from the user or guest. So there is no
357786
visible behavior change in adding the check code.
357786
357786
The int64_t -> uint64_t inconsistency, as shown by the type casting, is
357786
pre-existing due to the interface.
357786
357786
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
357786
Reviewed-by: Eric Blake <eblake@redhat.com>
357786
Signed-off-by: Fam Zheng <famz@redhat.com>
357786
Message-id: 20180601092648.24614-3-famz@redhat.com
357786
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
357786
(cherry picked from commit 384455385248762e74a080978f18f0c8f74757fe)
357786
Signed-off-by: Fam Zheng <famz@redhat.com>
357786
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
357786
---
357786
 block/raw-format.c | 64 +++++++++++++++++++++++++++++++++---------------------
357786
 1 file changed, 39 insertions(+), 25 deletions(-)
357786
357786
diff --git a/block/raw-format.c b/block/raw-format.c
357786
index fe33693..b69a067 100644
357786
--- a/block/raw-format.c
357786
+++ b/block/raw-format.c
357786
@@ -167,16 +167,37 @@ static void raw_reopen_abort(BDRVReopenState *state)
357786
     state->opaque = NULL;
357786
 }
357786
 
357786
+/* Check and adjust the offset, against 'offset' and 'size' options. */
357786
+static inline int raw_adjust_offset(BlockDriverState *bs, uint64_t *offset,
357786
+                                    uint64_t bytes, bool is_write)
357786
+{
357786
+    BDRVRawState *s = bs->opaque;
357786
+
357786
+    if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) {
357786
+        /* There's not enough space for the write, or the read request is
357786
+         * out-of-range. Don't read/write anything to prevent leaking out of
357786
+         * the size specified in options. */
357786
+        return is_write ? -ENOSPC : -EINVAL;;
357786
+    }
357786
+
357786
+    if (*offset > INT64_MAX - s->offset) {
357786
+        return -EINVAL;
357786
+    }
357786
+    *offset += s->offset;
357786
+
357786
+    return 0;
357786
+}
357786
+
357786
 static int coroutine_fn raw_co_preadv(BlockDriverState *bs, uint64_t offset,
357786
                                       uint64_t bytes, QEMUIOVector *qiov,
357786
                                       int flags)
357786
 {
357786
-    BDRVRawState *s = bs->opaque;
357786
+    int ret;
357786
 
357786
-    if (offset > UINT64_MAX - s->offset) {
357786
-        return -EINVAL;
357786
+    ret = raw_adjust_offset(bs, &offset, bytes, false);
357786
+    if (ret) {
357786
+        return ret;
357786
     }
357786
-    offset += s->offset;
357786
 
357786
     BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
357786
     return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
357786
@@ -186,23 +207,11 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset,
357786
                                        uint64_t bytes, QEMUIOVector *qiov,
357786
                                        int flags)
357786
 {
357786
-    BDRVRawState *s = bs->opaque;
357786
     void *buf = NULL;
357786
     BlockDriver *drv;
357786
     QEMUIOVector local_qiov;
357786
     int ret;
357786
 
357786
-    if (s->has_size && (offset > s->size || bytes > (s->size - offset))) {
357786
-        /* There's not enough space for the data. Don't write anything and just
357786
-         * fail to prevent leaking out of the size specified in options. */
357786
-        return -ENOSPC;
357786
-    }
357786
-
357786
-    if (offset > UINT64_MAX - s->offset) {
357786
-        ret = -EINVAL;
357786
-        goto fail;
357786
-    }
357786
-
357786
     if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) {
357786
         /* Handling partial writes would be a pain - so we just
357786
          * require that guests have 512-byte request alignment if
357786
@@ -237,7 +246,10 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset,
357786
         qiov = &local_qiov;
357786
     }
357786
 
357786
-    offset += s->offset;
357786
+    ret = raw_adjust_offset(bs, &offset, bytes, true);
357786
+    if (ret) {
357786
+        goto fail;
357786
+    }
357786
 
357786
     BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
357786
     ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
357786
@@ -267,22 +279,24 @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
357786
                                              int64_t offset, int bytes,
357786
                                              BdrvRequestFlags flags)
357786
 {
357786
-    BDRVRawState *s = bs->opaque;
357786
-    if (offset > UINT64_MAX - s->offset) {
357786
-        return -EINVAL;
357786
+    int ret;
357786
+
357786
+    ret = raw_adjust_offset(bs, (uint64_t *)&offset, bytes, true);
357786
+    if (ret) {
357786
+        return ret;
357786
     }
357786
-    offset += s->offset;
357786
     return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
357786
 }
357786
 
357786
 static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs,
357786
                                         int64_t offset, int bytes)
357786
 {
357786
-    BDRVRawState *s = bs->opaque;
357786
-    if (offset > UINT64_MAX - s->offset) {
357786
-        return -EINVAL;
357786
+    int ret;
357786
+
357786
+    ret = raw_adjust_offset(bs, (uint64_t *)&offset, bytes, true);
357786
+    if (ret) {
357786
+        return ret;
357786
     }
357786
-    offset += s->offset;
357786
     return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
357786
 }
357786
 
357786
-- 
357786
1.8.3.1
357786