From e191ab6358b656764374ff1b3c7224a744dc902a Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 26 Jan 2021 17:21:02 -0500 Subject: [PATCH 7/9] block: Require aligned image size to avoid assertion failure RH-Author: Kevin Wolf Message-id: <20210126172103.136060-2-kwolf@redhat.com> Patchwork-id: 100786 O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/2] block: Require aligned image size to avoid assertion failure Bugzilla: 1834281 RH-Acked-by: Markus Armbruster RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Max Reitz Unaligned requests will automatically be aligned to bl.request_alignment and we can't extend write requests to access space beyond the end of the image without resizing the image, so if we have the WRITE permission, but not the RESIZE one, it's required that the image size is aligned. Failing to meet this requirement could cause assertion failures like this if RESIZE permissions weren't requested: qemu-img: block/io.c:1910: bdrv_co_write_req_prepare: Assertion `end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE' failed. This was e.g. triggered by qemu-img converting to a target image with 4k request alignment when the image was only aligned to 512 bytes, but not to 4k. Turn this into a graceful error in bdrv_check_perm() so that WRITE without RESIZE can only be taken if the image size is aligned. If a user holds both permissions and drops only RESIZE, the function will return an error, but bdrv_child_try_set_perm() will ignore the failure silently if permissions are only requested to be relaxed and just keep both permissions while returning success. Signed-off-by: Kevin Wolf Message-Id: <20200716142601.111237-2-kwolf@redhat.com> Reviewed-by: Max Reitz Signed-off-by: Kevin Wolf (cherry picked from commit 9c60a5d1978e6dcf85c0e01b50e6f7f54ca09104) Signed-off-by: Kevin Wolf Signed-off-by: Jon Maloy --- block.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/block.c b/block.c index 57740d312e..e9579ddf84 100644 --- a/block.c +++ b/block.c @@ -2009,6 +2009,22 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q, return -EPERM; } + /* + * Unaligned requests will automatically be aligned to bl.request_alignment + * and without RESIZE we can't extend requests to write to space beyond the + * end of the image, so it's required that the image size is aligned. + */ + if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) && + !(cumulative_perms & BLK_PERM_RESIZE)) + { + if ((bs->total_sectors * BDRV_SECTOR_SIZE) % bs->bl.request_alignment) { + error_setg(errp, "Cannot get 'write' permission without 'resize': " + "Image size is not a multiple of request " + "alignment"); + return -EPERM; + } + } + /* Check this node */ if (!drv) { return 0; -- 2.18.2