Fix backup for not 64k-aligned storages

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Tested-by: Roland Kammerer <roland.kammerer@linbit.com>
master
Thomas Lamprecht 2020-06-24 16:21:39 +02:00
parent fff7e250ee
commit b570f1c41e
4 changed files with 127 additions and 1 deletions

View File

@ -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 @@

View File

@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stefan Reiter <s.reiter@proxmox.com>
Date: Mon, 22 Jun 2020 14:54:00 +0200
Subject: [PATCH] Add some qemu_vfree statements to prevent memory leaks
Suggested-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
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;
}

View File

@ -0,0 +1,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Stefan Reiter <s.reiter@proxmox.com>
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 <s.reiter@proxmox.com>
Reported-by: Roland Kammerer <roland.kammerer@linbit.com>
Suggested-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Roland Kammerer <roland.kammerer@linbit.com>
---
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");

View File

@ -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