diff options
author | Li Wang <li.wang@windriver.com> | 2020-09-22 02:35:18 +0000 |
---|---|---|
committer | Anuj Mittal <anuj.mittal@intel.com> | 2020-11-23 14:11:31 +0800 |
commit | 60b61942c34e1db237d466c406e25d0f36f5066d (patch) | |
tree | 4725e10f2ac078a9365f86bc9d142cf26e3e1210 | |
parent | ed16bdd8b7cb909251c1bb4c6f81c42cd84d069a (diff) | |
download | openembedded-core-contrib-60b61942c34e1db237d466c406e25d0f36f5066d.tar.gz |
qemu: CVE-2020-12829
Backport CVE patch from the upstream:
https://git.qemu.org/?p=qemu.git;a=commit;h=b15a22bbcbe6a78dc3d88fe3134985e4cdd87de4
Signed-off-by: Li Wang <li.wang@windriver.com>
Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
-rw-r--r-- | meta/recipes-devtools/qemu/qemu.inc | 1 | ||||
-rw-r--r-- | meta/recipes-devtools/qemu/qemu/CVE-2020-12829.patch | 267 |
2 files changed, 268 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc index ec32c90ad5..cbade92ac9 100644 --- a/meta/recipes-devtools/qemu/qemu.inc +++ b/meta/recipes-devtools/qemu/qemu.inc @@ -43,6 +43,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \ file://CVE-2020-10756.patch \ file://CVE-2020-15863.patch \ file://CVE-2020-14364.patch \ + file://CVE-2020-12829.patch \ " UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2020-12829.patch b/meta/recipes-devtools/qemu/qemu/CVE-2020-12829.patch new file mode 100644 index 0000000000..46e494dec0 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2020-12829.patch @@ -0,0 +1,267 @@ +From b15a22bbcbe6a78dc3d88fe3134985e4cdd87de4 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan <balaton@eik.bme.hu> +Date: Thu, 21 May 2020 21:39:44 +0200 +Subject: [PATCH] sm501: Replace hand written implementation with pixman +where possible + +Besides being faster this should also prevent malicious guests to +abuse 2D engine to overwrite data or cause a crash. + +Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> +Message-id: +58666389b6cae256e4e972a32c05cf8aa51bffc0.1590089984.git.balaton@eik.bme.hu +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> + +Upstream-Status: Backport +CVE: CVE-2020-12829 +[https://git.qemu.org/?p=qemu.git;a=commit;h=b15a22bbcbe6a78dc3d88fe3134985e4cdd87de4] +Signed-off-by: Li Wang <li.wang@windriver.com> +--- + hw/display/sm501.c | 205 ++++++++++++++++++++++++++------------------- + 1 file changed, 118 insertions(+), 87 deletions(-) + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index 5918f59..b52c7e8 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -702,12 +702,12 @@ static void sm501_2d_operation(SM501State *s) + /* obtain operation parameters */ + int operation = (s->twoD_control >> 16) & 0x1f; + int rtl = s->twoD_control & 0x8000000; +- int src_x = (s->twoD_source >> 16) & 0x01FFF; +- int src_y = s->twoD_source & 0xFFFF; +- int dst_x = (s->twoD_destination >> 16) & 0x01FFF; +- int dst_y = s->twoD_destination & 0xFFFF; +- int operation_width = (s->twoD_dimension >> 16) & 0x1FFF; +- int operation_height = s->twoD_dimension & 0xFFFF; ++ unsigned int src_x = (s->twoD_source >> 16) & 0x01FFF; ++ unsigned int src_y = s->twoD_source & 0xFFFF; ++ unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF; ++ unsigned int dst_y = s->twoD_destination & 0xFFFF; ++ unsigned int operation_width = (s->twoD_dimension >> 16) & 0x1FFF; ++ unsigned int operation_height = s->twoD_dimension & 0xFFFF; + uint32_t color = s->twoD_foreground; + int format_flags = (s->twoD_stretch >> 20) & 0x3; + int addressing = (s->twoD_stretch >> 16) & 0xF; +@@ -719,10 +719,8 @@ static void sm501_2d_operation(SM501State *s) + uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF; + + /* get frame buffer info */ +- uint8_t *src = s->local_mem + src_base; +- uint8_t *dst = s->local_mem + dst_base; +- int src_width = s->twoD_pitch & 0x1FFF; +- int dst_width = (s->twoD_pitch >> 16) & 0x1FFF; ++ unsigned int src_width = s->twoD_pitch & 0x1FFF; ++ unsigned int dst_width = (s->twoD_pitch >> 16) & 0x1FFF; + int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; + int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); + +@@ -731,95 +729,128 @@ static void sm501_2d_operation(SM501State *s) + abort(); + } + +- if (rop_mode == 0) { +- if (rop != 0xcc) { +- /* Anything other than plain copies are not supported */ +- qemu_log_mask(LOG_UNIMP, "sm501: rop3 mode with rop %x is not " +- "supported.\n", rop); +- } +- } else { +- if (rop2_source_is_pattern && rop != 0x5) { +- /* For pattern source, we support only inverse dest */ +- qemu_log_mask(LOG_UNIMP, "sm501: rop2 source being the pattern and " +- "rop %x is not supported.\n", rop); +- } else { +- if (rop != 0x5 && rop != 0xc) { +- /* Anything other than plain copies or inverse dest is not +- * supported */ +- qemu_log_mask(LOG_UNIMP, "sm501: rop mode %x is not " +- "supported.\n", rop); +- } +- } +- } +- + if ((s->twoD_source_base & 0x08000000) || + (s->twoD_destination_base & 0x08000000)) { + printf("%s: only local memory is supported.\n", __func__); + abort(); + } + +- switch (operation) { +- case 0x00: /* copy area */ +-#define COPY_AREA(_bpp, _pixel_type, rtl) { \ +- int y, x, index_d, index_s; \ +- for (y = 0; y < operation_height; y++) { \ +- for (x = 0; x < operation_width; x++) { \ +- _pixel_type val; \ +- \ +- if (rtl) { \ +- index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \ +- index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \ +- } else { \ +- index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \ +- index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ +- } \ +- if (rop_mode == 1 && rop == 5) { \ +- /* Invert dest */ \ +- val = ~*(_pixel_type *)&dst[index_d]; \ +- } else { \ +- val = *(_pixel_type *)&src[index_s]; \ +- } \ +- *(_pixel_type *)&dst[index_d] = val; \ +- } \ +- } \ ++ if (!dst_width) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n"); ++ return; + } +- switch (format_flags) { +- case 0: +- COPY_AREA(1, uint8_t, rtl); +- break; +- case 1: +- COPY_AREA(2, uint16_t, rtl); +- break; +- case 2: +- COPY_AREA(4, uint32_t, rtl); +- break; +- } +- break; + +- case 0x01: /* fill rectangle */ +-#define FILL_RECT(_bpp, _pixel_type) { \ +- int y, x; \ +- for (y = 0; y < operation_height; y++) { \ +- for (x = 0; x < operation_width; x++) { \ +- int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ +- *(_pixel_type *)&dst[index] = (_pixel_type)color; \ +- } \ +- } \ ++ if (!operation_width || !operation_height) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n"); ++ return; + } + +- switch (format_flags) { +- case 0: +- FILL_RECT(1, uint8_t); +- break; +- case 1: +- color = cpu_to_le16(color); +- FILL_RECT(2, uint16_t); +- break; +- case 2: ++ if (rtl) { ++ dst_x -= operation_width - 1; ++ dst_y -= operation_height - 1; ++ } ++ ++ if (dst_base >= get_local_mem_size(s) || dst_base + ++ (dst_x + operation_width + (dst_y + operation_height) * (dst_width + operation_width)) * ++ (1 << format_flags) >= get_local_mem_size(s)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n"); ++ return; ++ } ++ ++ switch (operation) { ++ case 0: /* BitBlt */ ++ if (!src_width) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n"); ++ return; ++ } ++ ++ if (rtl) { ++ src_x -= operation_width - 1; ++ src_y -= operation_height - 1; ++ } ++ ++ if (src_base >= get_local_mem_size(s) || src_base + ++ (src_x + operation_width + (src_y + operation_height) * (src_width + operation_width)) * ++ (1 << format_flags) >= get_local_mem_size(s)) { ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "sm501: 2D op src is outside vram.\n"); ++ return; ++ } ++ ++ if ((rop_mode && rop == 0x5) || (!rop_mode && rop == 0x55)) { ++ /* Invert dest, is there a way to do this with pixman? */ ++ unsigned int x, y, i; ++ uint8_t *d = s->local_mem + dst_base; ++ ++ for (y = 0; y < operation_height; y++) { ++ i = (dst_x + (dst_y + y) * dst_width) * (1 << format_flags); ++ for (x = 0; x < operation_width; x++, i += (1 << format_flags)) { ++ switch (format_flags) { ++ case 0: ++ d[i] = ~d[i]; ++ break; ++ case 1: ++ *(uint16_t *)&d[i] = ~*(uint16_t *)&d[i]; ++ break; ++ case 2: ++ *(uint32_t *)&d[i] = ~*(uint32_t *)&d[i]; ++ break; ++ } ++ } ++ } ++ } else { ++ /* Do copy src for unimplemented ops, better than unpainted area */ ++ if ((rop_mode && (rop != 0xc || rop2_source_is_pattern)) || ++ (!rop_mode && rop != 0xcc)) { ++ qemu_log_mask(LOG_UNIMP, ++ "sm501: rop%d op %x%s not implemented\n", ++ (rop_mode ? 2 : 3), rop, ++ (rop2_source_is_pattern ? ++ " with pattern source" : "")); ++ } ++ /* Check for overlaps, this could be made more exact */ ++ uint32_t sb, se, db, de; ++ sb = src_base + src_x + src_y * (operation_width + src_width); ++ se = sb + operation_width + operation_height * (operation_width + src_width); ++ db = dst_base + dst_x + dst_y * (operation_width + dst_width); ++ de = db + operation_width + operation_height * (operation_width + dst_width); ++ if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) { ++ /* regions may overlap: copy via temporary */ ++ int llb = operation_width * (1 << format_flags); ++ int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t)); ++ uint32_t *tmp = g_malloc(tmp_stride * sizeof(uint32_t) * ++ operation_height); ++ pixman_blt((uint32_t *)&s->local_mem[src_base], tmp, ++ src_width * (1 << format_flags) / sizeof(uint32_t), ++ tmp_stride, 8 * (1 << format_flags), 8 * (1 << format_flags), ++ src_x, src_y, 0, 0, operation_width, operation_height); ++ pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base], ++ tmp_stride, ++ dst_width * (1 << format_flags) / sizeof(uint32_t), ++ 8 * (1 << format_flags), 8 * (1 << format_flags), ++ 0, 0, dst_x, dst_y, operation_width, operation_height); ++ g_free(tmp); ++ } else { ++ pixman_blt((uint32_t *)&s->local_mem[src_base], ++ (uint32_t *)&s->local_mem[dst_base], ++ src_width * (1 << format_flags) / sizeof(uint32_t), ++ dst_width * (1 << format_flags) / sizeof(uint32_t), ++ 8 * (1 << format_flags), 8 * (1 << format_flags), ++ src_x, src_y, dst_x, dst_y, operation_width, operation_height); ++ } ++ } ++ break; ++ ++ case 1: /* Rectangle Fill */ ++ if (format_flags == 2) { + color = cpu_to_le32(color); +- FILL_RECT(4, uint32_t); +- break; ++ } else if (format_flags == 1) { ++ color = cpu_to_le16(color); + } ++ ++ pixman_fill((uint32_t *)&s->local_mem[dst_base], ++ dst_width * (1 << format_flags) / sizeof(uint32_t), ++ 8 * (1 << format_flags), dst_x, dst_y, operation_width, operation_height, color); + break; + + default: +-- +2.17.1 + |