From 76d3c196e746dba9bf3d489b2b5c9248207e6439 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..62be98b --- /dev/null +++ b/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch @@ -0,0 +1,58 @@ +From 2d18434c1ca66d68f80954be6828a3770176dab4 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 b64734a489a21b5d8ccb13b5c5377d60a606089c 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..a763f93 --- /dev/null +++ b/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch @@ -0,0 +1,40 @@ +From 596e7e8908b742f727d02ec9ab747116573f67e0 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 4a016809fca9664dc49fc96c2c5ccb1ba8c360f0 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..14a530b --- /dev/null +++ b/sm501-Convert-printf-abort-to-qemu_log_mask.patch @@ -0,0 +1,159 @@ +From 428e3a78ddf1de3dfb914043d6a8668f73ef8bb3 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 6d626b4931478be0113af7d9aa83b963f5a72540 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..a2eefcb --- /dev/null +++ b/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch @@ -0,0 +1,134 @@ +From bc472e56b985db1de73a7ddab5ea8568d6e7f327 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 47f7c9cf05d1a0c63bd4a58ba0d6e03338dde105 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..697d0ee --- /dev/null +++ b/sm501-Use-BIT-x-macro-to-shorten-constant.patch @@ -0,0 +1,42 @@ +From 9f1e9012047639121eb275a4f8f5693d340e91f6 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 98cbcf0b43fa0aa2684e0aca2ac8d903b3fe17d7 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..66e54cd --- /dev/null +++ b/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch @@ -0,0 +1,95 @@ +From 6186d3de416825e3a737dd3da31da475f50d66d0 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 c88123893ba046b191b387dbe527319fce6ee4e1 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..42fa23a --- /dev/null +++ b/sm501-Replace-hand-written-implementation-with-pixma.patch @@ -0,0 +1,261 @@ +From bbbf2c2f4201eb84a5bcd07a92399fe166d682e9 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 7c811d7f1bca6a256256bad63a81b229689c75b7 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Wed, 23 Sep 2020 09:12:34 +0800 Subject: [PATCH 8/9] spec: Update patch and changelog with !13 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 3ad6f7e..525f4f1 100644 --- a/qemu.spec +++ b/qemu.spec @@ -294,6 +294,13 @@ Patch0281: hw-xhci-check-return-value-of-usb_packet_map.patch Patch0282: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch Patch0283: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch Patch0284: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch +Patch0285: hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch +Patch0286: hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch +Patch0287: sm501-Convert-printf-abort-to-qemu_log_mask.patch +Patch0288: sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch +Patch0289: sm501-Use-BIT-x-macro-to-shorten-constant.patch +Patch0290: sm501-Clean-up-local-variables-in-sm501_2d_operation.patch +Patch0291: sm501-Replace-hand-written-implementation-with-pixma.patch BuildRequires: flex BuildRequires: bison @@ -640,6 +647,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 + * Sat Sep 19 2020 Peng Liang - target/arm: Update the ID registers of Kunpeng-920 -- Gitee From 96a1313f649706724e1e1c2936f25fecf5a43b81 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Wed, 23 Sep 2020 09:12:34 +0800 Subject: [PATCH 9/9] spec: Update release version with !13 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 525f4f1..97aebe3 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.1.0 -Release: 31 +Release: 32 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY -- Gitee