aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tschoke <lukts330@gmail.com>2023-04-08 00:11:38 +0200
committerMichael Tokarev <mjt@tls.msk.ru>2023-04-13 18:31:39 +0300
commit2e0e234272a65930743fe4580a500b6bf6782529 (patch)
tree8de2793b284a36a7cc3390c7626e2096f71753ef
parentc22120835295f2bbb7d101f1fa60abb70029be85 (diff)
block/vhdx: fix dynamic VHDX BAT corruption
The corruption occurs when a BAT entry aligned to 4096 bytes is changed. Specifically, the corruption occurs during the creation of the LOG Data Descriptor. The incorrect behavior involves copying 4088 bytes from the original 4096 bytes aligned offset to `tmp[8..4096]` and then copying the new value for the first BAT entry to the beginning `tmp[0..8]`. This results in all existing BAT entries inside the 4K region being incorrectly moved by 8 bytes and the last entry being lost. This bug did not cause noticeable corruption when only sequentially writing once to an empty dynamic VHDX (e.g. using `qemu-img convert -O vhdx -o subformat=dynamic ...`), but it still resulted in invalid values for the (unused) Sector Bitmap BAT entries. Importantly, this corruption would only become noticeable after the corrupted BAT is re-read from the file. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/727 Cc: qemu-stable@nongnu.org Signed-off-by: Lukas Tschoke <lukts330@gmail.com> Message-Id: <6cfb6d6b-adc5-7772-c8a5-6bae9a0ad668@gmail.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com> (cherry picked from commit 8af037fe4cfeb88bbcded3122cec2c5be0b90907) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--block/vhdx-log.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
index 572582b87b..0866897a85 100644
--- a/block/vhdx-log.c
+++ b/block/vhdx-log.c
@@ -980,7 +980,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
sector_write = merged_sector;
} else if (i == sectors - 1 && trailing_length) {
/* partial sector at the end of the buffer */
- ret = bdrv_pread(bs->file, file_offset,
+ ret = bdrv_pread(bs->file, file_offset + trailing_length,
VHDX_LOG_SECTOR_SIZE - trailing_length,
merged_sector + trailing_length, 0);
if (ret < 0) {