From 63f4ad1186b7bdf562193ee79a1f5d7f51343776 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 11 Dec 2020 21:39:25 +0300 Subject: block/io: improve bdrv_check_request: check qiov too Operations with qiov add more restrictions on bytes, let's cover it. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20201211183934.169161-8-vsementsov@virtuozzo.com> Reviewed-by: Eric Blake Signed-off-by: Eric Blake --- block/io.c | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index 39d943c33a..b56db913da 100644 --- a/block/io.c +++ b/block/io.c @@ -920,8 +920,14 @@ bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, return waited; } -int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp) +static int bdrv_check_qiov_request(int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset, + Error **errp) { + /* + * Check generic offset/bytes correctness + */ + if (offset < 0) { error_setg(errp, "offset is negative: %" PRIi64, offset); return -EIO; @@ -951,12 +957,38 @@ int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp) return -EIO; } + if (!qiov) { + return 0; + } + + /* + * Check qiov and qiov_offset + */ + + if (qiov_offset > qiov->size) { + error_setg(errp, "qiov_offset(%zu) overflow io vector size(%zu)", + qiov_offset, qiov->size); + return -EIO; + } + + if (bytes > qiov->size - qiov_offset) { + error_setg(errp, "bytes(%" PRIi64 ") + qiov_offset(%zu) overflow io " + "vector size(%zu)", bytes, qiov_offset, qiov->size); + return -EIO; + } + return 0; } -static int bdrv_check_request32(int64_t offset, int64_t bytes) +int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp) +{ + return bdrv_check_qiov_request(offset, bytes, NULL, 0, errp); +} + +static int bdrv_check_request32(int64_t offset, int64_t bytes, + QEMUIOVector *qiov, size_t qiov_offset) { - int ret = bdrv_check_request(offset, bytes, NULL); + int ret = bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, NULL); if (ret < 0) { return ret; } @@ -1736,7 +1768,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, return -ENOMEDIUM; } - ret = bdrv_check_request32(offset, bytes); + ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset); if (ret < 0) { return ret; } @@ -2157,7 +2189,7 @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child, return -ENOMEDIUM; } - ret = bdrv_check_request32(offset, bytes); + ret = bdrv_check_request32(offset, bytes, qiov, qiov_offset); if (ret < 0) { return ret; } @@ -3163,7 +3195,7 @@ static int coroutine_fn bdrv_co_copy_range_internal( if (!dst || !dst->bs || !bdrv_is_inserted(dst->bs)) { return -ENOMEDIUM; } - ret = bdrv_check_request32(dst_offset, bytes); + ret = bdrv_check_request32(dst_offset, bytes, NULL, 0); if (ret) { return ret; } @@ -3174,7 +3206,7 @@ static int coroutine_fn bdrv_co_copy_range_internal( if (!src || !src->bs || !bdrv_is_inserted(src->bs)) { return -ENOMEDIUM; } - ret = bdrv_check_request32(src_offset, bytes); + ret = bdrv_check_request32(src_offset, bytes, NULL, 0); if (ret) { return ret; } -- cgit v1.2.3-55-g7522