import qemu-kvm-6.2.0-11.module+el8.6.0+15668+464a1f31.2
This commit is contained in:
		
							parent
							
								
									fdc6cbd41b
								
							
						
					
					
						commit
						907dabadf9
					
				| @ -0,0 +1,107 @@ | ||||
| From fb23aa4bc1842bb78e270ee7c4fdd663e45e2317 Mon Sep 17 00:00:00 2001 | ||||
| From: Stefano Garzarella <sgarzare@redhat.com> | ||||
| Date: Thu, 24 Mar 2022 16:04:57 +0100 | ||||
| Subject: [PATCH 01/11] RHEL: disable "seqpacket" for "vhost-vsock-device" in | ||||
|  rhel8.6.0 | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Stefano Garzarella <sgarzare@redhat.com> | ||||
| RH-MergeRequest: 146: RHEL: disable "seqpacket" for "vhost-vsock-device" in rhel8.6.0 [rhel-8.6.0.z] | ||||
| RH-Commit: [1/1] 516ee668b84252528de6f4946298089b153846f1 | ||||
| RH-Bugzilla: 2071103 | ||||
| RH-Acked-by: Jason Wang <jasowang@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| RH-Acked-by: Eugenio Pérez <eperezma@redhat.com> | ||||
| RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> | ||||
| 
 | ||||
| vhost-vsock device in RHEL 8 kernels doesn't support seqpacket. | ||||
| To avoid problems when migrating a VM from RHEL 9 host, we need to | ||||
| disable it in rhel8-* machine types. | ||||
| 
 | ||||
| Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | ||||
| ---
 | ||||
|  hw/core/machine.c          | 10 ++++++++++ | ||||
|  hw/i386/pc_piix.c          |  2 ++ | ||||
|  hw/i386/pc_q35.c           |  2 ++ | ||||
|  hw/s390x/s390-virtio-ccw.c |  1 + | ||||
|  include/hw/boards.h        |  3 +++ | ||||
|  5 files changed, 18 insertions(+) | ||||
| 
 | ||||
| diff --git a/hw/core/machine.c b/hw/core/machine.c
 | ||||
| index 024b025fc2..76fcabec7a 100644
 | ||||
| --- a/hw/core/machine.c
 | ||||
| +++ b/hw/core/machine.c
 | ||||
| @@ -37,6 +37,16 @@
 | ||||
|  #include "hw/virtio/virtio.h" | ||||
|  #include "hw/virtio/virtio-pci.h" | ||||
|   | ||||
| +GlobalProperty hw_compat_rhel_8_6[] = {
 | ||||
| +    /* hw_compat_rhel_8_6 bz 2068202 */
 | ||||
| +    /*
 | ||||
| +     * vhost-vsock device in RHEL 8 kernels doesn't support seqpacket, so
 | ||||
| +     * we need do disable it downstream on the latest hw_compat_rhel_8.
 | ||||
| +     */
 | ||||
| +    { "vhost-vsock-device", "seqpacket", "off" },
 | ||||
| +};
 | ||||
| +const size_t hw_compat_rhel_8_6_len = G_N_ELEMENTS(hw_compat_rhel_8_6);
 | ||||
| +
 | ||||
|  /* | ||||
|   * Mostly the same as hw_compat_6_0 and hw_compat_6_1 | ||||
|   */ | ||||
| diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
 | ||||
| index f03a8f0db8..ab6d03e07a 100644
 | ||||
| --- a/hw/i386/pc_piix.c
 | ||||
| +++ b/hw/i386/pc_piix.c
 | ||||
| @@ -998,6 +998,8 @@ static void pc_machine_rhel760_options(MachineClass *m)
 | ||||
|      pcmc->kvmclock_create_always = false; | ||||
|      /* From pc_i440fx_5_1_machine_options() */ | ||||
|      pcmc->pci_root_uid = 1; | ||||
| +    compat_props_add(m->compat_props, hw_compat_rhel_8_6,
 | ||||
| +                     hw_compat_rhel_8_6_len);
 | ||||
|      compat_props_add(m->compat_props, hw_compat_rhel_8_5, | ||||
|                       hw_compat_rhel_8_5_len); | ||||
|      compat_props_add(m->compat_props, pc_rhel_8_5_compat, | ||||
| diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
 | ||||
| index 5559261d9e..882fe7a68d 100644
 | ||||
| --- a/hw/i386/pc_q35.c
 | ||||
| +++ b/hw/i386/pc_q35.c
 | ||||
| @@ -658,6 +658,8 @@ static void pc_q35_machine_rhel860_options(MachineClass *m)
 | ||||
|      m->desc = "RHEL-8.6.0 PC (Q35 + ICH9, 2009)"; | ||||
|      pcmc->smbios_stream_product = "RHEL-AV"; | ||||
|      pcmc->smbios_stream_version = "8.6.0"; | ||||
| +    compat_props_add(m->compat_props, hw_compat_rhel_8_6,
 | ||||
| +                     hw_compat_rhel_8_6_len);
 | ||||
|  } | ||||
|   | ||||
|  DEFINE_PC_MACHINE(q35_rhel860, "pc-q35-rhel8.6.0", pc_q35_init_rhel860, | ||||
| diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
 | ||||
| index 9795eb9406..bec270598b 100644
 | ||||
| --- a/hw/s390x/s390-virtio-ccw.c
 | ||||
| +++ b/hw/s390x/s390-virtio-ccw.c
 | ||||
| @@ -1109,6 +1109,7 @@ static void ccw_machine_rhel860_instance_options(MachineState *machine)
 | ||||
|   | ||||
|  static void ccw_machine_rhel860_class_options(MachineClass *mc) | ||||
|  { | ||||
| +    compat_props_add(mc->compat_props, hw_compat_rhel_8_6, hw_compat_rhel_8_6_len);
 | ||||
|  } | ||||
|  DEFINE_CCW_MACHINE(rhel860, "rhel8.6.0", true); | ||||
|   | ||||
| diff --git a/include/hw/boards.h b/include/hw/boards.h
 | ||||
| index 04e8759815..4ddb798144 100644
 | ||||
| --- a/include/hw/boards.h
 | ||||
| +++ b/include/hw/boards.h
 | ||||
| @@ -443,6 +443,9 @@ extern const size_t hw_compat_2_2_len;
 | ||||
|  extern GlobalProperty hw_compat_2_1[]; | ||||
|  extern const size_t hw_compat_2_1_len; | ||||
|   | ||||
| +extern GlobalProperty hw_compat_rhel_8_6[];
 | ||||
| +extern const size_t hw_compat_rhel_8_6_len;
 | ||||
| +
 | ||||
|  extern GlobalProperty hw_compat_rhel_8_5[]; | ||||
|  extern const size_t hw_compat_rhel_8_5_len; | ||||
|   | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,128 @@ | ||||
| From 27fbe5c920c6680f9dbe994963183ee515f40c12 Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@redhat.com> | ||||
| Date: Thu, 14 Apr 2022 16:45:30 -0400 | ||||
| Subject: [PATCH 1/2] Revert redhat: Add some devices for exporting upstream | ||||
|  machine types | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 177: Revert redhat: Add some devices for exporting upstream machine types | ||||
| RH-Commit: [1/1] 9e5dd81cc2e2c8f1df76de9f75d815c91c250c69 (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2077928 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Thomas Huth <thuth@redhat.com> | ||||
| RH-Acked-by: Peter Xu <peterx@redhat.com> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2077928 | ||||
| Upstream: no | ||||
| 
 | ||||
| Manual revert of commit 70d3924521c9bfd912bcf1a1fc76f49eb377de46, since | ||||
| the directory structure looks different from rhel-av-8.4.0.z where | ||||
| this commit is taken from. Besides, x86_64-softmmu.mak looks totally | ||||
| different and should not be affected by this reversal.
 | ||||
| 
 | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  configs/devices/x86_64-softmmu/x86_64-rh-devices.mak     | 1 - | ||||
|  .../devices/x86_64-softmmu/x86_64-upstream-devices.mak   | 4 ---- | ||||
|  hw/char/parallel.c                                       | 9 --------- | ||||
|  hw/i386/pc_piix.c                                        | 2 +- | ||||
|  hw/i386/pc_q35.c                                         | 2 +- | ||||
|  hw/timer/hpet.c                                          | 8 -------- | ||||
|  6 files changed, 2 insertions(+), 24 deletions(-) | ||||
|  delete mode 100644 configs/devices/x86_64-softmmu/x86_64-upstream-devices.mak | ||||
| 
 | ||||
| diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
 | ||||
| index fdbbdf9742..31ce08edab 100644
 | ||||
| --- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
 | ||||
| +++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
 | ||||
| @@ -1,5 +1,4 @@
 | ||||
|  include ../rh-virtio.mak | ||||
| -include x86_64-upstream-devices.mak
 | ||||
|   | ||||
|  CONFIG_AC97=y | ||||
|  CONFIG_ACPI=y | ||||
| diff --git a/configs/devices/x86_64-softmmu/x86_64-upstream-devices.mak b/configs/devices/x86_64-softmmu/x86_64-upstream-devices.mak
 | ||||
| deleted file mode 100644 | ||||
| index 2cd20f54d2..0000000000
 | ||||
| --- a/configs/devices/x86_64-softmmu/x86_64-upstream-devices.mak
 | ||||
| +++ /dev/null
 | ||||
| @@ -1,4 +0,0 @@
 | ||||
| -# We need "isa-parallel"
 | ||||
| -CONFIG_PARALLEL=y
 | ||||
| -# We need "hpet"
 | ||||
| -CONFIG_HPET=y
 | ||||
| diff --git a/hw/char/parallel.c b/hw/char/parallel.c
 | ||||
| index e5f108211b..b45e67bfbb 100644
 | ||||
| --- a/hw/char/parallel.c
 | ||||
| +++ b/hw/char/parallel.c
 | ||||
| @@ -29,7 +29,6 @@
 | ||||
|  #include "chardev/char-parallel.h" | ||||
|  #include "chardev/char-fe.h" | ||||
|  #include "hw/acpi/aml-build.h" | ||||
| -#include "hw/boards.h"
 | ||||
|  #include "hw/irq.h" | ||||
|  #include "hw/isa/isa.h" | ||||
|  #include "hw/qdev-properties.h" | ||||
| @@ -535,14 +534,6 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
 | ||||
|      int base; | ||||
|      uint8_t dummy; | ||||
|   | ||||
| -    /* Restricted for Red Hat Enterprise Linux */
 | ||||
| -    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
 | ||||
| -    if (strstr(mc->name, "rhel")) {
 | ||||
| -        error_setg(errp, "Device %s is not supported with machine type %s",
 | ||||
| -                   object_get_typename(OBJECT(dev)), mc->name);
 | ||||
| -        return;
 | ||||
| -    }
 | ||||
| -
 | ||||
|      if (!qemu_chr_fe_backend_connected(&s->chr)) { | ||||
|          error_setg(errp, "Can't create parallel device, empty char device"); | ||||
|          return; | ||||
| diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
 | ||||
| index ab6d03e07a..5f101c8748 100644
 | ||||
| --- a/hw/i386/pc_piix.c
 | ||||
| +++ b/hw/i386/pc_piix.c
 | ||||
| @@ -966,7 +966,7 @@ static void pc_machine_rhel7_options(MachineClass *m)
 | ||||
|  { | ||||
|      PCMachineClass *pcmc = PC_MACHINE_CLASS(m); | ||||
|      m->family = "pc_piix_Y"; | ||||
| -    m->default_machine_opts = "firmware=bios-256k.bin,hpet=off";
 | ||||
| +    m->default_machine_opts = "firmware=bios-256k.bin";
 | ||||
|      pcmc->default_nic_model = "e1000"; | ||||
|      pcmc->pci_root_uid = 0; | ||||
|      m->default_display = "std"; | ||||
| diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
 | ||||
| index 882fe7a68d..73b0d0d317 100644
 | ||||
| --- a/hw/i386/pc_q35.c
 | ||||
| +++ b/hw/i386/pc_q35.c
 | ||||
| @@ -633,7 +633,7 @@ static void pc_q35_machine_rhel_options(MachineClass *m)
 | ||||
|      pcmc->pci_root_uid = 0; | ||||
|      m->family = "pc_q35_Z"; | ||||
|      m->units_per_default_bus = 1; | ||||
| -    m->default_machine_opts = "firmware=bios-256k.bin,hpet=off";
 | ||||
| +    m->default_machine_opts = "firmware=bios-256k.bin";
 | ||||
|      m->default_display = "std"; | ||||
|      m->no_floppy = 1; | ||||
|      m->no_parallel = 1; | ||||
| diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
 | ||||
| index 202e032524..9520471be2 100644
 | ||||
| --- a/hw/timer/hpet.c
 | ||||
| +++ b/hw/timer/hpet.c
 | ||||
| @@ -733,14 +733,6 @@ static void hpet_realize(DeviceState *dev, Error **errp)
 | ||||
|      int i; | ||||
|      HPETTimer *timer; | ||||
|   | ||||
| -    /* Restricted for Red Hat Enterprise Linux */
 | ||||
| -    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
 | ||||
| -    if (strstr(mc->name, "rhel")) {
 | ||||
| -        error_setg(errp, "Device %s is not supported with machine type %s",
 | ||||
| -                   object_get_typename(OBJECT(dev)), mc->name);
 | ||||
| -        return;
 | ||||
| -    }
 | ||||
| -
 | ||||
|      if (!s->intcap) { | ||||
|          warn_report("Hpet's intcap not initialized"); | ||||
|      } | ||||
| -- 
 | ||||
| 2.35.3 | ||||
| 
 | ||||
| @ -0,0 +1,59 @@ | ||||
| From 08103b26cb393920410e0a943d35e79bbd9f5ce0 Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@rehat.com> | ||||
| Date: Wed, 13 Apr 2022 20:54:45 -0400 | ||||
| Subject: [PATCH 05/11] display/qxl-render: fix race condition in qxl_cursor | ||||
|  (CVE-2021-4207) | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 162: display/qxl-render: fix race condition in qxl_cursor (CVE-2021-4207) | ||||
| RH-Commit: [1/1] 055c5a8345ad434a723b8106ba0a7b85fe117547 (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2075683 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||
| RH-Acked-by: Mauro Matteo Cascella <None> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075683 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2021-4207 | ||||
| 
 | ||||
| commit 9569f5cb5b4bffa9d3ebc8ba7da1e03830a9a895 | ||||
| Author: Mauro Matteo Cascella <mcascell@redhat.com> | ||||
| Date:   Thu Apr 7 10:11:06 2022 +0200 | ||||
| 
 | ||||
|     display/qxl-render: fix race condition in qxl_cursor (CVE-2021-4207) | ||||
| 
 | ||||
|     Avoid fetching 'width' and 'height' a second time to prevent possible | ||||
|     race condition. Refer to security advisory | ||||
|     https://starlabs.sg/advisories/22-4207/ for more information. | ||||
| 
 | ||||
|     Fixes: CVE-2021-4207 | ||||
|     Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com> | ||||
|     Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||
|     Message-Id: <20220407081106.343235-1-mcascell@redhat.com> | ||||
|     Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> | ||||
| 
 | ||||
| (cherry picked from commit 9569f5cb5b4bffa9d3ebc8ba7da1e03830a9a895) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  hw/display/qxl-render.c | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
 | ||||
| index d28849b121..237ed293ba 100644
 | ||||
| --- a/hw/display/qxl-render.c
 | ||||
| +++ b/hw/display/qxl-render.c
 | ||||
| @@ -266,7 +266,7 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
 | ||||
|          } | ||||
|          break; | ||||
|      case SPICE_CURSOR_TYPE_ALPHA: | ||||
| -        size = sizeof(uint32_t) * cursor->header.width * cursor->header.height;
 | ||||
| +        size = sizeof(uint32_t) * c->width * c->height;
 | ||||
|          qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id); | ||||
|          if (qxl->debug > 2) { | ||||
|              cursor_print_ascii_art(c, "qxl/alpha"); | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,76 @@ | ||||
| From ef311c8ca284d11dc812a1004de52125fc9eb194 Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@redhat.com> | ||||
| Date: Wed, 13 Apr 2022 14:51:06 -0400 | ||||
| Subject: [PATCH 02/11] hw/intc/arm_gicv3: Check for !MEMTX_OK instead of | ||||
|  MEMTX_ERROR | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 158: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR | ||||
| RH-Commit: [1/3] ebfd87ea3a2de51c6961569861d5f4fba25890cc (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2075686 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| RH-Acked-by: Peter Xu <peterx@redhat.com> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075686 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2021-3750 | ||||
| 
 | ||||
| commit b9d383ab797f54ae5fa8746117770709921dc529 | ||||
| Author: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||
| Date:   Wed Dec 15 19:24:19 2021 +0100 | ||||
| 
 | ||||
|     hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR | ||||
| 
 | ||||
|     Quoting Peter Maydell: | ||||
| 
 | ||||
|      "These MEMTX_* aren't from the memory transaction | ||||
|       API functions; they're just being used by gicd_readl() and | ||||
|       friends as a way to indicate a success/failure so that the | ||||
|       actual MemoryRegionOps read/write fns like gicv3_dist_read() | ||||
|       can log a guest error." | ||||
| 
 | ||||
|     We are going to introduce more MemTxResult bits, so it is | ||||
|     safer to check for !MEMTX_OK rather than MEMTX_ERROR. | ||||
| 
 | ||||
|     Reviewed-by: Peter Xu <peterx@redhat.com> | ||||
|     Reviewed-by: David Hildenbrand <david@redhat.com> | ||||
|     Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||||
|     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
|     Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||
|     Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||||
| 
 | ||||
| (cherry picked from commit b9d383ab797f54ae5fa8746117770709921dc529) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  hw/intc/arm_gicv3_redist.c | 4 ++-- | ||||
|  1 file changed, 2 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
 | ||||
| index c8ff3eca08..99b11ca5ee 100644
 | ||||
| --- a/hw/intc/arm_gicv3_redist.c
 | ||||
| +++ b/hw/intc/arm_gicv3_redist.c
 | ||||
| @@ -462,7 +462,7 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
 | ||||
|          break; | ||||
|      } | ||||
|   | ||||
| -    if (r == MEMTX_ERROR) {
 | ||||
| +    if (r != MEMTX_OK) {
 | ||||
|          qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                        "%s: invalid guest read at offset " TARGET_FMT_plx | ||||
|                        " size %u\n", __func__, offset, size); | ||||
| @@ -521,7 +521,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
 | ||||
|          break; | ||||
|      } | ||||
|   | ||||
| -    if (r == MEMTX_ERROR) {
 | ||||
| +    if (r != MEMTX_OK) {
 | ||||
|          qemu_log_mask(LOG_GUEST_ERROR, | ||||
|                        "%s: invalid guest write at offset " TARGET_FMT_plx | ||||
|                        " size %u\n", __func__, offset, size); | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,52 @@ | ||||
| From f663b951b87735bee6b5a4d75b726f609e557f8c Mon Sep 17 00:00:00 2001 | ||||
| From: Hanna Reitz <hreitz@redhat.com> | ||||
| Date: Thu, 21 Apr 2022 16:24:35 +0200 | ||||
| Subject: [PATCH 11/11] iotests/108: Fix when missing user_allow_other | ||||
| 
 | ||||
| RH-Author: Hanna Reitz <hreitz@redhat.com> | ||||
| RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding | ||||
| RH-Commit: [4/4] cea00f9cb38639d4c51fab13c20311d1737d5ca3 | ||||
| RH-Bugzilla: 2072242 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Eric Blake <eblake@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| 
 | ||||
| FUSE exports' allow-other option defaults to "auto", which means that it | ||||
| will try passing allow_other as a mount option, and fall back to not | ||||
| using it when an error occurs.  We make no effort to hide fusermount's | ||||
| error message (because it would be difficult, and because users might | ||||
| want to know about the fallback occurring), and so when allow_other does | ||||
| not work (primarily when /etc/fuse.conf does not contain | ||||
| user_allow_other), this error message will appear and break the | ||||
| reference output. | ||||
| 
 | ||||
| We do not need allow_other here, though, so we can just pass | ||||
| allow-other=off to fix that. | ||||
| 
 | ||||
| Reported-by: Markus Armbruster <armbru@redhat.com> | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| Message-Id: <20220421142435.569600-1-hreitz@redhat.com> | ||||
| Tested-by: Markus Armbruster <armbru@redhat.com> | ||||
| Tested-by: Eric Blake <eblake@redhat.com> | ||||
| (cherry picked from commit 348a0740afc5b313599533eb69bbb2b95d2f1bba) | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| ---
 | ||||
|  tests/qemu-iotests/108 | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
 | ||||
| index 23abbeaff0..775ff08eca 100755
 | ||||
| --- a/tests/qemu-iotests/108
 | ||||
| +++ b/tests/qemu-iotests/108
 | ||||
| @@ -326,7 +326,7 @@ else
 | ||||
|   | ||||
|      $QSD \ | ||||
|          --blockdev file,node-name=export-node,filename="$TEST_IMG" \ | ||||
| -        --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off \
 | ||||
| +        --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off,allow-other=off \
 | ||||
|          --pidfile "$TEST_DIR/qsd.pid" \ | ||||
|          & | ||||
|   | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,445 @@ | ||||
| From a5cc7f98669fbde7290fc363cb61dc7bd41718f3 Mon Sep 17 00:00:00 2001 | ||||
| From: Hanna Reitz <hreitz@redhat.com> | ||||
| Date: Tue, 5 Apr 2022 15:46:51 +0200 | ||||
| Subject: [PATCH 09/11] iotests/108: Test new refcount rebuild algorithm | ||||
| 
 | ||||
| RH-Author: Hanna Reitz <hreitz@redhat.com> | ||||
| RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding | ||||
| RH-Commit: [2/4] db808dcc1c5ee9fd901c0800b3fac1348fab246f | ||||
| RH-Bugzilla: 2072242 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Eric Blake <eblake@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| 
 | ||||
| One clear problem with how qcow2's refcount structure rebuild algorithm | ||||
| used to be before "qcow2: Improve refcount structure rebuilding" was | ||||
| that it is prone to failure for qcow2 images on block devices: There is | ||||
| generally unused space after the actual image, and if that exceeds what | ||||
| one refblock covers, the old algorithm would invariably write the | ||||
| reftable past the block device's end, which cannot work.  The new | ||||
| algorithm does not have this problem. | ||||
| 
 | ||||
| Test it with three tests: | ||||
| (1) Create an image with more empty space at the end than what one | ||||
|     refblock covers, see whether rebuilding the refcount structures | ||||
|     results in a change in the image file length.  (It should not.) | ||||
| 
 | ||||
| (2) Leave precisely enough space somewhere at the beginning of the image | ||||
|     for the new reftable (and the refblock for that place), see whether | ||||
|     the new algorithm puts the reftable there.  (It should.) | ||||
| 
 | ||||
| (3) Test the original problem: Create (something like) a block device | ||||
|     with a fixed size, then create a qcow2 image in there, write some | ||||
|     data, and then have qemu-img check rebuild the refcount structures. | ||||
|     Before HEAD^, the reftable would have been written past the image | ||||
|     file end, i.e. outside of what the block device provides, which | ||||
|     cannot work.  HEAD^ should have fixed that. | ||||
|     ("Something like a block device" means a loop device if we can use | ||||
|     one ("sudo -n losetup" works), or a FUSE block export with | ||||
|     growable=false otherwise.) | ||||
| 
 | ||||
| Reviewed-by: Eric Blake <eblake@redhat.com> | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| Message-Id: <20220405134652.19278-3-hreitz@redhat.com> | ||||
| (cherry picked from commit 9ffd6d646d1d5ee9087a8cbf0b7d2f96c5656162) | ||||
| 
 | ||||
| Conflicts: | ||||
| - 108: The downstream qemu-storage-daemon does not support --daemonize,
 | ||||
|   so this switch has been replaced by a loop waiting for the PID file to | ||||
|   appear | ||||
| 
 | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| ---
 | ||||
|  tests/qemu-iotests/108     | 263 ++++++++++++++++++++++++++++++++++++- | ||||
|  tests/qemu-iotests/108.out |  81 ++++++++++++ | ||||
|  2 files changed, 343 insertions(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
 | ||||
| index 8eaef0b8bf..23abbeaff0 100755
 | ||||
| --- a/tests/qemu-iotests/108
 | ||||
| +++ b/tests/qemu-iotests/108
 | ||||
| @@ -30,13 +30,20 @@ status=1	# failure is the default!
 | ||||
|   | ||||
|  _cleanup() | ||||
|  { | ||||
| -	_cleanup_test_img
 | ||||
| +    _cleanup_test_img
 | ||||
| +    if [ -f "$TEST_DIR/qsd.pid" ]; then
 | ||||
| +        qsd_pid=$(cat "$TEST_DIR/qsd.pid")
 | ||||
| +        kill -KILL "$qsd_pid"
 | ||||
| +        fusermount -u "$TEST_DIR/fuse-export" &>/dev/null
 | ||||
| +    fi
 | ||||
| +    rm -f "$TEST_DIR/fuse-export"
 | ||||
|  } | ||||
|  trap "_cleanup; exit \$status" 0 1 2 3 15 | ||||
|   | ||||
|  # get standard environment, filters and checks | ||||
|  . ./common.rc | ||||
|  . ./common.filter | ||||
| +. ./common.qemu
 | ||||
|   | ||||
|  # This tests qcow2-specific low-level functionality | ||||
|  _supported_fmt qcow2 | ||||
| @@ -47,6 +54,22 @@ _supported_os Linux
 | ||||
|  # files | ||||
|  _unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file | ||||
|   | ||||
| +# This test either needs sudo -n losetup or FUSE exports to work
 | ||||
| +if sudo -n losetup &>/dev/null; then
 | ||||
| +    loopdev=true
 | ||||
| +else
 | ||||
| +    loopdev=false
 | ||||
| +
 | ||||
| +    # QSD --export fuse will either yield "Parameter 'id' is missing"
 | ||||
| +    # or "Invalid parameter 'fuse'", depending on whether there is
 | ||||
| +    # FUSE support or not.
 | ||||
| +    error=$($QSD --export fuse 2>&1)
 | ||||
| +    if [[ $error = *"'fuse'"* ]]; then
 | ||||
| +        _notrun 'Passwordless sudo for losetup or FUSE support required, but' \
 | ||||
| +                'neither is available'
 | ||||
| +    fi
 | ||||
| +fi
 | ||||
| +
 | ||||
|  echo | ||||
|  echo '=== Repairing an image without any refcount table ===' | ||||
|  echo | ||||
| @@ -138,6 +161,244 @@ _make_test_img 64M
 | ||||
|  poke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00" | ||||
|  _check_test_img -r all | ||||
|   | ||||
| +echo
 | ||||
| +echo '=== Check rebuilt reftable location ==='
 | ||||
| +
 | ||||
| +# In an earlier version of the refcount rebuild algorithm, the
 | ||||
| +# reftable was generally placed at the image end (unless something was
 | ||||
| +# allocated in the area covered by the refblock right before the image
 | ||||
| +# file end, then we would try to place the reftable in that refblock).
 | ||||
| +# This was later changed so the reftable would be placed in the
 | ||||
| +# earliest possible location.  Test this.
 | ||||
| +
 | ||||
| +echo
 | ||||
| +echo '--- Does the image size increase? ---'
 | ||||
| +echo
 | ||||
| +
 | ||||
| +# First test: Just create some image, write some data to it, and
 | ||||
| +# resize it so there is free space at the end of the image (enough
 | ||||
| +# that it spans at least one full refblock, which for cluster_size=512
 | ||||
| +# images, spans 128k).  With the old algorithm, the reftable would
 | ||||
| +# have then been placed at the end of the image file, but with the new
 | ||||
| +# one, it will be put in that free space.
 | ||||
| +# We want to check whether the size of the image file increases due to
 | ||||
| +# rebuilding the refcount structures (it should not).
 | ||||
| +
 | ||||
| +_make_test_img -o 'cluster_size=512' 1M
 | ||||
| +# Write something
 | ||||
| +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
 | ||||
| +
 | ||||
| +# Add free space
 | ||||
| +file_len=$(stat -c '%s' "$TEST_IMG")
 | ||||
| +truncate -s $((file_len + 256 * 1024)) "$TEST_IMG"
 | ||||
| +
 | ||||
| +# Corrupt the image by saying the image header was not allocated
 | ||||
| +rt_offset=$(peek_file_be "$TEST_IMG" 48 8)
 | ||||
| +rb_offset=$(peek_file_be "$TEST_IMG" $rt_offset 8)
 | ||||
| +poke_file "$TEST_IMG" $rb_offset "\x00\x00"
 | ||||
| +
 | ||||
| +# Check whether rebuilding the refcount structures increases the image
 | ||||
| +# file size
 | ||||
| +file_len=$(stat -c '%s' "$TEST_IMG")
 | ||||
| +echo
 | ||||
| +# The only leaks there can be are the old refcount structures that are
 | ||||
| +# leaked during rebuilding, no need to clutter the output with them
 | ||||
| +_check_test_img -r all | grep -v '^Repairing cluster.*refcount=1 reference=0'
 | ||||
| +echo
 | ||||
| +post_repair_file_len=$(stat -c '%s' "$TEST_IMG")
 | ||||
| +
 | ||||
| +if [[ $file_len -eq $post_repair_file_len ]]; then
 | ||||
| +    echo 'OK: Image size did not change'
 | ||||
| +else
 | ||||
| +    echo 'ERROR: Image size differs' \
 | ||||
| +        "($file_len before, $post_repair_file_len after)"
 | ||||
| +fi
 | ||||
| +
 | ||||
| +echo
 | ||||
| +echo '--- Will the reftable occupy a hole specifically left for it?  ---'
 | ||||
| +echo
 | ||||
| +
 | ||||
| +# Note: With cluster_size=512, every refblock covers 128k.
 | ||||
| +# The reftable covers 8M per reftable cluster.
 | ||||
| +
 | ||||
| +# Create an image that requires two reftable clusters (just because
 | ||||
| +# this is more interesting than a single-clustered reftable).
 | ||||
| +_make_test_img -o 'cluster_size=512' 9M
 | ||||
| +$QEMU_IO -c 'write 0 8M' "$TEST_IMG" | _filter_qemu_io
 | ||||
| +
 | ||||
| +# Writing 8M will have resized the reftable.  Unfortunately, doing so
 | ||||
| +# will leave holes in the file, so we need to fill them up so we can
 | ||||
| +# be sure the whole file is allocated.  Do that by writing
 | ||||
| +# consecutively smaller chunks starting from 8 MB, until the file
 | ||||
| +# length increases even with a chunk size of 512.  Then we must have
 | ||||
| +# filled all holes.
 | ||||
| +ofs=$((8 * 1024 * 1024))
 | ||||
| +block_len=$((16 * 1024))
 | ||||
| +while [[ $block_len -ge 512 ]]; do
 | ||||
| +    file_len=$(stat -c '%s' "$TEST_IMG")
 | ||||
| +    while [[ $(stat -c '%s' "$TEST_IMG") -eq $file_len ]]; do
 | ||||
| +        # Do not include this in the reference output, it does not
 | ||||
| +        # really matter which qemu-io calls we do here exactly
 | ||||
| +        $QEMU_IO -c "write $ofs $block_len" "$TEST_IMG" >/dev/null
 | ||||
| +        ofs=$((ofs + block_len))
 | ||||
| +    done
 | ||||
| +    block_len=$((block_len / 2))
 | ||||
| +done
 | ||||
| +
 | ||||
| +# Fill up to 9M (do not include this in the reference output either,
 | ||||
| +# $ofs is random for all we know)
 | ||||
| +$QEMU_IO -c "write $ofs $((9 * 1024 * 1024 - ofs))" "$TEST_IMG" >/dev/null
 | ||||
| +
 | ||||
| +# Make space as follows:
 | ||||
| +# - For the first refblock: Right at the beginning of the image (this
 | ||||
| +#   refblock is placed in the first place possible),
 | ||||
| +# - For the reftable somewhere soon afterwards, still near the
 | ||||
| +#   beginning of the image (i.e. covered by the first refblock); the
 | ||||
| +#   reftable too is placed in the first place possible, but only after
 | ||||
| +#   all refblocks have been placed)
 | ||||
| +# No space is needed for the other refblocks, because no refblock is
 | ||||
| +# put before the space it covers.  In this test case, we do not mind
 | ||||
| +# if they are placed at the image file's end.
 | ||||
| +
 | ||||
| +# Before we make that space, we have to find out the host offset of
 | ||||
| +# the area that belonged to the two data clusters at guest offset 4k,
 | ||||
| +# because we expect the reftable to be placed there, and we will have
 | ||||
| +# to verify that it is.
 | ||||
| +
 | ||||
| +l1_offset=$(peek_file_be "$TEST_IMG" 40 8)
 | ||||
| +l2_offset=$(peek_file_be "$TEST_IMG" $l1_offset 8)
 | ||||
| +l2_offset=$((l2_offset & 0x00fffffffffffe00))
 | ||||
| +data_4k_offset=$(peek_file_be "$TEST_IMG" \
 | ||||
| +                 $((l2_offset + 4096 / 512 * 8)) 8)
 | ||||
| +data_4k_offset=$((data_4k_offset & 0x00fffffffffffe00))
 | ||||
| +
 | ||||
| +$QEMU_IO -c "discard 0 512" -c "discard 4k 1k" "$TEST_IMG" | _filter_qemu_io
 | ||||
| +
 | ||||
| +# Corrupt the image by saying the image header was not allocated
 | ||||
| +rt_offset=$(peek_file_be "$TEST_IMG" 48 8)
 | ||||
| +rb_offset=$(peek_file_be "$TEST_IMG" $rt_offset 8)
 | ||||
| +poke_file "$TEST_IMG" $rb_offset "\x00\x00"
 | ||||
| +
 | ||||
| +echo
 | ||||
| +# The only leaks there can be are the old refcount structures that are
 | ||||
| +# leaked during rebuilding, no need to clutter the output with them
 | ||||
| +_check_test_img -r all | grep -v '^Repairing cluster.*refcount=1 reference=0'
 | ||||
| +echo
 | ||||
| +
 | ||||
| +# Check whether the reftable was put where we expected
 | ||||
| +rt_offset=$(peek_file_be "$TEST_IMG" 48 8)
 | ||||
| +if [[ $rt_offset -eq $data_4k_offset ]]; then
 | ||||
| +    echo 'OK: Reftable is where we expect it'
 | ||||
| +else
 | ||||
| +    echo "ERROR: Reftable is at $rt_offset, but was expected at $data_4k_offset"
 | ||||
| +fi
 | ||||
| +
 | ||||
| +echo
 | ||||
| +echo '--- Rebuilding refcount structures on block devices ---'
 | ||||
| +echo
 | ||||
| +
 | ||||
| +# A block device cannot really grow, at least not during qemu-img
 | ||||
| +# check.  As mentioned in the above cases, rebuilding the refcount
 | ||||
| +# structure may lead to new refcount structures being written after
 | ||||
| +# the end of the image, and in the past that happened even if there
 | ||||
| +# was more than sufficient space in the image.  Such post-EOF writes
 | ||||
| +# will not work on block devices, so test that the new algorithm
 | ||||
| +# avoids it.
 | ||||
| +
 | ||||
| +# If we have passwordless sudo and losetup, we can use those to create
 | ||||
| +# a block device.  Otherwise, we can resort to qemu's FUSE export to
 | ||||
| +# create a file that isn't growable, which effectively tests the same
 | ||||
| +# thing.
 | ||||
| +
 | ||||
| +_cleanup_test_img
 | ||||
| +truncate -s $((64 * 1024 * 1024)) "$TEST_IMG"
 | ||||
| +
 | ||||
| +if $loopdev; then
 | ||||
| +    export_mp=$(sudo -n losetup --show -f "$TEST_IMG")
 | ||||
| +    export_mp_driver=host_device
 | ||||
| +    sudo -n chmod go+rw "$export_mp"
 | ||||
| +else
 | ||||
| +    # Create non-growable FUSE export that is a bit like an empty
 | ||||
| +    # block device
 | ||||
| +    export_mp="$TEST_DIR/fuse-export"
 | ||||
| +    export_mp_driver=file
 | ||||
| +    touch "$export_mp"
 | ||||
| +
 | ||||
| +    $QSD \
 | ||||
| +        --blockdev file,node-name=export-node,filename="$TEST_IMG" \
 | ||||
| +        --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off \
 | ||||
| +        --pidfile "$TEST_DIR/qsd.pid" \
 | ||||
| +        &
 | ||||
| +
 | ||||
| +    while [ ! -f "$TEST_DIR/qsd.pid" ]; do
 | ||||
| +        sleep 0.1
 | ||||
| +    done
 | ||||
| +fi
 | ||||
| +
 | ||||
| +# Now create a qcow2 image on the device -- unfortunately, qemu-img
 | ||||
| +# create force-creates the file, so we have to resort to the
 | ||||
| +# blockdev-create job.
 | ||||
| +_launch_qemu \
 | ||||
| +    --blockdev $export_mp_driver,node-name=file,filename="$export_mp"
 | ||||
| +
 | ||||
| +_send_qemu_cmd \
 | ||||
| +    $QEMU_HANDLE \
 | ||||
| +    '{ "execute": "qmp_capabilities" }' \
 | ||||
| +    'return'
 | ||||
| +
 | ||||
| +# Small cluster size again, so the image needs multiple refblocks
 | ||||
| +_send_qemu_cmd \
 | ||||
| +    $QEMU_HANDLE \
 | ||||
| +    '{ "execute": "blockdev-create",
 | ||||
| +       "arguments": {
 | ||||
| +           "job-id": "create",
 | ||||
| +           "options": {
 | ||||
| +               "driver": "qcow2",
 | ||||
| +               "file": "file",
 | ||||
| +               "size": '$((64 * 1024 * 1024))',
 | ||||
| +               "cluster-size": 512
 | ||||
| +           } } }' \
 | ||||
| +    '"concluded"'
 | ||||
| +
 | ||||
| +_send_qemu_cmd \
 | ||||
| +    $QEMU_HANDLE \
 | ||||
| +    '{ "execute": "job-dismiss", "arguments": { "id": "create" } }' \
 | ||||
| +    'return'
 | ||||
| +
 | ||||
| +_send_qemu_cmd \
 | ||||
| +    $QEMU_HANDLE \
 | ||||
| +    '{ "execute": "quit" }' \
 | ||||
| +    'return'
 | ||||
| +
 | ||||
| +wait=y _cleanup_qemu
 | ||||
| +echo
 | ||||
| +
 | ||||
| +# Write some data
 | ||||
| +$QEMU_IO -c 'write 0 64k' "$export_mp" | _filter_qemu_io
 | ||||
| +
 | ||||
| +# Corrupt the image by saying the image header was not allocated
 | ||||
| +rt_offset=$(peek_file_be "$export_mp" 48 8)
 | ||||
| +rb_offset=$(peek_file_be "$export_mp" $rt_offset 8)
 | ||||
| +poke_file "$export_mp" $rb_offset "\x00\x00"
 | ||||
| +
 | ||||
| +# Repairing such a simple case should just work
 | ||||
| +# (We used to put the reftable at the end of the image file, which can
 | ||||
| +# never work for non-growable devices.)
 | ||||
| +echo
 | ||||
| +TEST_IMG="$export_mp" _check_test_img -r all \
 | ||||
| +    | grep -v '^Repairing cluster.*refcount=1 reference=0'
 | ||||
| +
 | ||||
| +if $loopdev; then
 | ||||
| +    sudo -n losetup -d "$export_mp"
 | ||||
| +else
 | ||||
| +    qsd_pid=$(cat "$TEST_DIR/qsd.pid")
 | ||||
| +    kill -TERM "$qsd_pid"
 | ||||
| +    # Wait for process to exit (cannot `wait` because the QSD is daemonized)
 | ||||
| +    while [ -f "$TEST_DIR/qsd.pid" ]; do
 | ||||
| +        true
 | ||||
| +    done
 | ||||
| +fi
 | ||||
| +
 | ||||
|  # success, all done | ||||
|  echo '*** done' | ||||
|  rm -f $seq.full | ||||
| diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out
 | ||||
| index 75bab8dc84..b5401d788d 100644
 | ||||
| --- a/tests/qemu-iotests/108.out
 | ||||
| +++ b/tests/qemu-iotests/108.out
 | ||||
| @@ -105,6 +105,87 @@ The following inconsistencies were found and repaired:
 | ||||
|      0 leaked clusters | ||||
|      1 corruptions | ||||
|   | ||||
| +Double checking the fixed image now...
 | ||||
| +No errors were found on the image.
 | ||||
| +
 | ||||
| +=== Check rebuilt reftable location ===
 | ||||
| +
 | ||||
| +--- Does the image size increase? ---
 | ||||
| +
 | ||||
| +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
 | ||||
| +wrote 65536/65536 bytes at offset 0
 | ||||
| +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||
| +
 | ||||
| +ERROR cluster 0 refcount=0 reference=1
 | ||||
| +Rebuilding refcount structure
 | ||||
| +The following inconsistencies were found and repaired:
 | ||||
| +
 | ||||
| +    0 leaked clusters
 | ||||
| +    1 corruptions
 | ||||
| +
 | ||||
| +Double checking the fixed image now...
 | ||||
| +No errors were found on the image.
 | ||||
| +
 | ||||
| +OK: Image size did not change
 | ||||
| +
 | ||||
| +--- Will the reftable occupy a hole specifically left for it?  ---
 | ||||
| +
 | ||||
| +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=9437184
 | ||||
| +wrote 8388608/8388608 bytes at offset 0
 | ||||
| +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||
| +discard 512/512 bytes at offset 0
 | ||||
| +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||
| +discard 1024/1024 bytes at offset 4096
 | ||||
| +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||
| +
 | ||||
| +ERROR cluster 0 refcount=0 reference=1
 | ||||
| +Rebuilding refcount structure
 | ||||
| +The following inconsistencies were found and repaired:
 | ||||
| +
 | ||||
| +    0 leaked clusters
 | ||||
| +    1 corruptions
 | ||||
| +
 | ||||
| +Double checking the fixed image now...
 | ||||
| +No errors were found on the image.
 | ||||
| +
 | ||||
| +OK: Reftable is where we expect it
 | ||||
| +
 | ||||
| +--- Rebuilding refcount structures on block devices ---
 | ||||
| +
 | ||||
| +{ "execute": "qmp_capabilities" }
 | ||||
| +{"return": {}}
 | ||||
| +{ "execute": "blockdev-create",
 | ||||
| +       "arguments": {
 | ||||
| +           "job-id": "create",
 | ||||
| +           "options": {
 | ||||
| +               "driver": "IMGFMT",
 | ||||
| +               "file": "file",
 | ||||
| +               "size": 67108864,
 | ||||
| +               "cluster-size": 512
 | ||||
| +           } } }
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "create"}}
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "create"}}
 | ||||
| +{"return": {}}
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "create"}}
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "create"}}
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "create"}}
 | ||||
| +{ "execute": "job-dismiss", "arguments": { "id": "create" } }
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "create"}}
 | ||||
| +{"return": {}}
 | ||||
| +{ "execute": "quit" }
 | ||||
| +{"return": {}}
 | ||||
| +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
 | ||||
| +
 | ||||
| +wrote 65536/65536 bytes at offset 0
 | ||||
| +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||
| +
 | ||||
| +ERROR cluster 0 refcount=0 reference=1
 | ||||
| +Rebuilding refcount structure
 | ||||
| +The following inconsistencies were found and repaired:
 | ||||
| +
 | ||||
| +    0 leaked clusters
 | ||||
| +    1 corruptions
 | ||||
| +
 | ||||
|  Double checking the fixed image now... | ||||
|  No errors were found on the image. | ||||
|  *** done | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
							
								
								
									
										162
									
								
								SOURCES/kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								SOURCES/kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,162 @@ | ||||
| From 6c475f4bc2c323d75d40eb37386fbb86819791ec Mon Sep 17 00:00:00 2001 | ||||
| From: Hanna Reitz <hreitz@redhat.com> | ||||
| Date: Tue, 5 Apr 2022 15:46:52 +0200 | ||||
| Subject: [PATCH 10/11] qcow2: Add errp to rebuild_refcount_structure() | ||||
| 
 | ||||
| RH-Author: Hanna Reitz <hreitz@redhat.com> | ||||
| RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding | ||||
| RH-Commit: [3/4] 95a6b7bb558a9ed35afae3fa9fefd761312ecb3b | ||||
| RH-Bugzilla: 2072242 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Eric Blake <eblake@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| 
 | ||||
| Instead of fprint()-ing error messages in rebuild_refcount_structure() | ||||
| and its rebuild_refcounts_write_refblocks() helper, pass them through an | ||||
| Error object to qcow2_check_refcounts() (which will then print it). | ||||
| 
 | ||||
| Suggested-by: Eric Blake <eblake@redhat.com> | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| Message-Id: <20220405134652.19278-4-hreitz@redhat.com> | ||||
| Reviewed-by: Eric Blake <eblake@redhat.com> | ||||
| (cherry picked from commit 0423f75351ab83b844a31349218b0eadd830e07a) | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| ---
 | ||||
|  block/qcow2-refcount.c | 33 +++++++++++++++++++-------------- | ||||
|  1 file changed, 19 insertions(+), 14 deletions(-) | ||||
| 
 | ||||
| diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
 | ||||
| index 555d8ba5ac..09f8ef4927 100644
 | ||||
| --- a/block/qcow2-refcount.c
 | ||||
| +++ b/block/qcow2-refcount.c
 | ||||
| @@ -2462,7 +2462,8 @@ static int64_t alloc_clusters_imrt(BlockDriverState *bs,
 | ||||
|  static int rebuild_refcounts_write_refblocks( | ||||
|          BlockDriverState *bs, void **refcount_table, int64_t *nb_clusters, | ||||
|          int64_t first_cluster, int64_t end_cluster, | ||||
| -        uint64_t **on_disk_reftable_ptr, uint32_t *on_disk_reftable_entries_ptr
 | ||||
| +        uint64_t **on_disk_reftable_ptr, uint32_t *on_disk_reftable_entries_ptr,
 | ||||
| +        Error **errp
 | ||||
|      ) | ||||
|  { | ||||
|      BDRVQcow2State *s = bs->opaque; | ||||
| @@ -2513,8 +2514,8 @@ static int rebuild_refcounts_write_refblocks(
 | ||||
|                                                    nb_clusters, | ||||
|                                                    &first_free_cluster); | ||||
|              if (refblock_offset < 0) { | ||||
| -                fprintf(stderr, "ERROR allocating refblock: %s\n",
 | ||||
| -                        strerror(-refblock_offset));
 | ||||
| +                error_setg_errno(errp, -refblock_offset,
 | ||||
| +                                 "ERROR allocating refblock");
 | ||||
|                  return refblock_offset; | ||||
|              } | ||||
|   | ||||
| @@ -2536,6 +2537,7 @@ static int rebuild_refcounts_write_refblocks(
 | ||||
|                                    on_disk_reftable_entries * | ||||
|                                    REFTABLE_ENTRY_SIZE); | ||||
|                  if (!on_disk_reftable) { | ||||
| +                    error_setg(errp, "ERROR allocating reftable memory");
 | ||||
|                      return -ENOMEM; | ||||
|                  } | ||||
|   | ||||
| @@ -2559,7 +2561,7 @@ static int rebuild_refcounts_write_refblocks(
 | ||||
|          ret = qcow2_pre_write_overlap_check(bs, 0, refblock_offset, | ||||
|                                              s->cluster_size, false); | ||||
|          if (ret < 0) { | ||||
| -            fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret));
 | ||||
| +            error_setg_errno(errp, -ret, "ERROR writing refblock");
 | ||||
|              return ret; | ||||
|          } | ||||
|   | ||||
| @@ -2575,7 +2577,7 @@ static int rebuild_refcounts_write_refblocks(
 | ||||
|          ret = bdrv_pwrite(bs->file, refblock_offset, on_disk_refblock, | ||||
|                            s->cluster_size); | ||||
|          if (ret < 0) { | ||||
| -            fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret));
 | ||||
| +            error_setg_errno(errp, -ret, "ERROR writing refblock");
 | ||||
|              return ret; | ||||
|          } | ||||
|   | ||||
| @@ -2598,7 +2600,8 @@ static int rebuild_refcounts_write_refblocks(
 | ||||
|  static int rebuild_refcount_structure(BlockDriverState *bs, | ||||
|                                        BdrvCheckResult *res, | ||||
|                                        void **refcount_table, | ||||
| -                                      int64_t *nb_clusters)
 | ||||
| +                                      int64_t *nb_clusters,
 | ||||
| +                                      Error **errp)
 | ||||
|  { | ||||
|      BDRVQcow2State *s = bs->opaque; | ||||
|      int64_t reftable_offset = -1; | ||||
| @@ -2649,7 +2652,7 @@ static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
|          rebuild_refcounts_write_refblocks(bs, refcount_table, nb_clusters, | ||||
|                                            0, *nb_clusters, | ||||
|                                            &on_disk_reftable, | ||||
| -                                          &on_disk_reftable_entries);
 | ||||
| +                                          &on_disk_reftable_entries, errp);
 | ||||
|      if (reftable_size_changed < 0) { | ||||
|          res->check_errors++; | ||||
|          ret = reftable_size_changed; | ||||
| @@ -2673,8 +2676,8 @@ static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
|                                                refcount_table, nb_clusters, | ||||
|                                                &first_free_cluster); | ||||
|          if (reftable_offset < 0) { | ||||
| -            fprintf(stderr, "ERROR allocating reftable: %s\n",
 | ||||
| -                    strerror(-reftable_offset));
 | ||||
| +            error_setg_errno(errp, -reftable_offset,
 | ||||
| +                             "ERROR allocating reftable");
 | ||||
|              res->check_errors++; | ||||
|              ret = reftable_offset; | ||||
|              goto fail; | ||||
| @@ -2692,7 +2695,7 @@ static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
|                                                reftable_start_cluster, | ||||
|                                                reftable_end_cluster, | ||||
|                                                &on_disk_reftable, | ||||
| -                                              &on_disk_reftable_entries);
 | ||||
| +                                              &on_disk_reftable_entries, errp);
 | ||||
|          if (reftable_size_changed < 0) { | ||||
|              res->check_errors++; | ||||
|              ret = reftable_size_changed; | ||||
| @@ -2722,7 +2725,7 @@ static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
|      ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset, reftable_length, | ||||
|                                          false); | ||||
|      if (ret < 0) { | ||||
| -        fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret));
 | ||||
| +        error_setg_errno(errp, -ret, "ERROR writing reftable");
 | ||||
|          goto fail; | ||||
|      } | ||||
|   | ||||
| @@ -2730,7 +2733,7 @@ static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
|      ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable, | ||||
|                        reftable_length); | ||||
|      if (ret < 0) { | ||||
| -        fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret));
 | ||||
| +        error_setg_errno(errp, -ret, "ERROR writing reftable");
 | ||||
|          goto fail; | ||||
|      } | ||||
|   | ||||
| @@ -2743,7 +2746,7 @@ static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
|                             &reftable_offset_and_clusters, | ||||
|                             sizeof(reftable_offset_and_clusters)); | ||||
|      if (ret < 0) { | ||||
| -        fprintf(stderr, "ERROR setting reftable: %s\n", strerror(-ret));
 | ||||
| +        error_setg_errno(errp, -ret, "ERROR setting reftable");
 | ||||
|          goto fail; | ||||
|      } | ||||
|   | ||||
| @@ -2811,11 +2814,13 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
 | ||||
|      if (rebuild && (fix & BDRV_FIX_ERRORS)) { | ||||
|          BdrvCheckResult old_res = *res; | ||||
|          int fresh_leaks = 0; | ||||
| +        Error *local_err = NULL;
 | ||||
|   | ||||
|          fprintf(stderr, "Rebuilding refcount structure\n"); | ||||
|          ret = rebuild_refcount_structure(bs, res, &refcount_table, | ||||
| -                                         &nb_clusters);
 | ||||
| +                                         &nb_clusters, &local_err);
 | ||||
|          if (ret < 0) { | ||||
| +            error_report_err(local_err);
 | ||||
|              goto fail; | ||||
|          } | ||||
|   | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
							
								
								
									
										465
									
								
								SOURCES/kvm-qcow2-Improve-refcount-structure-rebuilding.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								SOURCES/kvm-qcow2-Improve-refcount-structure-rebuilding.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,465 @@ | ||||
| From 3daca05a8f845d2a389a6cf767314bcb72109578 Mon Sep 17 00:00:00 2001 | ||||
| From: Hanna Reitz <hreitz@redhat.com> | ||||
| Date: Tue, 5 Apr 2022 15:46:50 +0200 | ||||
| Subject: [PATCH 08/11] qcow2: Improve refcount structure rebuilding | ||||
| 
 | ||||
| RH-Author: Hanna Reitz <hreitz@redhat.com> | ||||
| RH-MergeRequest: 173: qcow2: Improve refcount structure rebuilding | ||||
| RH-Commit: [1/4] 586e7a0fc3cb7cc2296b544ffcef34d8395fa74c | ||||
| RH-Bugzilla: 2072242 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Eric Blake <eblake@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| 
 | ||||
| When rebuilding the refcount structures (when qemu-img check -r found | ||||
| errors with refcount = 0, but reference count > 0), the new refcount | ||||
| table defaults to being put at the image file end[1].  There is no good | ||||
| reason for that except that it means we will not have to rewrite any | ||||
| refblocks we already wrote to disk. | ||||
| 
 | ||||
| Changing the code to rewrite those refblocks is not too difficult, | ||||
| though, so let us do that.  That is beneficial for images on block | ||||
| devices, where we cannot really write beyond the end of the image file. | ||||
| 
 | ||||
| Use this opportunity to add extensive comments to the code, and refactor | ||||
| it a bit, getting rid of the backwards-jumping goto. | ||||
| 
 | ||||
| [1] Unless there is something allocated in the area pointed to by the | ||||
|     last refblock, so we have to write that refblock.  In that case, we | ||||
|     try to put the reftable in there. | ||||
| 
 | ||||
| Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1519071 | ||||
| Closes: https://gitlab.com/qemu-project/qemu/-/issues/941 | ||||
| Reviewed-by: Eric Blake <eblake@redhat.com> | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| Message-Id: <20220405134652.19278-2-hreitz@redhat.com> | ||||
| (cherry picked from commit a8c07ec287554dcefd33733f0e5888a281ddc95e) | ||||
| Signed-off-by: Hanna Reitz <hreitz@redhat.com> | ||||
| ---
 | ||||
|  block/qcow2-refcount.c | 332 +++++++++++++++++++++++++++++------------ | ||||
|  1 file changed, 235 insertions(+), 97 deletions(-) | ||||
| 
 | ||||
| diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
 | ||||
| index 4614572252..555d8ba5ac 100644
 | ||||
| --- a/block/qcow2-refcount.c
 | ||||
| +++ b/block/qcow2-refcount.c
 | ||||
| @@ -2435,111 +2435,140 @@ static int64_t alloc_clusters_imrt(BlockDriverState *bs,
 | ||||
|  } | ||||
|   | ||||
|  /* | ||||
| - * Creates a new refcount structure based solely on the in-memory information
 | ||||
| - * given through *refcount_table. All necessary allocations will be reflected
 | ||||
| - * in that array.
 | ||||
| + * Helper function for rebuild_refcount_structure().
 | ||||
|   * | ||||
| - * On success, the old refcount structure is leaked (it will be covered by the
 | ||||
| - * new refcount structure).
 | ||||
| + * Scan the range of clusters [first_cluster, end_cluster) for allocated
 | ||||
| + * clusters and write all corresponding refblocks to disk.  The refblock
 | ||||
| + * and allocation data is taken from the in-memory refcount table
 | ||||
| + * *refcount_table[] (of size *nb_clusters), which is basically one big
 | ||||
| + * (unlimited size) refblock for the whole image.
 | ||||
| + *
 | ||||
| + * For these refblocks, clusters are allocated using said in-memory
 | ||||
| + * refcount table.  Care is taken that these allocations are reflected
 | ||||
| + * in the refblocks written to disk.
 | ||||
| + *
 | ||||
| + * The refblocks' offsets are written into a reftable, which is
 | ||||
| + * *on_disk_reftable_ptr[] (of size *on_disk_reftable_entries_ptr).  If
 | ||||
| + * that reftable is of insufficient size, it will be resized to fit.
 | ||||
| + * This reftable is not written to disk.
 | ||||
| + *
 | ||||
| + * (If *on_disk_reftable_ptr is not NULL, the entries within are assumed
 | ||||
| + * to point to existing valid refblocks that do not need to be allocated
 | ||||
| + * again.)
 | ||||
| + *
 | ||||
| + * Return whether the on-disk reftable array was resized (true/false),
 | ||||
| + * or -errno on error.
 | ||||
|   */ | ||||
| -static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
| -                                      BdrvCheckResult *res,
 | ||||
| -                                      void **refcount_table,
 | ||||
| -                                      int64_t *nb_clusters)
 | ||||
| +static int rebuild_refcounts_write_refblocks(
 | ||||
| +        BlockDriverState *bs, void **refcount_table, int64_t *nb_clusters,
 | ||||
| +        int64_t first_cluster, int64_t end_cluster,
 | ||||
| +        uint64_t **on_disk_reftable_ptr, uint32_t *on_disk_reftable_entries_ptr
 | ||||
| +    )
 | ||||
|  { | ||||
|      BDRVQcow2State *s = bs->opaque; | ||||
| -    int64_t first_free_cluster = 0, reftable_offset = -1, cluster = 0;
 | ||||
| +    int64_t cluster;
 | ||||
|      int64_t refblock_offset, refblock_start, refblock_index; | ||||
| -    uint32_t reftable_size = 0;
 | ||||
| -    uint64_t *on_disk_reftable = NULL;
 | ||||
| +    int64_t first_free_cluster = 0;
 | ||||
| +    uint64_t *on_disk_reftable = *on_disk_reftable_ptr;
 | ||||
| +    uint32_t on_disk_reftable_entries = *on_disk_reftable_entries_ptr;
 | ||||
|      void *on_disk_refblock; | ||||
| -    int ret = 0;
 | ||||
| -    struct {
 | ||||
| -        uint64_t reftable_offset;
 | ||||
| -        uint32_t reftable_clusters;
 | ||||
| -    } QEMU_PACKED reftable_offset_and_clusters;
 | ||||
| -
 | ||||
| -    qcow2_cache_empty(bs, s->refcount_block_cache);
 | ||||
| +    bool reftable_grown = false;
 | ||||
| +    int ret;
 | ||||
|   | ||||
| -write_refblocks:
 | ||||
| -    for (; cluster < *nb_clusters; cluster++) {
 | ||||
| +    for (cluster = first_cluster; cluster < end_cluster; cluster++) {
 | ||||
| +        /* Check all clusters to find refblocks that contain non-zero entries */
 | ||||
|          if (!s->get_refcount(*refcount_table, cluster)) { | ||||
|              continue; | ||||
|          } | ||||
|   | ||||
| +        /*
 | ||||
| +         * This cluster is allocated, so we need to create a refblock
 | ||||
| +         * for it.  The data we will write to disk is just the
 | ||||
| +         * respective slice from *refcount_table, so it will contain
 | ||||
| +         * accurate refcounts for all clusters belonging to this
 | ||||
| +         * refblock.  After we have written it, we will therefore skip
 | ||||
| +         * all remaining clusters in this refblock.
 | ||||
| +         */
 | ||||
| +
 | ||||
|          refblock_index = cluster >> s->refcount_block_bits; | ||||
|          refblock_start = refblock_index << s->refcount_block_bits; | ||||
|   | ||||
| -        /* Don't allocate a cluster in a refblock already written to disk */
 | ||||
| -        if (first_free_cluster < refblock_start) {
 | ||||
| -            first_free_cluster = refblock_start;
 | ||||
| -        }
 | ||||
| -        refblock_offset = alloc_clusters_imrt(bs, 1, refcount_table,
 | ||||
| -                                              nb_clusters, &first_free_cluster);
 | ||||
| -        if (refblock_offset < 0) {
 | ||||
| -            fprintf(stderr, "ERROR allocating refblock: %s\n",
 | ||||
| -                    strerror(-refblock_offset));
 | ||||
| -            res->check_errors++;
 | ||||
| -            ret = refblock_offset;
 | ||||
| -            goto fail;
 | ||||
| -        }
 | ||||
| +        if (on_disk_reftable_entries > refblock_index &&
 | ||||
| +            on_disk_reftable[refblock_index])
 | ||||
| +        {
 | ||||
| +            /*
 | ||||
| +             * We can get here after a `goto write_refblocks`: We have a
 | ||||
| +             * reftable from a previous run, and the refblock is already
 | ||||
| +             * allocated.  No need to allocate it again.
 | ||||
| +             */
 | ||||
| +            refblock_offset = on_disk_reftable[refblock_index];
 | ||||
| +        } else {
 | ||||
| +            int64_t refblock_cluster_index;
 | ||||
|   | ||||
| -        if (reftable_size <= refblock_index) {
 | ||||
| -            uint32_t old_reftable_size = reftable_size;
 | ||||
| -            uint64_t *new_on_disk_reftable;
 | ||||
| +            /* Don't allocate a cluster in a refblock already written to disk */
 | ||||
| +            if (first_free_cluster < refblock_start) {
 | ||||
| +                first_free_cluster = refblock_start;
 | ||||
| +            }
 | ||||
| +            refblock_offset = alloc_clusters_imrt(bs, 1, refcount_table,
 | ||||
| +                                                  nb_clusters,
 | ||||
| +                                                  &first_free_cluster);
 | ||||
| +            if (refblock_offset < 0) {
 | ||||
| +                fprintf(stderr, "ERROR allocating refblock: %s\n",
 | ||||
| +                        strerror(-refblock_offset));
 | ||||
| +                return refblock_offset;
 | ||||
| +            }
 | ||||
|   | ||||
| -            reftable_size = ROUND_UP((refblock_index + 1) * REFTABLE_ENTRY_SIZE,
 | ||||
| -                                     s->cluster_size) / REFTABLE_ENTRY_SIZE;
 | ||||
| -            new_on_disk_reftable = g_try_realloc(on_disk_reftable,
 | ||||
| -                                                 reftable_size *
 | ||||
| -                                                 REFTABLE_ENTRY_SIZE);
 | ||||
| -            if (!new_on_disk_reftable) {
 | ||||
| -                res->check_errors++;
 | ||||
| -                ret = -ENOMEM;
 | ||||
| -                goto fail;
 | ||||
| +            refblock_cluster_index = refblock_offset / s->cluster_size;
 | ||||
| +            if (refblock_cluster_index >= end_cluster) {
 | ||||
| +                /*
 | ||||
| +                 * We must write the refblock that holds this refblock's
 | ||||
| +                 * refcount
 | ||||
| +                 */
 | ||||
| +                end_cluster = refblock_cluster_index + 1;
 | ||||
|              } | ||||
| -            on_disk_reftable = new_on_disk_reftable;
 | ||||
|   | ||||
| -            memset(on_disk_reftable + old_reftable_size, 0,
 | ||||
| -                   (reftable_size - old_reftable_size) * REFTABLE_ENTRY_SIZE);
 | ||||
| +            if (on_disk_reftable_entries <= refblock_index) {
 | ||||
| +                on_disk_reftable_entries =
 | ||||
| +                    ROUND_UP((refblock_index + 1) * REFTABLE_ENTRY_SIZE,
 | ||||
| +                             s->cluster_size) / REFTABLE_ENTRY_SIZE;
 | ||||
| +                on_disk_reftable =
 | ||||
| +                    g_try_realloc(on_disk_reftable,
 | ||||
| +                                  on_disk_reftable_entries *
 | ||||
| +                                  REFTABLE_ENTRY_SIZE);
 | ||||
| +                if (!on_disk_reftable) {
 | ||||
| +                    return -ENOMEM;
 | ||||
| +                }
 | ||||
|   | ||||
| -            /* The offset we have for the reftable is now no longer valid;
 | ||||
| -             * this will leak that range, but we can easily fix that by running
 | ||||
| -             * a leak-fixing check after this rebuild operation */
 | ||||
| -            reftable_offset = -1;
 | ||||
| -        } else {
 | ||||
| -            assert(on_disk_reftable);
 | ||||
| -        }
 | ||||
| -        on_disk_reftable[refblock_index] = refblock_offset;
 | ||||
| +                memset(on_disk_reftable + *on_disk_reftable_entries_ptr, 0,
 | ||||
| +                       (on_disk_reftable_entries -
 | ||||
| +                        *on_disk_reftable_entries_ptr) *
 | ||||
| +                       REFTABLE_ENTRY_SIZE);
 | ||||
|   | ||||
| -        /* If this is apparently the last refblock (for now), try to squeeze the
 | ||||
| -         * reftable in */
 | ||||
| -        if (refblock_index == (*nb_clusters - 1) >> s->refcount_block_bits &&
 | ||||
| -            reftable_offset < 0)
 | ||||
| -        {
 | ||||
| -            uint64_t reftable_clusters = size_to_clusters(s, reftable_size *
 | ||||
| -                                                          REFTABLE_ENTRY_SIZE);
 | ||||
| -            reftable_offset = alloc_clusters_imrt(bs, reftable_clusters,
 | ||||
| -                                                  refcount_table, nb_clusters,
 | ||||
| -                                                  &first_free_cluster);
 | ||||
| -            if (reftable_offset < 0) {
 | ||||
| -                fprintf(stderr, "ERROR allocating reftable: %s\n",
 | ||||
| -                        strerror(-reftable_offset));
 | ||||
| -                res->check_errors++;
 | ||||
| -                ret = reftable_offset;
 | ||||
| -                goto fail;
 | ||||
| +                *on_disk_reftable_ptr = on_disk_reftable;
 | ||||
| +                *on_disk_reftable_entries_ptr = on_disk_reftable_entries;
 | ||||
| +
 | ||||
| +                reftable_grown = true;
 | ||||
| +            } else {
 | ||||
| +                assert(on_disk_reftable);
 | ||||
|              } | ||||
| +            on_disk_reftable[refblock_index] = refblock_offset;
 | ||||
|          } | ||||
|   | ||||
| +        /* Refblock is allocated, write it to disk */
 | ||||
| +
 | ||||
|          ret = qcow2_pre_write_overlap_check(bs, 0, refblock_offset, | ||||
|                                              s->cluster_size, false); | ||||
|          if (ret < 0) { | ||||
|              fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret)); | ||||
| -            goto fail;
 | ||||
| +            return ret;
 | ||||
|          } | ||||
|   | ||||
| -        /* The size of *refcount_table is always cluster-aligned, therefore the
 | ||||
| -         * write operation will not overflow */
 | ||||
| +        /*
 | ||||
| +         * The refblock is simply a slice of *refcount_table.
 | ||||
| +         * Note that the size of *refcount_table is always aligned to
 | ||||
| +         * whole clusters, so the write operation will not result in
 | ||||
| +         * out-of-bounds accesses.
 | ||||
| +         */
 | ||||
|          on_disk_refblock = (void *)((char *) *refcount_table + | ||||
|                                      refblock_index * s->cluster_size); | ||||
|   | ||||
| @@ -2547,23 +2576,99 @@ write_refblocks:
 | ||||
|                            s->cluster_size); | ||||
|          if (ret < 0) { | ||||
|              fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret)); | ||||
| -            goto fail;
 | ||||
| +            return ret;
 | ||||
|          } | ||||
|   | ||||
| -        /* Go to the end of this refblock */
 | ||||
| +        /* This refblock is done, skip to its end */
 | ||||
|          cluster = refblock_start + s->refcount_block_size - 1; | ||||
|      } | ||||
|   | ||||
| -    if (reftable_offset < 0) {
 | ||||
| -        uint64_t post_refblock_start, reftable_clusters;
 | ||||
| +    return reftable_grown;
 | ||||
| +}
 | ||||
| +
 | ||||
| +/*
 | ||||
| + * Creates a new refcount structure based solely on the in-memory information
 | ||||
| + * given through *refcount_table (this in-memory information is basically just
 | ||||
| + * the concatenation of all refblocks).  All necessary allocations will be
 | ||||
| + * reflected in that array.
 | ||||
| + *
 | ||||
| + * On success, the old refcount structure is leaked (it will be covered by the
 | ||||
| + * new refcount structure).
 | ||||
| + */
 | ||||
| +static int rebuild_refcount_structure(BlockDriverState *bs,
 | ||||
| +                                      BdrvCheckResult *res,
 | ||||
| +                                      void **refcount_table,
 | ||||
| +                                      int64_t *nb_clusters)
 | ||||
| +{
 | ||||
| +    BDRVQcow2State *s = bs->opaque;
 | ||||
| +    int64_t reftable_offset = -1;
 | ||||
| +    int64_t reftable_length = 0;
 | ||||
| +    int64_t reftable_clusters;
 | ||||
| +    int64_t refblock_index;
 | ||||
| +    uint32_t on_disk_reftable_entries = 0;
 | ||||
| +    uint64_t *on_disk_reftable = NULL;
 | ||||
| +    int ret = 0;
 | ||||
| +    int reftable_size_changed = 0;
 | ||||
| +    struct {
 | ||||
| +        uint64_t reftable_offset;
 | ||||
| +        uint32_t reftable_clusters;
 | ||||
| +    } QEMU_PACKED reftable_offset_and_clusters;
 | ||||
| +
 | ||||
| +    qcow2_cache_empty(bs, s->refcount_block_cache);
 | ||||
| +
 | ||||
| +    /*
 | ||||
| +     * For each refblock containing entries, we try to allocate a
 | ||||
| +     * cluster (in the in-memory refcount table) and write its offset
 | ||||
| +     * into on_disk_reftable[].  We then write the whole refblock to
 | ||||
| +     * disk (as a slice of the in-memory refcount table).
 | ||||
| +     * This is done by rebuild_refcounts_write_refblocks().
 | ||||
| +     *
 | ||||
| +     * Once we have scanned all clusters, we try to find space for the
 | ||||
| +     * reftable.  This will dirty the in-memory refcount table (i.e.
 | ||||
| +     * make it differ from the refblocks we have already written), so we
 | ||||
| +     * need to run rebuild_refcounts_write_refblocks() again for the
 | ||||
| +     * range of clusters where the reftable has been allocated.
 | ||||
| +     *
 | ||||
| +     * This second run might make the reftable grow again, in which case
 | ||||
| +     * we will need to allocate another space for it, which is why we
 | ||||
| +     * repeat all this until the reftable stops growing.
 | ||||
| +     *
 | ||||
| +     * (This loop will terminate, because with every cluster the
 | ||||
| +     * reftable grows, it can accomodate a multitude of more refcounts,
 | ||||
| +     * so that at some point this must be able to cover the reftable
 | ||||
| +     * and all refblocks describing it.)
 | ||||
| +     *
 | ||||
| +     * We then convert the reftable to big-endian and write it to disk.
 | ||||
| +     *
 | ||||
| +     * Note that we never free any reftable allocations.  Doing so would
 | ||||
| +     * needlessly complicate the algorithm: The eventual second check
 | ||||
| +     * run we do will clean up all leaks we have caused.
 | ||||
| +     */
 | ||||
| +
 | ||||
| +    reftable_size_changed =
 | ||||
| +        rebuild_refcounts_write_refblocks(bs, refcount_table, nb_clusters,
 | ||||
| +                                          0, *nb_clusters,
 | ||||
| +                                          &on_disk_reftable,
 | ||||
| +                                          &on_disk_reftable_entries);
 | ||||
| +    if (reftable_size_changed < 0) {
 | ||||
| +        res->check_errors++;
 | ||||
| +        ret = reftable_size_changed;
 | ||||
| +        goto fail;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    /*
 | ||||
| +     * There was no reftable before, so rebuild_refcounts_write_refblocks()
 | ||||
| +     * must have increased its size (from 0 to something).
 | ||||
| +     */
 | ||||
| +    assert(reftable_size_changed);
 | ||||
| +
 | ||||
| +    do {
 | ||||
| +        int64_t reftable_start_cluster, reftable_end_cluster;
 | ||||
| +        int64_t first_free_cluster = 0;
 | ||||
| +
 | ||||
| +        reftable_length = on_disk_reftable_entries * REFTABLE_ENTRY_SIZE;
 | ||||
| +        reftable_clusters = size_to_clusters(s, reftable_length);
 | ||||
|   | ||||
| -        post_refblock_start = ROUND_UP(*nb_clusters, s->refcount_block_size);
 | ||||
| -        reftable_clusters =
 | ||||
| -            size_to_clusters(s, reftable_size * REFTABLE_ENTRY_SIZE);
 | ||||
| -        /* Not pretty but simple */
 | ||||
| -        if (first_free_cluster < post_refblock_start) {
 | ||||
| -            first_free_cluster = post_refblock_start;
 | ||||
| -        }
 | ||||
|          reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, | ||||
|                                                refcount_table, nb_clusters, | ||||
|                                                &first_free_cluster); | ||||
| @@ -2575,24 +2680,55 @@ write_refblocks:
 | ||||
|              goto fail; | ||||
|          } | ||||
|   | ||||
| -        goto write_refblocks;
 | ||||
| -    }
 | ||||
| +        /*
 | ||||
| +         * We need to update the affected refblocks, so re-run the
 | ||||
| +         * write_refblocks loop for the reftable's range of clusters.
 | ||||
| +         */
 | ||||
| +        assert(offset_into_cluster(s, reftable_offset) == 0);
 | ||||
| +        reftable_start_cluster = reftable_offset / s->cluster_size;
 | ||||
| +        reftable_end_cluster = reftable_start_cluster + reftable_clusters;
 | ||||
| +        reftable_size_changed =
 | ||||
| +            rebuild_refcounts_write_refblocks(bs, refcount_table, nb_clusters,
 | ||||
| +                                              reftable_start_cluster,
 | ||||
| +                                              reftable_end_cluster,
 | ||||
| +                                              &on_disk_reftable,
 | ||||
| +                                              &on_disk_reftable_entries);
 | ||||
| +        if (reftable_size_changed < 0) {
 | ||||
| +            res->check_errors++;
 | ||||
| +            ret = reftable_size_changed;
 | ||||
| +            goto fail;
 | ||||
| +        }
 | ||||
| +
 | ||||
| +        /*
 | ||||
| +         * If the reftable size has changed, we will need to find a new
 | ||||
| +         * allocation, repeating the loop.
 | ||||
| +         */
 | ||||
| +    } while (reftable_size_changed);
 | ||||
|   | ||||
| -    for (refblock_index = 0; refblock_index < reftable_size; refblock_index++) {
 | ||||
| +    /* The above loop must have run at least once */
 | ||||
| +    assert(reftable_offset >= 0);
 | ||||
| +
 | ||||
| +    /*
 | ||||
| +     * All allocations are done, all refblocks are written, convert the
 | ||||
| +     * reftable to big-endian and write it to disk.
 | ||||
| +     */
 | ||||
| +
 | ||||
| +    for (refblock_index = 0; refblock_index < on_disk_reftable_entries;
 | ||||
| +         refblock_index++)
 | ||||
| +    {
 | ||||
|          cpu_to_be64s(&on_disk_reftable[refblock_index]); | ||||
|      } | ||||
|   | ||||
| -    ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset,
 | ||||
| -                                        reftable_size * REFTABLE_ENTRY_SIZE,
 | ||||
| +    ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset, reftable_length,
 | ||||
|                                          false); | ||||
|      if (ret < 0) { | ||||
|          fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); | ||||
|          goto fail; | ||||
|      } | ||||
|   | ||||
| -    assert(reftable_size < INT_MAX / REFTABLE_ENTRY_SIZE);
 | ||||
| +    assert(reftable_length < INT_MAX);
 | ||||
|      ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable, | ||||
| -                      reftable_size * REFTABLE_ENTRY_SIZE);
 | ||||
| +                      reftable_length);
 | ||||
|      if (ret < 0) { | ||||
|          fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); | ||||
|          goto fail; | ||||
| @@ -2601,7 +2737,7 @@ write_refblocks:
 | ||||
|      /* Enter new reftable into the image header */ | ||||
|      reftable_offset_and_clusters.reftable_offset = cpu_to_be64(reftable_offset); | ||||
|      reftable_offset_and_clusters.reftable_clusters = | ||||
| -        cpu_to_be32(size_to_clusters(s, reftable_size * REFTABLE_ENTRY_SIZE));
 | ||||
| +        cpu_to_be32(reftable_clusters);
 | ||||
|      ret = bdrv_pwrite_sync(bs->file, | ||||
|                             offsetof(QCowHeader, refcount_table_offset), | ||||
|                             &reftable_offset_and_clusters, | ||||
| @@ -2611,12 +2747,14 @@ write_refblocks:
 | ||||
|          goto fail; | ||||
|      } | ||||
|   | ||||
| -    for (refblock_index = 0; refblock_index < reftable_size; refblock_index++) {
 | ||||
| +    for (refblock_index = 0; refblock_index < on_disk_reftable_entries;
 | ||||
| +         refblock_index++)
 | ||||
| +    {
 | ||||
|          be64_to_cpus(&on_disk_reftable[refblock_index]); | ||||
|      } | ||||
|      s->refcount_table = on_disk_reftable; | ||||
|      s->refcount_table_offset = reftable_offset; | ||||
| -    s->refcount_table_size = reftable_size;
 | ||||
| +    s->refcount_table_size = on_disk_reftable_entries;
 | ||||
|      update_max_refcount_table_index(s); | ||||
|   | ||||
|      return 0; | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,176 @@ | ||||
| From b1eae36683cdfe63af5749b5fe86b1c08fc0f63e Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@redhat.com> | ||||
| Date: Wed, 13 Apr 2022 14:51:06 -0400 | ||||
| Subject: [PATCH 04/11] softmmu/physmem: Introduce MemTxAttrs::memory field and | ||||
|  MEMTX_ACCESS_ERROR | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 158: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR | ||||
| RH-Commit: [3/3] 84d64fe85a106f8faf579e43266d4349fc8e65b4 (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2075686 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| RH-Acked-by: Peter Xu <peterx@redhat.com> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075686 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2021-3750 | ||||
| Conflicts: memalign.h has not been introduced in this version. Instead, | ||||
|            we include osdep.h where the function prototypes are to be | ||||
|            found. | ||||
| 
 | ||||
| commit 3ab6fdc91b72e156da22848f0003ff4225690ced | ||||
| Author: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||
| Date:   Wed Dec 15 19:24:21 2021 +0100 | ||||
| 
 | ||||
|     softmmu/physmem: Introduce MemTxAttrs::memory field and MEMTX_ACCESS_ERROR | ||||
| 
 | ||||
|     Add the 'memory' bit to the memory attributes to restrict bus | ||||
|     controller accesses to memories. | ||||
| 
 | ||||
|     Introduce flatview_access_allowed() to check bus permission | ||||
|     before running any bus transaction. | ||||
| 
 | ||||
|     Have read/write accessors return MEMTX_ACCESS_ERROR if an access is | ||||
|     restricted. | ||||
| 
 | ||||
|     There is no change for the default case where 'memory' is not set. | ||||
| 
 | ||||
|     Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||
|     Message-Id: <20211215182421.418374-4-philmd@redhat.com> | ||||
|     Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||||
|     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
|     [thuth: Replaced MEMTX_BUS_ERROR with MEMTX_ACCESS_ERROR, remove "inline"] | ||||
|     Signed-off-by: Thomas Huth <thuth@redhat.com> | ||||
| 
 | ||||
| (cherry picked from commit 3ab6fdc91b72e156da22848f0003ff4225690ced) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  include/exec/memattrs.h |  9 +++++++++ | ||||
|  softmmu/physmem.c       | 45 +++++++++++++++++++++++++++++++++++++++-- | ||||
|  2 files changed, 52 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
 | ||||
| index 95f2d20d55..9fb98bc1ef 100644
 | ||||
| --- a/include/exec/memattrs.h
 | ||||
| +++ b/include/exec/memattrs.h
 | ||||
| @@ -35,6 +35,14 @@ typedef struct MemTxAttrs {
 | ||||
|      unsigned int secure:1; | ||||
|      /* Memory access is usermode (unprivileged) */ | ||||
|      unsigned int user:1; | ||||
| +    /*
 | ||||
| +     * Bus interconnect and peripherals can access anything (memories,
 | ||||
| +     * devices) by default. By setting the 'memory' bit, bus transaction
 | ||||
| +     * are restricted to "normal" memories (per the AMBA documentation)
 | ||||
| +     * versus devices. Access to devices will be logged and rejected
 | ||||
| +     * (see MEMTX_ACCESS_ERROR).
 | ||||
| +     */
 | ||||
| +    unsigned int memory:1;
 | ||||
|      /* Requester ID (for MSI for example) */ | ||||
|      unsigned int requester_id:16; | ||||
|      /* Invert endianness for this page */ | ||||
| @@ -66,6 +74,7 @@ typedef struct MemTxAttrs {
 | ||||
|  #define MEMTX_OK 0 | ||||
|  #define MEMTX_ERROR             (1U << 0) /* device returned an error */ | ||||
|  #define MEMTX_DECODE_ERROR      (1U << 1) /* nothing at that address */ | ||||
| +#define MEMTX_ACCESS_ERROR      (1U << 2) /* access denied */
 | ||||
|  typedef uint32_t MemTxResult; | ||||
|   | ||||
|  #endif | ||||
| diff --git a/softmmu/physmem.c b/softmmu/physmem.c
 | ||||
| index 483a31be81..4d0ef5f92f 100644
 | ||||
| --- a/softmmu/physmem.c
 | ||||
| +++ b/softmmu/physmem.c
 | ||||
| @@ -41,6 +41,8 @@
 | ||||
|  #include "qemu/config-file.h" | ||||
|  #include "qemu/error-report.h" | ||||
|  #include "qemu/qemu-print.h" | ||||
| +#include "qemu/log.h"
 | ||||
| +#include "qemu/osdep.h"
 | ||||
|  #include "exec/memory.h" | ||||
|  #include "exec/ioport.h" | ||||
|  #include "sysemu/dma.h" | ||||
| @@ -2759,6 +2761,33 @@ static bool prepare_mmio_access(MemoryRegion *mr)
 | ||||
|      return release_lock; | ||||
|  } | ||||
|   | ||||
| +/**
 | ||||
| + * flatview_access_allowed
 | ||||
| + * @mr: #MemoryRegion to be accessed
 | ||||
| + * @attrs: memory transaction attributes
 | ||||
| + * @addr: address within that memory region
 | ||||
| + * @len: the number of bytes to access
 | ||||
| + *
 | ||||
| + * Check if a memory transaction is allowed.
 | ||||
| + *
 | ||||
| + * Returns: true if transaction is allowed, false if denied.
 | ||||
| + */
 | ||||
| +static bool flatview_access_allowed(MemoryRegion *mr, MemTxAttrs attrs,
 | ||||
| +                                    hwaddr addr, hwaddr len)
 | ||||
| +{
 | ||||
| +    if (likely(!attrs.memory)) {
 | ||||
| +        return true;
 | ||||
| +    }
 | ||||
| +    if (memory_region_is_ram(mr)) {
 | ||||
| +        return true;
 | ||||
| +    }
 | ||||
| +    qemu_log_mask(LOG_GUEST_ERROR,
 | ||||
| +                  "Invalid access to non-RAM device at "
 | ||||
| +                  "addr 0x%" HWADDR_PRIX ", size %" HWADDR_PRIu ", "
 | ||||
| +                  "region '%s'\n", addr, len, memory_region_name(mr));
 | ||||
| +    return false;
 | ||||
| +}
 | ||||
| +
 | ||||
|  /* Called within RCU critical section.  */ | ||||
|  static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr, | ||||
|                                             MemTxAttrs attrs, | ||||
| @@ -2773,7 +2802,10 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
 | ||||
|      const uint8_t *buf = ptr; | ||||
|   | ||||
|      for (;;) { | ||||
| -        if (!memory_access_is_direct(mr, true)) {
 | ||||
| +        if (!flatview_access_allowed(mr, attrs, addr1, l)) {
 | ||||
| +            result |= MEMTX_ACCESS_ERROR;
 | ||||
| +            /* Keep going. */
 | ||||
| +        } else if (!memory_access_is_direct(mr, true)) {
 | ||||
|              release_lock |= prepare_mmio_access(mr); | ||||
|              l = memory_access_size(mr, l, addr1); | ||||
|              /* XXX: could force current_cpu to NULL to avoid | ||||
| @@ -2818,6 +2850,9 @@ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
 | ||||
|   | ||||
|      l = len; | ||||
|      mr = flatview_translate(fv, addr, &addr1, &l, true, attrs); | ||||
| +    if (!flatview_access_allowed(mr, attrs, addr, len)) {
 | ||||
| +        return MEMTX_ACCESS_ERROR;
 | ||||
| +    }
 | ||||
|      return flatview_write_continue(fv, addr, attrs, buf, len, | ||||
|                                     addr1, l, mr); | ||||
|  } | ||||
| @@ -2836,7 +2871,10 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
 | ||||
|   | ||||
|      fuzz_dma_read_cb(addr, len, mr); | ||||
|      for (;;) { | ||||
| -        if (!memory_access_is_direct(mr, false)) {
 | ||||
| +        if (!flatview_access_allowed(mr, attrs, addr1, l)) {
 | ||||
| +            result |= MEMTX_ACCESS_ERROR;
 | ||||
| +            /* Keep going. */
 | ||||
| +        } else if (!memory_access_is_direct(mr, false)) {
 | ||||
|              /* I/O case */ | ||||
|              release_lock |= prepare_mmio_access(mr); | ||||
|              l = memory_access_size(mr, l, addr1); | ||||
| @@ -2879,6 +2917,9 @@ static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
 | ||||
|   | ||||
|      l = len; | ||||
|      mr = flatview_translate(fv, addr, &addr1, &l, false, attrs); | ||||
| +    if (!flatview_access_allowed(mr, attrs, addr, len)) {
 | ||||
| +        return MEMTX_ACCESS_ERROR;
 | ||||
| +    }
 | ||||
|      return flatview_read_continue(fv, addr, attrs, buf, len, | ||||
|                                    addr1, l, mr); | ||||
|  } | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,81 @@ | ||||
| From b570eb3a78a3096af55979ce63d96f5fc012f9e5 Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@redhat.com> | ||||
| Date: Wed, 13 Apr 2022 14:51:06 -0400 | ||||
| Subject: [PATCH 03/11] softmmu/physmem: Simplify flatview_write and | ||||
|  address_space_access_valid | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 158: hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR | ||||
| RH-Commit: [2/3] 66281d1c439be549c7890a662a817dd1b9367ef2 (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2075686 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| RH-Acked-by: Peter Xu <peterx@redhat.com> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075686 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2021-3750 | ||||
| 
 | ||||
| commit 58e74682baf4e1ad26b064d8c02e5bc99c75c5d9 | ||||
| Author: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||
| Date:   Wed Dec 15 19:24:20 2021 +0100 | ||||
| 
 | ||||
|     softmmu/physmem: Simplify flatview_write and address_space_access_valid | ||||
| 
 | ||||
|     Remove unuseful local 'result' variables. | ||||
| 
 | ||||
|     Reviewed-by: Peter Xu <peterx@redhat.com> | ||||
|     Reviewed-by: David Hildenbrand <david@redhat.com> | ||||
|     Reviewed-by: Alexander Bulekov <alxndr@bu.edu> | ||||
|     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
|     Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||
|     Message-Id: <20211215182421.418374-3-philmd@redhat.com> | ||||
|     Signed-off-by: Thomas Huth <thuth@redhat.com> | ||||
| 
 | ||||
| (cherry picked from commit 58e74682baf4e1ad26b064d8c02e5bc99c75c5d9) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  softmmu/physmem.c | 11 +++-------- | ||||
|  1 file changed, 3 insertions(+), 8 deletions(-) | ||||
| 
 | ||||
| diff --git a/softmmu/physmem.c b/softmmu/physmem.c
 | ||||
| index 3524c04c2a..483a31be81 100644
 | ||||
| --- a/softmmu/physmem.c
 | ||||
| +++ b/softmmu/physmem.c
 | ||||
| @@ -2815,14 +2815,11 @@ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
 | ||||
|      hwaddr l; | ||||
|      hwaddr addr1; | ||||
|      MemoryRegion *mr; | ||||
| -    MemTxResult result = MEMTX_OK;
 | ||||
|   | ||||
|      l = len; | ||||
|      mr = flatview_translate(fv, addr, &addr1, &l, true, attrs); | ||||
| -    result = flatview_write_continue(fv, addr, attrs, buf, len,
 | ||||
| -                                     addr1, l, mr);
 | ||||
| -
 | ||||
| -    return result;
 | ||||
| +    return flatview_write_continue(fv, addr, attrs, buf, len,
 | ||||
| +                                   addr1, l, mr);
 | ||||
|  } | ||||
|   | ||||
|  /* Called within RCU critical section.  */ | ||||
| @@ -3119,12 +3116,10 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr,
 | ||||
|                                  MemTxAttrs attrs) | ||||
|  { | ||||
|      FlatView *fv; | ||||
| -    bool result;
 | ||||
|   | ||||
|      RCU_READ_LOCK_GUARD(); | ||||
|      fv = address_space_to_flatview(as); | ||||
| -    result = flatview_access_valid(fv, addr, len, is_write, attrs);
 | ||||
| -    return result;
 | ||||
| +    return flatview_access_valid(fv, addr, len, is_write, attrs);
 | ||||
|  } | ||||
|   | ||||
|  static hwaddr | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,105 @@ | ||||
| From 0a493615833edbe6448bc639200b4a5fa7d492e3 Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@redhat.com> | ||||
| Date: Wed, 4 May 2022 10:35:17 -0400 | ||||
| Subject: [PATCH 2/2] ui/cursor: fix integer overflow in cursor_alloc | ||||
|  (CVE-2021-4206) | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 190: ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206) | ||||
| RH-Commit: [1/1] 80588f646942c345a2491812cb41aacd4c0805ff (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2082622 | ||||
| RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||
| RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||
| RH-Acked-by: Mauro Matteo Cascella <None> | ||||
| 
 | ||||
| BZ: https://bugzilla.redhat.com/show_bug.cgi?id=2082622 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2021-4206 | ||||
| 
 | ||||
| commit fa892e9abb728e76afcf27323ab29c57fb0fe7aa | ||||
| Author: Mauro Matteo Cascella <mcascell@redhat.com> | ||||
| Date:   Thu Apr 7 10:17:12 2022 +0200 | ||||
| 
 | ||||
|     ui/cursor: fix integer overflow in cursor_alloc (CVE-2021-4206) | ||||
| 
 | ||||
|     Prevent potential integer overflow by limiting 'width' and 'height' to | ||||
|     512x512. Also change 'datasize' type to size_t. Refer to security | ||||
|     advisory https://starlabs.sg/advisories/22-4206/ for more information. | ||||
| 
 | ||||
|     Fixes: CVE-2021-4206 | ||||
|     Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com> | ||||
|     Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||
|     Message-Id: <20220407081712.345609-1-mcascell@redhat.com> | ||||
|     Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> | ||||
| 
 | ||||
| (cherry picked from commit fa892e9abb728e76afcf27323ab29c57fb0fe7aa) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  hw/display/qxl-render.c | 7 +++++++ | ||||
|  hw/display/vmware_vga.c | 2 ++ | ||||
|  ui/cursor.c             | 8 +++++++- | ||||
|  3 files changed, 16 insertions(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
 | ||||
| index 237ed293ba..ca217004bf 100644
 | ||||
| --- a/hw/display/qxl-render.c
 | ||||
| +++ b/hw/display/qxl-render.c
 | ||||
| @@ -247,6 +247,13 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
 | ||||
|      size_t size; | ||||
|   | ||||
|      c = cursor_alloc(cursor->header.width, cursor->header.height); | ||||
| +
 | ||||
| +    if (!c) {
 | ||||
| +        qxl_set_guest_bug(qxl, "%s: cursor %ux%u alloc error", __func__,
 | ||||
| +                cursor->header.width, cursor->header.height);
 | ||||
| +        goto fail;
 | ||||
| +    }
 | ||||
| +
 | ||||
|      c->hot_x = cursor->header.hot_spot_x; | ||||
|      c->hot_y = cursor->header.hot_spot_y; | ||||
|      switch (cursor->header.type) { | ||||
| diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
 | ||||
| index e2969a6c81..2b81d6122f 100644
 | ||||
| --- a/hw/display/vmware_vga.c
 | ||||
| +++ b/hw/display/vmware_vga.c
 | ||||
| @@ -509,6 +509,8 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
 | ||||
|      int i, pixels; | ||||
|   | ||||
|      qc = cursor_alloc(c->width, c->height); | ||||
| +    assert(qc != NULL);
 | ||||
| +
 | ||||
|      qc->hot_x = c->hot_x; | ||||
|      qc->hot_y = c->hot_y; | ||||
|      switch (c->bpp) { | ||||
| diff --git a/ui/cursor.c b/ui/cursor.c
 | ||||
| index 1d62ddd4d0..835f0802f9 100644
 | ||||
| --- a/ui/cursor.c
 | ||||
| +++ b/ui/cursor.c
 | ||||
| @@ -46,6 +46,8 @@ static QEMUCursor *cursor_parse_xpm(const char *xpm[])
 | ||||
|   | ||||
|      /* parse pixel data */ | ||||
|      c = cursor_alloc(width, height); | ||||
| +    assert(c != NULL);
 | ||||
| +
 | ||||
|      for (pixel = 0, y = 0; y < height; y++, line++) { | ||||
|          for (x = 0; x < height; x++, pixel++) { | ||||
|              idx = xpm[line][x]; | ||||
| @@ -91,7 +93,11 @@ QEMUCursor *cursor_builtin_left_ptr(void)
 | ||||
|  QEMUCursor *cursor_alloc(int width, int height) | ||||
|  { | ||||
|      QEMUCursor *c; | ||||
| -    int datasize = width * height * sizeof(uint32_t);
 | ||||
| +    size_t datasize = width * height * sizeof(uint32_t);
 | ||||
| +
 | ||||
| +    if (width > 512 || height > 512) {
 | ||||
| +        return NULL;
 | ||||
| +    }
 | ||||
|   | ||||
|      c = g_malloc0(sizeof(QEMUCursor) + datasize); | ||||
|      c->width  = width; | ||||
| -- 
 | ||||
| 2.35.3 | ||||
| 
 | ||||
| @ -0,0 +1,78 @@ | ||||
| From 2abf617accf878bec7f1c0419d5b85c93b0aa426 Mon Sep 17 00:00:00 2001 | ||||
| From: Jon Maloy <jmaloy@rehat.com> | ||||
| Date: Thu, 14 Apr 2022 10:38:26 -0400 | ||||
| Subject: [PATCH 07/11] vhost-vsock: detach the virqueue element in case of | ||||
|  error | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 168: vhost-vsock: detach the virqueue element in case of error | ||||
| RH-Commit: [1/1] f81a39d26a7165f8b717fdeeb9526081cb73129b (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2075639 | ||||
| RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com> | ||||
| RH-Acked-by: Jason Wang <jasowang@redhat.com> | ||||
| RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075639 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2022-26354 | ||||
| 
 | ||||
| commit 8d1b247f3748ac4078524130c6d7ae42b6140aaf | ||||
| Author: Stefano Garzarella <sgarzare@redhat.com> | ||||
| Date:   Mon Feb 28 10:50:58 2022 +0100 | ||||
| 
 | ||||
|     vhost-vsock: detach the virqueue element in case of error | ||||
| 
 | ||||
|     In vhost_vsock_common_send_transport_reset(), if an element popped from | ||||
|     the virtqueue is invalid, we should call virtqueue_detach_element() to | ||||
|     detach it from the virtqueue before freeing its memory. | ||||
| 
 | ||||
|     Fixes: fc0b9b0e1c ("vhost-vsock: add virtio sockets device") | ||||
|     Fixes: CVE-2022-26354 | ||||
|     Cc: qemu-stable@nongnu.org | ||||
|     Reported-by: VictorV <vv474172261@gmail.com> | ||||
|     Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> | ||||
|     Message-Id: <20220228095058.27899-1-sgarzare@redhat.com> | ||||
|     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||
|     Reviewed-by: Michael S. Tsirkin <mst@redhat.com> | ||||
|     Signed-off-by: Michael S. Tsirkin <mst@redhat.com> | ||||
| 
 | ||||
| (cherry picked from commit 8d1b247f3748ac4078524130c6d7ae42b6140aaf) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  hw/virtio/vhost-vsock-common.c | 10 +++++++--- | ||||
|  1 file changed, 7 insertions(+), 3 deletions(-) | ||||
| 
 | ||||
| diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
 | ||||
| index 3f3771274e..ed706681ac 100644
 | ||||
| --- a/hw/virtio/vhost-vsock-common.c
 | ||||
| +++ b/hw/virtio/vhost-vsock-common.c
 | ||||
| @@ -153,19 +153,23 @@ static void vhost_vsock_common_send_transport_reset(VHostVSockCommon *vvc)
 | ||||
|      if (elem->out_num) { | ||||
|          error_report("invalid vhost-vsock event virtqueue element with " | ||||
|                       "out buffers"); | ||||
| -        goto out;
 | ||||
| +        goto err;
 | ||||
|      } | ||||
|   | ||||
|      if (iov_from_buf(elem->in_sg, elem->in_num, 0, | ||||
|                       &event, sizeof(event)) != sizeof(event)) { | ||||
|          error_report("vhost-vsock event virtqueue element is too short"); | ||||
| -        goto out;
 | ||||
| +        goto err;
 | ||||
|      } | ||||
|   | ||||
|      virtqueue_push(vq, elem, sizeof(event)); | ||||
|      virtio_notify(VIRTIO_DEVICE(vvc), vq); | ||||
|   | ||||
| -out:
 | ||||
| +    g_free(elem);
 | ||||
| +    return;
 | ||||
| +
 | ||||
| +err:
 | ||||
| +    virtqueue_detach_element(vq, elem, 0);
 | ||||
|      g_free(elem); | ||||
|  } | ||||
|   | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -0,0 +1,63 @@ | ||||
| From ba9806fd38f113deb452156fdc644407f061311c Mon Sep 17 00:00:00 2001 | ||||
| From: Jason Wang <jasowang@redhat.com> | ||||
| Date: Tue, 8 Mar 2022 10:42:51 +0800 | ||||
| Subject: [PATCH 06/11] virtio-net: fix map leaking on error during receive | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||
| RH-MergeRequest: 165: virtio-net: fix map leaking on error during receive | ||||
| RH-Commit: [1/1] f0546c74a5bfd37de473703f6a7c6f8f29fb0831 (jmaloy/qemu-kvm) | ||||
| RH-Bugzilla: 2075637 | ||||
| RH-Acked-by: Mauro Matteo Cascella <None> | ||||
| RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||
| RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com> | ||||
| 
 | ||||
| Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2075637 | ||||
| Upstream: Merged | ||||
| CVE: CVE-2022-26353 | ||||
| 
 | ||||
| commit abe300d9d894f7138e1af7c8e9c88c04bfe98b37 | ||||
| Author: Jason Wang <jasowang@redhat.com> | ||||
| Date:   Tue Mar 8 10:42:51 2022 +0800 | ||||
| 
 | ||||
|     virtio-net: fix map leaking on error during receive | ||||
| 
 | ||||
|     Commit bedd7e93d0196 ("virtio-net: fix use after unmap/free for sg") | ||||
|     tries to fix the use after free of the sg by caching the virtqueue | ||||
|     elements in an array and unmap them at once after receiving the | ||||
|     packets, But it forgot to unmap the cached elements on error which | ||||
|     will lead to leaking of mapping and other unexpected results. | ||||
| 
 | ||||
|     Fixing this by detaching the cached elements on error. This addresses | ||||
|     CVE-2022-26353. | ||||
| 
 | ||||
|     Reported-by: Victor Tom <vv474172261@gmail.com> | ||||
|     Cc: qemu-stable@nongnu.org | ||||
|     Fixes: CVE-2022-26353 | ||||
|     Fixes: bedd7e93d0196 ("virtio-net: fix use after unmap/free for sg") | ||||
|     Reviewed-by: Michael S. Tsirkin <mst@redhat.com> | ||||
|     Signed-off-by: Jason Wang <jasowang@redhat.com> | ||||
| 
 | ||||
| (cherry picked from commit abe300d9d894f7138e1af7c8e9c88c04bfe98b37) | ||||
| Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||
| ---
 | ||||
|  hw/net/virtio-net.c | 1 + | ||||
|  1 file changed, 1 insertion(+) | ||||
| 
 | ||||
| diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
 | ||||
| index f2014d5ea0..e1f4748831 100644
 | ||||
| --- a/hw/net/virtio-net.c
 | ||||
| +++ b/hw/net/virtio-net.c
 | ||||
| @@ -1862,6 +1862,7 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
 | ||||
|   | ||||
|  err: | ||||
|      for (j = 0; j < i; j++) { | ||||
| +        virtqueue_detach_element(q->rx_vq, elems[j], lens[j]);
 | ||||
|          g_free(elems[j]); | ||||
|      } | ||||
|   | ||||
| -- 
 | ||||
| 2.27.0 | ||||
| 
 | ||||
| @ -83,7 +83,7 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} | ||||
| Summary: QEMU is a machine emulator and virtualizer | ||||
| Name: qemu-kvm | ||||
| Version: 6.2.0 | ||||
| Release: 11%{?rcrel}%{?dist} | ||||
| Release: 11%{?rcrel}%{?dist}.2 | ||||
| # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped | ||||
| Epoch: 15 | ||||
| License: GPLv2 and GPLv2+ and CC-BY | ||||
| @ -242,6 +242,32 @@ Patch70: kvm-tests-acpi-update-expected-blobs.patch | ||||
| Patch71: kvm-tests-acpi-test-short-OEM_ID-OEM_TABLE_ID-values-in-.patch | ||||
| # For bz#1975840 - Windows guest hangs after updating and restarting from the guest OS | ||||
| Patch72: kvm-target-i386-properly-reset-TSC-on-reset.patch | ||||
| # For bz#2071103 - RHEL 9.0 guest with vsock device migration failed from RHEL 9.0 > RHEL 8.6 [rhel-8.6.0.z] | ||||
| Patch73: kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch | ||||
| # For bz#2075686 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z] | ||||
| Patch74: kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch | ||||
| # For bz#2075686 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z] | ||||
| Patch75: kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch | ||||
| # For bz#2075686 - CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z] | ||||
| Patch76: kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch | ||||
| # For bz#2075683 - CVE-2021-4207 virt:rhel/qemu-kvm: QEMU: QXL: double fetch in qxl_cursor() can lead to heap buffer overflow [rhel-8] [rhel-8.6.0.z] | ||||
| Patch77: kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch | ||||
| # For bz#2075637 - CVE-2022-26353 virt:rhel/qemu-kvm: QEMU: virtio-net: map leaking on error during receive [rhel-8] [rhel-8.6.0.z] | ||||
| Patch78: kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch | ||||
| # For bz#2075639 - CVE-2022-26354 virt:rhel/qemu-kvm: QEMU: vhost-vsock: missing virtqueue detach on error can lead to memory leak [rhel-8] [rhel-8.6.0.z] | ||||
| Patch79: kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch | ||||
| # For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] | ||||
| Patch80: kvm-qcow2-Improve-refcount-structure-rebuilding.patch | ||||
| # For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] | ||||
| Patch81: kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch | ||||
| # For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] | ||||
| Patch82: kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch | ||||
| # For bz#2072242 - Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z] | ||||
| Patch83: kvm-iotests-108-Fix-when-missing-user_allow_other.patch | ||||
| # For bz#2077928 - Remove upstream-only devices from the qemu-kvm binary [rhel-8.6.0.z] | ||||
| Patch84: kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch | ||||
| # For bz#2082622 - CVE-2021-4206 virt:rhel/qemu-kvm: QEMU: QXL: integer overflow in cursor_alloc() can lead to heap buffer overflow [rhel-8.6.0.z] | ||||
| Patch85: kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch | ||||
| 
 | ||||
| 
 | ||||
| BuildRequires: wget | ||||
| @ -1411,6 +1437,39 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : | ||||
| 
 | ||||
| 
 | ||||
| %changelog | ||||
| * Wed Jun 15 2022 Jon Maloy <jmaloy@redhat.com> - 6.2.0-11.el8_6.2 | ||||
| - kvm-Revert-redhat-Add-some-devices-for-exporting-upstrea.patch [bz#2077928] | ||||
| - kvm-ui-cursor-fix-integer-overflow-in-cursor_alloc-CVE-2.patch [bz#2082622] | ||||
| - Resolves: bz#2077928 | ||||
|   (Remove upstream-only devices from the qemu-kvm binary [rhel-8.6.0.z]) | ||||
| - Resolves: bz#2082622 | ||||
|   (CVE-2021-4206 virt:rhel/qemu-kvm: QEMU: QXL: integer overflow in cursor_alloc() can lead to heap buffer overflow [rhel-8.6.0.z]) | ||||
| 
 | ||||
| * Wed May 25 2022 Jon Maloy <jmaloy@redhat.com> - 6.2.0-11.el8_6.1 | ||||
| - kvm-RHEL-disable-seqpacket-for-vhost-vsock-device-in-rhe.patch [bz#2071103] | ||||
| - kvm-hw-intc-arm_gicv3-Check-for-MEMTX_OK-instead-of-MEMT.patch [bz#2075686] | ||||
| - kvm-softmmu-physmem-Simplify-flatview_write-and-address_.patch [bz#2075686] | ||||
| - kvm-softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch [bz#2075686] | ||||
| - kvm-display-qxl-render-fix-race-condition-in-qxl_cursor-.patch [bz#2075683] | ||||
| - kvm-virtio-net-fix-map-leaking-on-error-during-receive.patch [bz#2075637] | ||||
| - kvm-vhost-vsock-detach-the-virqueue-element-in-case-of-e.patch [bz#2075639] | ||||
| - kvm-qcow2-Improve-refcount-structure-rebuilding.patch [bz#2072242] | ||||
| - kvm-iotests-108-Test-new-refcount-rebuild-algorithm.patch [bz#2072242] | ||||
| - kvm-qcow2-Add-errp-to-rebuild_refcount_structure.patch [bz#2072242] | ||||
| - kvm-iotests-108-Fix-when-missing-user_allow_other.patch [bz#2072242] | ||||
| - Resolves: bz#2071103 | ||||
|   (RHEL 9.0 guest with vsock device migration failed from RHEL 9.0 > RHEL 8.6 [rhel-8.6.0.z]) | ||||
| - Resolves: bz#2075686 | ||||
|   (CVE-2021-3750 virt:rhel/qemu-kvm: QEMU: hcd-ehci: DMA reentrancy issue leads to use-after-free [rhel-8] [rhel-8.6.0.z]) | ||||
| - Resolves: bz#2075683 | ||||
|   (CVE-2021-4207 virt:rhel/qemu-kvm: QEMU: QXL: double fetch in qxl_cursor() can lead to heap buffer overflow [rhel-8] [rhel-8.6.0.z]) | ||||
| - Resolves: bz#2075637 | ||||
|   (CVE-2022-26353 virt:rhel/qemu-kvm: QEMU: virtio-net: map leaking on error during receive [rhel-8] [rhel-8.6.0.z]) | ||||
| - Resolves: bz#2075639 | ||||
|   (CVE-2022-26354 virt:rhel/qemu-kvm: QEMU: vhost-vsock: missing virtqueue detach on error can lead to memory leak [rhel-8] [rhel-8.6.0.z]) | ||||
| - Resolves: bz#2072242 | ||||
|   (Fail to rebuild the reference count tables of qcow2 image on host block devices (e.g. LVs) [rhel-8.6.0.z]) | ||||
| 
 | ||||
| * Tue Apr 05 2022 Jon Maloy <jmaloy@redhat.com> - 6.2.0-11 | ||||
| - kvm-target-i386-properly-reset-TSC-on-reset.patch [bz#1975840] | ||||
| - Resolves: bz#1975840 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user