[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH v2 4/7] vmdk: Reject invalid compressed writes
From: |
Max Reitz |
Subject: |
[Qemu-block] [PATCH v2 4/7] vmdk: Reject invalid compressed writes |
Date: |
Thu, 15 Aug 2019 17:36:35 +0200 |
Compressed writes generally have to write full clusters, not just in
theory but also in practice when it comes to vmdk's streamOptimized
subformat. It currently is just silently broken for writes with
non-zero in-cluster offsets:
$ qemu-img create -f vmdk -o subformat=streamOptimized foo.vmdk 1M
$ qemu-io -c 'write 4k 4k' -c 'read 4k 4k' foo.vmdk
wrote 4096/4096 bytes at offset 4096
4 KiB, 1 ops; 00.01 sec (443.724 KiB/sec and 110.9309 ops/sec)
read failed: Invalid argument
(The technical reason is that vmdk_write_extent() just writes the
incomplete compressed data actually to offset 4k. When reading the
data, vmdk_read_extent() looks at offset 0 and finds the compressed data
size to be 0, because that is what it reads from there. This yields an
error.)
For incomplete writes with zero in-cluster offsets, the error path when
reading the rest of the cluster is a bit different, but the result is
the same:
$ qemu-img create -f vmdk -o subformat=streamOptimized foo.vmdk 1M
$ qemu-io -c 'write 0k 4k' -c 'read 4k 4k' foo.vmdk
wrote 4096/4096 bytes at offset 0
4 KiB, 1 ops; 00.01 sec (362.641 KiB/sec and 90.6603 ops/sec)
read failed: Invalid argument
(Here, vmdk_read_extent() finds the data and then sees that the
uncompressed data is short.)
It is better to reject invalid writes than to make the user believe they
might have succeeded and then fail when trying to read it back.
Signed-off-by: Max Reitz <address@hidden>
Reviewed-by: John Snow <address@hidden>
---
block/vmdk.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/block/vmdk.c b/block/vmdk.c
index 825222de55..94a7021fcc 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1731,6 +1731,16 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t
cluster_offset,
if (extent->compressed) {
void *compressed_data;
+ /* Only whole clusters */
+ if (offset_in_cluster ||
+ n_bytes > (extent->cluster_sectors * SECTOR_SIZE) ||
+ (n_bytes < (extent->cluster_sectors * SECTOR_SIZE) &&
+ offset + n_bytes != extent->end_sector * SECTOR_SIZE))
+ {
+ ret = -EINVAL;
+ goto out;
+ }
+
if (!extent->has_marker) {
ret = -EINVAL;
goto out;
--
2.21.0
- [Qemu-block] [PATCH v2 0/7] vmdk: Misc fixes, Max Reitz, 2019/08/15
- [Qemu-block] [PATCH v2 1/7] iotests: Fix _filter_img_create(), Max Reitz, 2019/08/15
- [Qemu-block] [PATCH v2 2/7] vmdk: Use bdrv_dirname() for relative extent paths, Max Reitz, 2019/08/15
- [Qemu-block] [PATCH v2 3/7] iotests: Keep testing broken relative extent paths, Max Reitz, 2019/08/15
- [Qemu-block] [PATCH v2 5/7] iotests: Disable broken streamOptimized tests, Max Reitz, 2019/08/15
- [Qemu-block] [PATCH v2 4/7] vmdk: Reject invalid compressed writes,
Max Reitz <=
- [Qemu-block] [PATCH v2 6/7] iotests: Disable 110 for vmdk.twoGbMaxExtentSparse, Max Reitz, 2019/08/15
- [Qemu-block] [PATCH v2 7/7] iotests: Disable 126 for flat vmdk subformats, Max Reitz, 2019/08/15
- Re: [Qemu-block] [Qemu-devel] [PATCH v2 0/7] vmdk: Misc fixes, John Snow, 2019/08/15
- Re: [Qemu-block] [PATCH v2 0/7] vmdk: Misc fixes, Max Reitz, 2019/08/27