| From ac2071c3791b67fc7af78b8ceb320c01ca1b5df7 Mon Sep 17 00:00:00 2001 |
| From: BALATON Zoltan <balaton@eik.bme.hu> |
| Date: Mon, 6 Apr 2020 22:34:26 +0200 |
| Subject: [PATCH] ati-vga: Fix checks in ati_2d_blt() to avoid crash |
| |
| In some corner cases (that never happen during normal operation but a |
| malicious guest could program wrong values) pixman functions were |
| called with parameters that result in a crash. Fix this and add more |
| checks to disallow such cases. |
| |
| Reported-by: Ziming Zhang <ezrakiez@gmail.com> |
| Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> |
| Message-id: 20200406204029.19559747D5D@zero.eik.bme.hu |
| Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> |
| |
| Upstream-Status: Backport [https://git.qemu.org/?p=qemu.git;a=commit;h=ac2071c3791b67fc7af78b8ceb320c01ca1b5df7] |
| CVE: CVE-2020-11869 |
| Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com> |
| --- |
| hw/display/ati_2d.c | 37 ++++++++++++++++++++++++++----------- |
| 1 file changed, 26 insertions(+), 11 deletions(-) |
| |
| diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c |
| index 42e8231..23a8ae0 100644 |
| --- a/hw/display/ati_2d.c |
| +++ b/hw/display/ati_2d.c |
| @@ -53,12 +53,20 @@ void ati_2d_blt(ATIVGAState *s) |
| s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds), |
| surface_bits_per_pixel(ds), |
| (s->regs.dp_mix & GMC_ROP3_MASK) >> 16); |
| - int dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? |
| - s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width); |
| - int dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? |
| - s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height); |
| + unsigned dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? |
| + s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width); |
| + unsigned dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? |
| + s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height); |
| int bpp = ati_bpp_from_datatype(s); |
| + if (!bpp) { |
| + qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); |
| + return; |
| + } |
| int dst_stride = DEFAULT_CNTL ? s->regs.dst_pitch : s->regs.default_pitch; |
| + if (!dst_stride) { |
| + qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n"); |
| + return; |
| + } |
| uint8_t *dst_bits = s->vga.vram_ptr + (DEFAULT_CNTL ? |
| s->regs.dst_offset : s->regs.default_offset); |
| |
| @@ -82,12 +90,16 @@ void ati_2d_blt(ATIVGAState *s) |
| switch (s->regs.dp_mix & GMC_ROP3_MASK) { |
| case ROP3_SRCCOPY: |
| { |
| - int src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? |
| - s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width); |
| - int src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? |
| - s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height); |
| + unsigned src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? |
| + s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width); |
| + unsigned src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? |
| + s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height); |
| int src_stride = DEFAULT_CNTL ? |
| s->regs.src_pitch : s->regs.default_pitch; |
| + if (!src_stride) { |
| + qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); |
| + return; |
| + } |
| uint8_t *src_bits = s->vga.vram_ptr + (DEFAULT_CNTL ? |
| s->regs.src_offset : s->regs.default_offset); |
| |
| @@ -137,8 +149,10 @@ void ati_2d_blt(ATIVGAState *s) |
| dst_y * surface_stride(ds), |
| s->regs.dst_height * surface_stride(ds)); |
| } |
| - s->regs.dst_x += s->regs.dst_width; |
| - s->regs.dst_y += s->regs.dst_height; |
| + s->regs.dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? |
| + dst_x + s->regs.dst_width : dst_x); |
| + s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? |
| + dst_y + s->regs.dst_height : dst_y); |
| break; |
| } |
| case ROP3_PATCOPY: |
| @@ -179,7 +193,8 @@ void ati_2d_blt(ATIVGAState *s) |
| dst_y * surface_stride(ds), |
| s->regs.dst_height * surface_stride(ds)); |
| } |
| - s->regs.dst_y += s->regs.dst_height; |
| + s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? |
| + dst_y + s->regs.dst_height : dst_y); |
| break; |
| } |
| default: |
| -- |
| 1.8.3.1 |