From 7f097b06041d9003d2ce5aafe83a325984681937 Mon Sep 17 00:00:00 2001 From: Mauro Matteo Cascella Date: Fri, 10 Jul 2020 11:19:41 +0200 Subject: [PATCH 1/9] hw/net/xgmac: Fix buffer overflow in xgmac_enet_send() A buffer overflow issue was reported by Mr. Ziming Zhang, CC'd here. It occurs while sending an Ethernet frame due to missing break statements and improper checking of the buffer size. Reported-by: Ziming Zhang Signed-off-by: Mauro Matteo Cascella Reviewed-by: Peter Maydell Signed-off-by: Jason Wang --- ...x-buffer-overflow-in-xgmac_enet_send.patch | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch diff --git a/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch b/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch new file mode 100644 index 0000000..778be39 --- /dev/null +++ b/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch @@ -0,0 +1,58 @@ +From a80a85c7c358febb164ace0dfa75c468f43e0f02 Mon Sep 17 00:00:00 2001 +From: Mauro Matteo Cascella +Date: Fri, 10 Jul 2020 11:19:41 +0200 +Subject: [PATCH] hw/net/xgmac: Fix buffer overflow in xgmac_enet_send() + +A buffer overflow issue was reported by Mr. Ziming Zhang, CC'd here. It +occurs while sending an Ethernet frame due to missing break statements +and improper checking of the buffer size. + +Reported-by: Ziming Zhang +Signed-off-by: Mauro Matteo Cascella +Reviewed-by: Peter Maydell +Signed-off-by: Jason Wang +--- + hw/net/xgmac.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c +index f49df95b07..f496f7ed4c 100644 +--- a/hw/net/xgmac.c ++++ b/hw/net/xgmac.c +@@ -217,21 +217,31 @@ static void xgmac_enet_send(XgmacState *s) + } + len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff); + ++ /* ++ * FIXME: these cases of malformed tx descriptors (bad sizes) ++ * should probably be reported back to the guest somehow ++ * rather than simply silently stopping processing, but we ++ * don't know what the hardware does in this situation. ++ * This will only happen for buggy guests anyway. ++ */ + if ((bd.buffer1_size & 0xfff) > 2048) { + DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- " + "xgmac buffer 1 len on send > 2048 (0x%x)\n", + __func__, bd.buffer1_size & 0xfff); ++ break; + } + if ((bd.buffer2_size & 0xfff) != 0) { + DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- " + "xgmac buffer 2 len on send != 0 (0x%x)\n", + __func__, bd.buffer2_size & 0xfff); ++ break; + } +- if (len >= sizeof(frame)) { ++ if (frame_size + len >= sizeof(frame)) { + DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu " +- "buffer\n" , __func__, len, sizeof(frame)); ++ "buffer\n" , __func__, frame_size + len, sizeof(frame)); + DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n", + __func__, bd.buffer1_size, bd.buffer2_size); ++ break; + } + + cpu_physical_memory_read(bd.buffer1_addr, ptr, len); +-- +2.23.0 + -- Gitee From 7c7ce70caa809ec8dee70e27578a81cbbaae531b Mon Sep 17 00:00:00 2001 From: Mauro Matteo Cascella Date: Sat, 1 Aug 2020 18:42:38 +0200 Subject: [PATCH 2/9] hw/net/net_tx_pkt: fix assertion failure in net_tx_pkt_add_raw_fragment() An assertion failure issue was found in the code that processes network packets while adding data fragments into the packet context. It could be abused by a malicious guest to abort the QEMU process on the host. This patch replaces the affected assert() with a conditional statement, returning false if the current data fragment exceeds max_raw_frags. Reported-by: Alexander Bulekov Reported-by: Ziming Zhang Reviewed-by: Dmitry Fleytman Signed-off-by: Mauro Matteo Cascella Signed-off-by: Jason Wang --- ...t-fix-assertion-failure-in-net_tx_pk.patch | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch diff --git a/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch b/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch new file mode 100644 index 0000000..15fcf57 --- /dev/null +++ b/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch @@ -0,0 +1,40 @@ +From d65a00000e56ee2cec2f506b1408128d2df56ad9 Mon Sep 17 00:00:00 2001 +From: Mauro Matteo Cascella +Date: Sat, 1 Aug 2020 18:42:38 +0200 +Subject: [PATCH] hw/net/net_tx_pkt: fix assertion failure in + net_tx_pkt_add_raw_fragment() + +An assertion failure issue was found in the code that processes network packets +while adding data fragments into the packet context. It could be abused by a +malicious guest to abort the QEMU process on the host. This patch replaces the +affected assert() with a conditional statement, returning false if the current +data fragment exceeds max_raw_frags. + +Reported-by: Alexander Bulekov +Reported-by: Ziming Zhang +Reviewed-by: Dmitry Fleytman +Signed-off-by: Mauro Matteo Cascella +Signed-off-by: Jason Wang +--- + hw/net/net_tx_pkt.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c +index 162f802dd7..54d4c3bbd0 100644 +--- a/hw/net/net_tx_pkt.c ++++ b/hw/net/net_tx_pkt.c +@@ -379,7 +379,10 @@ bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, + hwaddr mapped_len = 0; + struct iovec *ventry; + assert(pkt); +- assert(pkt->max_raw_frags > pkt->raw_frags); ++ ++ if (pkt->raw_frags >= pkt->max_raw_frags) { ++ return false; ++ } + + if (!len) { + return true; +-- +2.23.0 + -- Gitee From 6a474e6bbc57c192604be21303fa7ba87a899835 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 21 May 2020 21:39:44 +0200 Subject: [PATCH 3/9] sm501: Convert printf + abort to qemu_log_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some places already use qemu_log_mask() to log unimplemented features or errors but some others have printf() then abort(). Convert these to qemu_log_mask() and avoid aborting to prevent guests to easily cause denial of service. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-id: 305af87f59d81e92f2aaff09eb8a3603b8baa322.1590089984.git.balaton@eik.bme.hu Signed-off-by: Gerd Hoffmann --- ...onvert-printf-abort-to-qemu_log_mask.patch | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 sm501-Convert-printf-abort-to-qemu_log_mask.patch diff --git a/sm501-Convert-printf-abort-to-qemu_log_mask.patch b/sm501-Convert-printf-abort-to-qemu_log_mask.patch new file mode 100644 index 0000000..a151656 --- /dev/null +++ b/sm501-Convert-printf-abort-to-qemu_log_mask.patch @@ -0,0 +1,159 @@ +From c52852158aa010d534ee6d1c7a44f72ef87857a3 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Thu, 21 May 2020 21:39:44 +0200 +Subject: [PATCH] sm501: Convert printf + abort to qemu_log_mask +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some places already use qemu_log_mask() to log unimplemented features +or errors but some others have printf() then abort(). Convert these to +qemu_log_mask() and avoid aborting to prevent guests to easily cause +denial of service. + +Signed-off-by: BALATON Zoltan +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 305af87f59d81e92f2aaff09eb8a3603b8baa322.1590089984.git.balaton@eik.bme.hu +Signed-off-by: Gerd Hoffmann +--- + hw/display/sm501.c | 57 ++++++++++++++++++++++------------------------ + 1 file changed, 27 insertions(+), 30 deletions(-) + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index 5918f59b2b..aa4b202a48 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -727,8 +727,8 @@ static void sm501_2d_operation(SM501State *s) + int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); + + if (addressing != 0x0) { +- printf("%s: only XY addressing is supported.\n", __func__); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n"); ++ return; + } + + if (rop_mode == 0) { +@@ -754,8 +754,8 @@ static void sm501_2d_operation(SM501State *s) + + if ((s->twoD_source_base & 0x08000000) || + (s->twoD_destination_base & 0x08000000)) { +- printf("%s: only local memory is supported.\n", __func__); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); ++ return; + } + + switch (operation) { +@@ -823,9 +823,9 @@ static void sm501_2d_operation(SM501State *s) + break; + + default: +- printf("non-implemented SM501 2D operation. %d\n", operation); +- abort(); +- break; ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", ++ operation); ++ return; + } + + if (dst_base >= get_fb_addr(s, crt) && +@@ -892,9 +892,8 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, + break; + + default: +- printf("sm501 system config : not implemented register read." +- " addr=%x\n", (int)addr); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config" ++ "register read. addr=%" HWADDR_PRIx "\n", addr); + } + + return ret; +@@ -948,15 +947,15 @@ static void sm501_system_config_write(void *opaque, hwaddr addr, + break; + case SM501_ENDIAN_CONTROL: + if (value & 0x00000001) { +- printf("sm501 system config : big endian mode not implemented.\n"); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: system config big endian mode not" ++ " implemented.\n"); + } + break; + + default: +- printf("sm501 system config : not implemented register write." +- " addr=%x, val=%x\n", (int)addr, (uint32_t)value); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config" ++ "register write. addr=%" HWADDR_PRIx ++ ", val=%" PRIx64 "\n", addr, value); + } + } + +@@ -1207,9 +1206,8 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, + break; + + default: +- printf("sm501 disp ctrl : not implemented register read." +- " addr=%x\n", (int)addr); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " ++ "read. addr=%" HWADDR_PRIx "\n", addr); + } + + return ret; +@@ -1345,9 +1343,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, + break; + + default: +- printf("sm501 disp ctrl : not implemented register write." +- " addr=%x, val=%x\n", (int)addr, (unsigned)value); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " ++ "write. addr=%" HWADDR_PRIx ++ ", val=%" PRIx64 "\n", addr, value); + } + } + +@@ -1433,9 +1431,8 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr, + ret = 0; /* Should return interrupt status */ + break; + default: +- printf("sm501 disp ctrl : not implemented register read." +- " addr=%x\n", (int)addr); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " ++ "read. addr=%" HWADDR_PRIx "\n", addr); + } + + return ret; +@@ -1520,9 +1517,9 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr, + /* ignored, writing 0 should clear interrupt status */ + break; + default: +- printf("sm501 2d engine : not implemented register write." +- " addr=%x, val=%x\n", (int)addr, (unsigned)value); +- abort(); ++ qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2d engine register " ++ "write. addr=%" HWADDR_PRIx ++ ", val=%" PRIx64 "\n", addr, value); + } + } + +@@ -1670,9 +1667,9 @@ static void sm501_update_display(void *opaque) + draw_line = draw_line32_funcs[dst_depth_index]; + break; + default: +- printf("sm501 update display : invalid control register value.\n"); +- abort(); +- break; ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: update display" ++ "invalid control register value.\n"); ++ return; + } + + /* set up to draw hardware cursor */ +-- +2.23.0 + -- Gitee From c38ad8a2edd46e2c719a189950938b8acee6a33b Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 21 May 2020 21:39:44 +0200 Subject: [PATCH 4/9] sm501: Shorten long variable names in sm501_2d_operation This increases readability and cleans up some confusing naming. Signed-off-by: BALATON Zoltan Message-id: b9b67b94c46e945252a73c77dfd117132c63c4fb.1590089984.git.balaton@eik.bme.hu Signed-off-by: Gerd Hoffmann --- ...ng-variable-names-in-sm501_2d_operat.patch | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch diff --git a/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch b/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch new file mode 100644 index 0000000..9214016 --- /dev/null +++ b/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch @@ -0,0 +1,134 @@ +From 54c647d867891b58084d6b36ac2db794c19bed22 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Thu, 21 May 2020 21:39:44 +0200 +Subject: [PATCH] sm501: Shorten long variable names in sm501_2d_operation + +This increases readability and cleans up some confusing naming. + +Signed-off-by: BALATON Zoltan +Message-id: b9b67b94c46e945252a73c77dfd117132c63c4fb.1590089984.git.balaton@eik.bme.hu +Signed-off-by: Gerd Hoffmann +--- + hw/display/sm501.c | 45 ++++++++++++++++++++++----------------------- + 1 file changed, 22 insertions(+), 23 deletions(-) + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index aa4b202a48..51e7ccc39d 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -700,17 +700,16 @@ static inline void hwc_invalidate(SM501State *s, int crt) + static void sm501_2d_operation(SM501State *s) + { + /* obtain operation parameters */ +- int operation = (s->twoD_control >> 16) & 0x1f; ++ int cmd = (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; ++ int width = (s->twoD_dimension >> 16) & 0x1FFF; ++ int 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; ++ int format = (s->twoD_stretch >> 20) & 0x3; + int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ + /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ + int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; +@@ -721,12 +720,12 @@ static void sm501_2d_operation(SM501State *s) + /* 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; ++ int src_pitch = s->twoD_pitch & 0x1FFF; ++ int dst_pitch = (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); + +- if (addressing != 0x0) { ++ if ((s->twoD_stretch >> 16) & 0xF) { + qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n"); + return; + } +@@ -758,20 +757,20 @@ static void sm501_2d_operation(SM501State *s) + return; + } + +- switch (operation) { ++ switch (cmd) { + 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++) { \ ++ for (y = 0; y < height; y++) { \ ++ for (x = 0; x < 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; \ ++ index_s = ((src_y - y) * src_pitch + src_x - x) * _bpp; \ ++ index_d = ((dst_y - y) * dst_pitch + 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; \ ++ index_s = ((src_y + y) * src_pitch + src_x + x) * _bpp; \ ++ index_d = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ + } \ + if (rop_mode == 1 && rop == 5) { \ + /* Invert dest */ \ +@@ -783,7 +782,7 @@ static void sm501_2d_operation(SM501State *s) + } \ + } \ + } +- switch (format_flags) { ++ switch (format) { + case 0: + COPY_AREA(1, uint8_t, rtl); + break; +@@ -799,15 +798,15 @@ static void sm501_2d_operation(SM501State *s) + 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; \ ++ for (y = 0; y < height; y++) { \ ++ for (x = 0; x < width; x++) { \ ++ int index = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ + *(_pixel_type *)&dst[index] = (_pixel_type)color; \ + } \ + } \ + } + +- switch (format_flags) { ++ switch (format) { + case 0: + FILL_RECT(1, uint8_t); + break; +@@ -824,14 +823,14 @@ static void sm501_2d_operation(SM501State *s) + + default: + qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", +- operation); ++ cmd); + return; + } + + if (dst_base >= get_fb_addr(s, crt) && + dst_base <= get_fb_addr(s, crt) + fb_len) { +- int dst_len = MIN(fb_len, ((dst_y + operation_height - 1) * dst_width + +- dst_x + operation_width) * (1 << format_flags)); ++ int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch + ++ dst_x + width) * (1 << format)); + if (dst_len) { + memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len); + } +-- +2.23.0 + -- Gitee From 28a981218105945585dc1dd80cadbf2b6278f081 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 21 May 2020 21:39:44 +0200 Subject: [PATCH 5/9] sm501: Use BIT(x) macro to shorten constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-id: 124bf5de8d7cf503b32b377d0445029a76bfbd49.1590089984.git.balaton@eik.bme.hu Signed-off-by: Gerd Hoffmann --- ...-Use-BIT-x-macro-to-shorten-constant.patch | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 sm501-Use-BIT-x-macro-to-shorten-constant.patch diff --git a/sm501-Use-BIT-x-macro-to-shorten-constant.patch b/sm501-Use-BIT-x-macro-to-shorten-constant.patch new file mode 100644 index 0000000..dbd4127 --- /dev/null +++ b/sm501-Use-BIT-x-macro-to-shorten-constant.patch @@ -0,0 +1,42 @@ +From a2622f39d8050c86100b40e47b2586d0ebf3b541 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Thu, 21 May 2020 21:39:44 +0200 +Subject: [PATCH] sm501: Use BIT(x) macro to shorten constant +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: BALATON Zoltan +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 124bf5de8d7cf503b32b377d0445029a76bfbd49.1590089984.git.balaton@eik.bme.hu +Signed-off-by: Gerd Hoffmann +--- + hw/display/sm501.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index 51e7ccc39d..f3d11d0b23 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -701,7 +701,7 @@ static void sm501_2d_operation(SM501State *s) + { + /* obtain operation parameters */ + int cmd = (s->twoD_control >> 16) & 0x1F; +- int rtl = s->twoD_control & 0x8000000; ++ int rtl = s->twoD_control & BIT(27); + int src_x = (s->twoD_source >> 16) & 0x01FFF; + int src_y = s->twoD_source & 0xFFFF; + int dst_x = (s->twoD_destination >> 16) & 0x01FFF; +@@ -751,8 +751,7 @@ static void sm501_2d_operation(SM501State *s) + } + } + +- if ((s->twoD_source_base & 0x08000000) || +- (s->twoD_destination_base & 0x08000000)) { ++ if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27)) { + qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); + return; + } +-- +2.23.0 + -- Gitee From 086f90e1135f48824fd4e1888e5582a5aa965dbf Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 21 May 2020 21:39:44 +0200 Subject: [PATCH 6/9] sm501: Clean up local variables in sm501_2d_operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make variables local to the block they are used in to make it clearer which operation they are needed for. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-id: ae59f8138afe7f6a5a4a82539d0f61496a906b06.1590089984.git.balaton@eik.bme.hu Signed-off-by: Gerd Hoffmann --- ...ocal-variables-in-sm501_2d_operation.patch | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 sm501-Clean-up-local-variables-in-sm501_2d_operation.patch diff --git a/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch b/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch new file mode 100644 index 0000000..70d8792 --- /dev/null +++ b/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch @@ -0,0 +1,95 @@ +From b08fddd2931fa2e3d12d2c26074835956b114d56 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Thu, 21 May 2020 21:39:44 +0200 +Subject: [PATCH] sm501: Clean up local variables in sm501_2d_operation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Make variables local to the block they are used in to make it clearer +which operation they are needed for. + +Signed-off-by: BALATON Zoltan +Reviewed-by: Philippe Mathieu-Daudé +Message-id: ae59f8138afe7f6a5a4a82539d0f61496a906b06.1590089984.git.balaton@eik.bme.hu +Signed-off-by: Gerd Hoffmann +--- + hw/display/sm501.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index f3d11d0b23..98b3b97f7b 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -699,28 +699,19 @@ static inline void hwc_invalidate(SM501State *s, int crt) + + static void sm501_2d_operation(SM501State *s) + { +- /* obtain operation parameters */ + int cmd = (s->twoD_control >> 16) & 0x1F; + int rtl = s->twoD_control & BIT(27); +- 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 width = (s->twoD_dimension >> 16) & 0x1FFF; +- int height = s->twoD_dimension & 0xFFFF; +- uint32_t color = s->twoD_foreground; + int format = (s->twoD_stretch >> 20) & 0x3; + int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ + /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ + int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; + int rop = s->twoD_control & 0xFF; +- uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; ++ int dst_x = (s->twoD_destination >> 16) & 0x01FFF; ++ int dst_y = s->twoD_destination & 0xFFFF; ++ int width = (s->twoD_dimension >> 16) & 0x1FFF; ++ int height = s->twoD_dimension & 0xFFFF; + 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_pitch = s->twoD_pitch & 0x1FFF; + int dst_pitch = (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); +@@ -758,6 +749,13 @@ static void sm501_2d_operation(SM501State *s) + + switch (cmd) { + case 0x00: /* copy area */ ++ { ++ int src_x = (s->twoD_source >> 16) & 0x01FFF; ++ int src_y = s->twoD_source & 0xFFFF; ++ uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; ++ uint8_t *src = s->local_mem + src_base; ++ int src_pitch = s->twoD_pitch & 0x1FFF; ++ + #define COPY_AREA(_bpp, _pixel_type, rtl) { \ + int y, x, index_d, index_s; \ + for (y = 0; y < height; y++) { \ +@@ -793,8 +791,11 @@ static void sm501_2d_operation(SM501State *s) + break; + } + break; +- ++ } + case 0x01: /* fill rectangle */ ++ { ++ uint32_t color = s->twoD_foreground; ++ + #define FILL_RECT(_bpp, _pixel_type) { \ + int y, x; \ + for (y = 0; y < height; y++) { \ +@@ -819,7 +820,7 @@ static void sm501_2d_operation(SM501State *s) + break; + } + break; +- ++ } + default: + qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", + cmd); +-- +2.23.0 + -- Gitee From f6f8cee9ce7f557b93630274e10aee1e82a5a217 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Thu, 21 May 2020 21:39:44 +0200 Subject: [PATCH 7/9] 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 Message-id: 58666389b6cae256e4e972a32c05cf8aa51bffc0.1590089984.git.balaton@eik.bme.hu Signed-off-by: Gerd Hoffmann --- ...nd-written-implementation-with-pixma.patch | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 sm501-Replace-hand-written-implementation-with-pixma.patch diff --git a/sm501-Replace-hand-written-implementation-with-pixma.patch b/sm501-Replace-hand-written-implementation-with-pixma.patch new file mode 100644 index 0000000..67842be --- /dev/null +++ b/sm501-Replace-hand-written-implementation-with-pixma.patch @@ -0,0 +1,261 @@ +From 2f57a288065de4fffcf182deacd3c75aec90a9ef Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +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 +Message-id: 58666389b6cae256e4e972a32c05cf8aa51bffc0.1590089984.git.balaton@eik.bme.hu +Signed-off-by: Gerd Hoffmann +--- + hw/display/sm501.c | 207 ++++++++++++++++++++++++++------------------- + 1 file changed, 119 insertions(+), 88 deletions(-) + +diff --git a/hw/display/sm501.c b/hw/display/sm501.c +index 98b3b97f7b..7dc4bb18b7 100644 +--- a/hw/display/sm501.c ++++ b/hw/display/sm501.c +@@ -706,13 +706,12 @@ static void sm501_2d_operation(SM501State *s) + /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ + int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; + int rop = s->twoD_control & 0xFF; +- int dst_x = (s->twoD_destination >> 16) & 0x01FFF; +- int dst_y = s->twoD_destination & 0xFFFF; +- int width = (s->twoD_dimension >> 16) & 0x1FFF; +- int height = s->twoD_dimension & 0xFFFF; ++ unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF; ++ unsigned int dst_y = s->twoD_destination & 0xFFFF; ++ unsigned int width = (s->twoD_dimension >> 16) & 0x1FFF; ++ unsigned int height = s->twoD_dimension & 0xFFFF; + uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF; +- uint8_t *dst = s->local_mem + dst_base; +- int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF; ++ unsigned int dst_pitch = (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); + +@@ -721,104 +720,136 @@ static void sm501_2d_operation(SM501State *s) + return; + } + +- 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 & BIT(27) || s->twoD_destination_base & BIT(27)) { + qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); + return; + } + ++ if (!dst_pitch) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n"); ++ return; ++ } ++ ++ if (!width || !height) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n"); ++ return; ++ } ++ ++ if (rtl) { ++ dst_x -= width - 1; ++ dst_y -= height - 1; ++ } ++ ++ if (dst_base >= get_local_mem_size(s) || dst_base + ++ (dst_x + width + (dst_y + height) * (dst_pitch + width)) * ++ (1 << format) >= get_local_mem_size(s)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n"); ++ return; ++ } ++ + switch (cmd) { +- case 0x00: /* copy area */ ++ case 0: /* BitBlt */ + { +- int src_x = (s->twoD_source >> 16) & 0x01FFF; +- int src_y = s->twoD_source & 0xFFFF; ++ unsigned int src_x = (s->twoD_source >> 16) & 0x01FFF; ++ unsigned int src_y = s->twoD_source & 0xFFFF; + uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; +- uint8_t *src = s->local_mem + src_base; +- int src_pitch = s->twoD_pitch & 0x1FFF; +- +-#define COPY_AREA(_bpp, _pixel_type, rtl) { \ +- int y, x, index_d, index_s; \ +- for (y = 0; y < height; y++) { \ +- for (x = 0; x < width; x++) { \ +- _pixel_type val; \ +- \ +- if (rtl) { \ +- index_s = ((src_y - y) * src_pitch + src_x - x) * _bpp; \ +- index_d = ((dst_y - y) * dst_pitch + dst_x - x) * _bpp; \ +- } else { \ +- index_s = ((src_y + y) * src_pitch + src_x + x) * _bpp; \ +- index_d = ((dst_y + y) * dst_pitch + 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; \ +- } \ +- } \ +- } +- switch (format) { +- 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; ++ unsigned int src_pitch = s->twoD_pitch & 0x1FFF; ++ ++ if (!src_pitch) { ++ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n"); ++ return; ++ } ++ ++ if (rtl) { ++ src_x -= width - 1; ++ src_y -= height - 1; ++ } ++ ++ if (src_base >= get_local_mem_size(s) || src_base + ++ (src_x + width + (src_y + height) * (src_pitch + width)) * ++ (1 << format) >= 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 < height; y++) { ++ i = (dst_x + (dst_y + y) * dst_pitch) * (1 << format); ++ for (x = 0; x < width; x++, i += (1 << format)) { ++ switch (format) { ++ 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 * (width + src_pitch); ++ se = sb + width + height * (width + src_pitch); ++ db = dst_base + dst_x + dst_y * (width + dst_pitch); ++ de = db + width + height * (width + dst_pitch); ++ if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) { ++ /* regions may overlap: copy via temporary */ ++ int llb = width * (1 << format); ++ int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t)); ++ uint32_t *tmp = g_malloc(tmp_stride * sizeof(uint32_t) * ++ height); ++ pixman_blt((uint32_t *)&s->local_mem[src_base], tmp, ++ src_pitch * (1 << format) / sizeof(uint32_t), ++ tmp_stride, 8 * (1 << format), 8 * (1 << format), ++ src_x, src_y, 0, 0, width, height); ++ pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base], ++ tmp_stride, ++ dst_pitch * (1 << format) / sizeof(uint32_t), ++ 8 * (1 << format), 8 * (1 << format), ++ 0, 0, dst_x, dst_y, width, height); ++ g_free(tmp); ++ } else { ++ pixman_blt((uint32_t *)&s->local_mem[src_base], ++ (uint32_t *)&s->local_mem[dst_base], ++ src_pitch * (1 << format) / sizeof(uint32_t), ++ dst_pitch * (1 << format) / sizeof(uint32_t), ++ 8 * (1 << format), 8 * (1 << format), ++ src_x, src_y, dst_x, dst_y, width, height); ++ } + } + break; + } +- case 0x01: /* fill rectangle */ ++ case 1: /* Rectangle Fill */ + { + uint32_t color = s->twoD_foreground; + +-#define FILL_RECT(_bpp, _pixel_type) { \ +- int y, x; \ +- for (y = 0; y < height; y++) { \ +- for (x = 0; x < width; x++) { \ +- int index = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ +- *(_pixel_type *)&dst[index] = (_pixel_type)color; \ +- } \ +- } \ +- } +- +- switch (format) { +- case 0: +- FILL_RECT(1, uint8_t); +- break; +- case 1: +- color = cpu_to_le16(color); +- FILL_RECT(2, uint16_t); +- break; +- case 2: ++ if (format == 2) { + color = cpu_to_le32(color); +- FILL_RECT(4, uint32_t); +- break; ++ } else if (format == 1) { ++ color = cpu_to_le16(color); + } ++ ++ pixman_fill((uint32_t *)&s->local_mem[dst_base], ++ dst_pitch * (1 << format) / sizeof(uint32_t), ++ 8 * (1 << format), dst_x, dst_y, width, height, color); + break; + } + default: +-- +2.23.0 + -- Gitee From 415f49239c5ff834d6741205bf286a10ba66c8a0 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Thu, 24 Sep 2020 16:09:40 +0800 Subject: [PATCH 8/9] spec: Update patch and changelog with !14 hw/net/xgmac: Fix buffer overflow in xgmac_enet_send() hw/net/net_tx_pkt: fix assertion failure in net_tx_pkt_add_raw_fragment() sm501: Convert printf + abort to qemu_log_mask sm501: Shorten long variable names in sm501_2d_operation sm501: Use BIT(x) macro to shorten constant sm501: Clean up local variables in sm501_2d_operation sm501: Replace hand written implementation with pixman where possible Signed-off-by: BALATON Zoltan Signed-off-by: Gerd Hoffmann Signed-off-by: Jason Wang Signed-off-by: Mauro Matteo Cascella --- qemu.spec | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/qemu.spec b/qemu.spec index ddf8110..d7ae871 100644 --- a/qemu.spec +++ b/qemu.spec @@ -187,6 +187,13 @@ Patch0174: hw-usb-core-fix-buffer-overflow.patch Patch0175: slirp-drop-bogus-IPv6-messages.patch Patch0176: hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch Patch0177: hw-xhci-check-return-value-of-usb_packet_map.patch +Patch0178: hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch +Patch0179: hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch +Patch0180: sm501-Convert-printf-abort-to-qemu_log_mask.patch +Patch0181: sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch +Patch0182: sm501-Use-BIT-x-macro-to-shorten-constant.patch +Patch0183: sm501-Clean-up-local-variables-in-sm501_2d_operation.patch +Patch0184: sm501-Replace-hand-written-implementation-with-pixma.patch BuildRequires: flex BuildRequires: bison @@ -532,6 +539,15 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu May 21 2020 BALATON Zoltan +- hw/net/xgmac: Fix buffer overflow in xgmac_enet_send() +- hw/net/net_tx_pkt: fix assertion failure in net_tx_pkt_add_raw_fragment() +- sm501: Convert printf + abort to qemu_log_mask +- sm501: Shorten long variable names in sm501_2d_operation +- sm501: Use BIT(x) macro to shorten constant +- sm501: Clean up local variables in sm501_2d_operation +- sm501: Replace hand written implementation with pixman where possible + * Thu Sep 24 2020 Huawei Technologies Co., Ltd - enrich commit info for some patches - rename some patches for slirp -- Gitee From 6b851f02d80f94c2b97c32118f98840e8111da23 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Thu, 24 Sep 2020 16:09:40 +0800 Subject: [PATCH 9/9] spec: Update release version with !14 increase release verison by one Signed-off-by: Euler Robot --- qemu.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu.spec b/qemu.spec index d7ae871..71602de 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.1.0 -Release: 21 +Release: 22 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY -- Gitee