From b570f1c41e40b6455ffb11dc2fb12a1d8205d00f Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Wed, 24 Jun 2020 16:21:39 +0200 Subject: [PATCH] Fix backup for not 64k-aligned storages Signed-off-by: Thomas Lamprecht Tested-by: Roland Kammerer --- ...estore-new-command-to-restore-from-p.patch | 2 +- ...ree-statements-to-prevent-memory-lea.patch | 44 ++++++++++ ...-backup-for-not-64k-aligned-storages.patch | 80 +++++++++++++++++++ debian/patches/series | 2 + 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 debian/patches/pve/0049-Add-some-qemu_vfree-statements-to-prevent-memory-lea.patch create mode 100644 debian/patches/pve/0050-Fix-backup-for-not-64k-aligned-storages.patch diff --git a/debian/patches/pve/0032-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch b/debian/patches/pve/0032-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch index f5868c7..2652bcf 100644 --- a/debian/patches/pve/0032-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch +++ b/debian/patches/pve/0032-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch @@ -35,7 +35,7 @@ index dbd9542ae4..7c1fb58e18 100644 diff --git a/pbs-restore.c b/pbs-restore.c new file mode 100644 -index 0000000000..fc881de560 +index 0000000000..4bf37ef1fa --- /dev/null +++ b/pbs-restore.c @@ -0,0 +1,217 @@ diff --git a/debian/patches/pve/0049-Add-some-qemu_vfree-statements-to-prevent-memory-lea.patch b/debian/patches/pve/0049-Add-some-qemu_vfree-statements-to-prevent-memory-lea.patch new file mode 100644 index 0000000..fcf46d2 --- /dev/null +++ b/debian/patches/pve/0049-Add-some-qemu_vfree-statements-to-prevent-memory-lea.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stefan Reiter +Date: Mon, 22 Jun 2020 14:54:00 +0200 +Subject: [PATCH] Add some qemu_vfree statements to prevent memory leaks + +Suggested-by: Lars Ellenberg +Signed-off-by: Stefan Reiter +--- + vma-writer.c | 2 ++ + vma.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/vma-writer.c b/vma-writer.c +index fe86b18a60..06cbc02b1e 100644 +--- a/vma-writer.c ++++ b/vma-writer.c +@@ -767,5 +767,7 @@ void vma_writer_destroy(VmaWriter *vmaw) + g_checksum_free(vmaw->md5csum); + } + ++ qemu_vfree(vmaw->headerbuf); ++ qemu_vfree(vmaw->outbuf); + g_free(vmaw); + } +diff --git a/vma.c b/vma.c +index a82752448a..2eea2fc281 100644 +--- a/vma.c ++++ b/vma.c +@@ -565,6 +565,7 @@ out: + g_warning("vma_writer_close failed %s", error_get_pretty(err)); + } + } ++ qemu_vfree(buf); + } + + static int create_archive(int argc, char **argv) +@@ -732,6 +733,7 @@ static int create_archive(int argc, char **argv) + g_error("creating vma archive failed"); + } + ++ vma_writer_destroy(vmaw); + return 0; + } + diff --git a/debian/patches/pve/0050-Fix-backup-for-not-64k-aligned-storages.patch b/debian/patches/pve/0050-Fix-backup-for-not-64k-aligned-storages.patch new file mode 100644 index 0000000..c09b709 --- /dev/null +++ b/debian/patches/pve/0050-Fix-backup-for-not-64k-aligned-storages.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stefan Reiter +Date: Mon, 22 Jun 2020 14:54:02 +0200 +Subject: [PATCH] Fix backup for not 64k-aligned storages + +Zero out clusters after the end of the device, this makes restore handle +it correctly (even if it may try to write those zeros, it won't fail and +just ignore the out-of-bounds write to disk). + +For not even 4k-aligned disks, there is a potential buffer overrun in +the memcpy (since always 4k are copied), which causes host-memory +leakage into VMA archives. Fix this by always zeroing the affected area +in the output-buffer. + +Signed-off-by: Stefan Reiter +Reported-by: Roland Kammerer +Suggested-by: Lars Ellenberg +Tested-by: Roland Kammerer +--- + vma-writer.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/vma-writer.c b/vma-writer.c +index 06cbc02b1e..f5d2c5d23c 100644 +--- a/vma-writer.c ++++ b/vma-writer.c +@@ -633,17 +633,33 @@ vma_writer_write(VmaWriter *vmaw, uint8_t dev_id, int64_t cluster_num, + + DPRINTF("VMA WRITE %d %zd\n", dev_id, cluster_num); + ++ uint64_t dev_size = vmaw->stream_info[dev_id].size; + uint16_t mask = 0; + + if (buf) { + int i; + int bit = 1; ++ uint64_t byte_offset = cluster_num * VMA_CLUSTER_SIZE; + for (i = 0; i < 16; i++) { + const unsigned char *vmablock = buf + (i*VMA_BLOCK_SIZE); +- if (!buffer_is_zero(vmablock, VMA_BLOCK_SIZE)) { ++ ++ // Note: If the source is not 64k-aligned, we might reach 4k blocks ++ // after the end of the device. Always mark these as zero in the ++ // mask, so the restore handles them correctly. ++ if (byte_offset < dev_size && ++ !buffer_is_zero(vmablock, VMA_BLOCK_SIZE)) ++ { + mask |= bit; + memcpy(vmaw->outbuf + vmaw->outbuf_pos, vmablock, + VMA_BLOCK_SIZE); ++ ++ // prevent memory leakage on unaligned last block ++ if (byte_offset + VMA_BLOCK_SIZE > dev_size) { ++ uint64_t real_data_in_block = dev_size - byte_offset; ++ memset(vmaw->outbuf + vmaw->outbuf_pos + real_data_in_block, ++ 0, VMA_BLOCK_SIZE - real_data_in_block); ++ } ++ + vmaw->outbuf_pos += VMA_BLOCK_SIZE; + } else { + DPRINTF("VMA WRITE %zd ZERO BLOCK %d\n", cluster_num, i); +@@ -651,6 +667,7 @@ vma_writer_write(VmaWriter *vmaw, uint8_t dev_id, int64_t cluster_num, + *zero_bytes += VMA_BLOCK_SIZE; + } + ++ byte_offset += VMA_BLOCK_SIZE; + bit = bit << 1; + } + } else { +@@ -676,8 +693,8 @@ vma_writer_write(VmaWriter *vmaw, uint8_t dev_id, int64_t cluster_num, + + if (dev_id != vmaw->vmstate_stream) { + uint64_t last = (cluster_num + 1) * VMA_CLUSTER_SIZE; +- if (last > vmaw->stream_info[dev_id].size) { +- uint64_t diff = last - vmaw->stream_info[dev_id].size; ++ if (last > dev_size) { ++ uint64_t diff = last - dev_size; + if (diff >= VMA_CLUSTER_SIZE) { + vma_writer_set_error(vmaw, "vma_writer_write: " + "read after last cluster"); diff --git a/debian/patches/series b/debian/patches/series index e7345ce..4ca940c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -46,3 +46,5 @@ pve/0045-savevm-async-move-more-code-to-cleanup-and-rename-to.patch pve/0046-util-async-Add-aio_co_reschedule_self.patch pve/0047-savevm-async-flush-IOThread-drives-async-before-ente.patch pve/0048-savevm-async-add-debug-timing-prints.patch +pve/0049-Add-some-qemu_vfree-statements-to-prevent-memory-lea.patch +pve/0050-Fix-backup-for-not-64k-aligned-storages.patch