]> git.proxmox.com Git - pve-qemu.git/commitdiff
Fix backup for not 64k-aligned storages
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 24 Jun 2020 14:21:39 +0000 (16:21 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 24 Jun 2020 14:26:30 +0000 (16:26 +0200)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Tested-by: Roland Kammerer <roland.kammerer@linbit.com>
debian/patches/pve/0032-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch
debian/patches/pve/0049-Add-some-qemu_vfree-statements-to-prevent-memory-lea.patch [new file with mode: 0644]
debian/patches/pve/0050-Fix-backup-for-not-64k-aligned-storages.patch [new file with mode: 0644]
debian/patches/series

index f5868c7d60d9abc6867504d8069e0ffa4bbd4a25..2652bcff08a3f761ca277d1260465309fc7a2ff7 100644 (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 @@
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 (file)
index 0000000..fcf46d2
--- /dev/null
@@ -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;
+ }
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 (file)
index 0000000..c09b709
--- /dev/null
@@ -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");
index e7345cebfcd117dd9c62caecc82d2a27d4923762..4ca940cd4854cd3fb5011d68b5260f1515fc062e 100644 (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