!134 qemu: backport patches from openEuler-20.03-LTS

From: @zhendongchen
Reviewed-by: @yorifang
Signed-off-by: @yorifang
This commit is contained in:
openeuler-ci-bot 2020-10-10 17:14:11 +08:00 committed by Gitee
commit eabdfdd7c7
15 changed files with 967 additions and 6 deletions

View File

@ -0,0 +1,40 @@
From d65a00000e56ee2cec2f506b1408128d2df56ad9 Mon Sep 17 00:00:00 2001
From: Mauro Matteo Cascella <mcascell@redhat.com>
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 <alxndr@bu.edu>
Reported-by: Ziming Zhang <ezrakiez@gmail.com>
Reviewed-by: Dmitry Fleytman <dmitry.fleytman@gmail.com>
Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
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

View File

@ -0,0 +1,58 @@
From a80a85c7c358febb164ace0dfa75c468f43e0f02 Mon Sep 17 00:00:00 2001
From: Mauro Matteo Cascella <mcascell@redhat.com>
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 <ezrakiez@gmail.com>
Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
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

View File

@ -0,0 +1,38 @@
From d99d965c232c649686b4d8bc42dc11dcaf90dc0b Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Fri, 18 Sep 2020 10:55:22 +0800
Subject: [PATCH] hw/sd/sdhci: Fix DMA Transfer Block Size field
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The 'Transfer Block Size' field is 12-bit wide.
See section '2.2.2. Block Size Register (Offset 004h)' in datasheet.
Cc: qemu-stable@nongnu.org
Cc: Igor Mitsyanko <i.mitsyanko@gmail.com>
Buglink: https://bugs.launchpad.net/qemu/+bug/1892960
Fixes: d7dfca0807a ("hw/sdhci: introduce standard SD host controller")
Reported-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
hw/sd/sdhci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 7b80b1d93f..65a530aee4 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1127,7 +1127,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
break;
case SDHC_BLKSIZE:
if (!TRANSFERRING_DATA(s->prnsts)) {
- MASKED_WRITE(s->blksize, mask, value);
+ MASKED_WRITE(s->blksize, mask, extract32(value, 0, 12));
MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16);
}
--
2.23.0

View File

@ -0,0 +1,74 @@
From ff7545a6911bc7b9d818a541130f666a81077b44 Mon Sep 17 00:00:00 2001
From: Li Qiang <liq3ea@163.com>
Date: Fri, 18 Sep 2020 11:08:28 +0800
Subject: [PATCH] hw: xhci: check return value of 'usb_packet_map'
Currently we don't check the return value of 'usb_packet_map',
this will cause an UAF issue. This is LP#1891341.
Following is the reproducer provided in:
-->https://bugs.launchpad.net/qemu/+bug/1891341
cat << EOF | ./i386-softmmu/qemu-system-i386 -device nec-usb-xhci \
-trace usb\* -device usb-audio -device usb-storage,drive=mydrive \
-drive id=mydrive,file=null-co://,size=2M,format=raw,if=none \
-nodefaults -nographic -qtest stdio
outl 0xcf8 0x80001016
outl 0xcfc 0x3c009f0d
outl 0xcf8 0x80001004
outl 0xcfc 0xc77695e
writel 0x9f0d000000000040 0xffff3655
writeq 0x9f0d000000002000 0xff2f9e0000000000
write 0x1d 0x1 0x27
write 0x2d 0x1 0x2e
write 0x17232 0x1 0x03
write 0x17254 0x1 0x06
write 0x17278 0x1 0x34
write 0x3d 0x1 0x27
write 0x40 0x1 0x2e
write 0x41 0x1 0x72
write 0x42 0x1 0x01
write 0x4d 0x1 0x2e
write 0x4f 0x1 0x01
writeq 0x9f0d000000002000 0x5c051a0100000000
write 0x34001d 0x1 0x13
write 0x340026 0x1 0x30
write 0x340028 0x1 0x08
write 0x34002c 0x1 0xfe
write 0x34002d 0x1 0x08
write 0x340037 0x1 0x5e
write 0x34003a 0x1 0x05
write 0x34003d 0x1 0x05
write 0x34004d 0x1 0x13
writeq 0x9f0d000000002000 0xff00010100400009
EOF
This patch fixes this.
Buglink: https://bugs.launchpad.net/qemu/+bug/1891341
Reported-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Li Qiang <liq3ea@163.com>
Message-id: 20200812153139.15146-1-liq3ea@163.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/hcd-xhci.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index a21485fe8a..3b25abcacd 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1614,7 +1614,10 @@ static int xhci_setup_packet(XHCITransfer *xfer)
xhci_xfer_create_sgl(xfer, dir == USB_TOKEN_IN); /* Also sets int_req */
usb_packet_setup(&xfer->packet, dir, ep, xfer->streamid,
xfer->trbs[0].addr, false, xfer->int_req);
- usb_packet_map(&xfer->packet, &xfer->sgl);
+ if (usb_packet_map(&xfer->packet, &xfer->sgl)) {
+ qemu_sglist_destroy(&xfer->sgl);
+ return -1;
+ }
DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
xfer->packet.pid, ep->dev->addr, ep->nr);
return 0;
--
2.23.0

View File

@ -1,6 +1,6 @@
Name: qemu
Version: 4.1.0
Release: 18
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
@ -40,11 +40,11 @@ Patch0027: nbd-fix-uninitialized-variable-warning.patch
Patch0028: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch
Patch0029: block-fix-memleaks-in-bdrv_refresh_filename.patch
Patch0030: iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch
Patch0031: tcp_emu-Fix-oob-access.patch
Patch0031: slirp-tcp_emu-Fix-oob-access.patch
Patch0032: slirp-use-correct-size-while-emulating-IRC-commands.patch
Patch0033: slirp-use-correct-size-while-emulating-commands.patch
Patch0034: util-add-slirp_fmt-helpers.patch
Patch0035: tcp_emu-fix-unsafe-snprintf-usages.patch
Patch0034: slirp-util-add-slirp_fmt-helpers.patch
Patch0035: slirp-tcp_emu-fix-unsafe-snprintf-usages.patch
Patch0036: block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch
Patch0037: monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch
Patch0038: memory-Align-MemoryRegionSections-fields.patch
@ -165,7 +165,7 @@ Patch0152: arm-virt-Support-CPU-cold-plug.patch
Patch0153: ide-Fix-incorrect-handling-of-some-PRDTs-in-ide_dma_.patch
Patch0154: ati-vga-Fix-checks-in-ati_2d_blt-to-avoid-crash.patch
Patch0155: slirp-tftp-restrict-relative-path-access.patch
Patch0156: ip_reass-Fix-use-after-free.patch
Patch0156: slirp-ip_reass-Fix-use-after-free.patch
Patch0157: bt-use-size_t-type-for-length-parameters-instead-of-.patch
Patch0158: log-Add-some-logs-on-VM-runtime-path.patch
Patch0159: Revert-vtimer-compat-cross-version-migration-from-v4.patch
@ -183,7 +183,17 @@ Patch0170: megasas-avoid-NULL-pointer-dereference.patch
Patch0171: megasas-use-unsigned-type-for-positive-numeric-field.patch
Patch0172: hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch
Patch0173: hw-arm-acpi-enable-SHPC-native-hot-plug.patch
PATCH0174: hw-usb-core-fix-buffer-overflow.patch
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
@ -529,6 +539,26 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Thu May 21 2020 BALATON Zoltan <balaton@eik.bme.hu>
- 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 <alex.chen@huawei.com>
- enrich commit info for some patches
- rename some patches for slirp
* Fri Sep 18 2020 Huawei Technologies Co., Ltd <lijiajie11@huawei.com>
- hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch
- hw-xhci-check-return-value-of-usb_packet_map.patch
* Fri Sep 11 2020 Huawei Technologies Co., Ltd <lijiajie11@huawei.com>
- slirp/src/ip6_input.c: fix out-of-bounds read information vulnerablity
* Thu Aug 27 2020 Huawei Technologies Co., Ltd <lijiajie11@huawei.com>
- hw/usb/core.c: fix buffer overflow in do_token_setup function

View File

@ -0,0 +1,30 @@
From e8b555c08061ad78920611a5e98ee14fcd967692 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.com>
Date: Fri, 11 Sep 2020 10:55:49 +0800
Subject: [PATCH] Drop bogus IPv6 messages
Drop IPv6 message shorter than what's mentioned in the playload
length header (+the size of IPv6 header). They're invalid and could
lead to data leakage in icmp6_send_echoreply().
diff --git a/slirp/src/ip6_input.c b/slirp/src/ip6_input.c
index d9d2b7e..c2dce52 100644
--- a/slirp/src/ip6_input.c
+++ b/slirp/src/ip6_input.c
@@ -49,6 +49,13 @@ void ip6_input(struct mbuf *m)
goto bad;
}
+ // Check if the message size is big enough to hold what's
+ // set in the payload length header. If not this is an invalid
+ // packet
+ if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) {
+ goto bad;
+ }
+
/* check ip_ttl for a correct ICMP reply */
if (ip6->ip_hl == 0) {
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
--
1.8.3.1

View File

@ -0,0 +1,95 @@
From b08fddd2931fa2e3d12d2c26074835956b114d56 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: 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 <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: ae59f8138afe7f6a5a4a82539d0f61496a906b06.1590089984.git.balaton@eik.bme.hu
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
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

View File

@ -0,0 +1,159 @@
From c52852158aa010d534ee6d1c7a44f72ef87857a3 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: 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 <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: 305af87f59d81e92f2aaff09eb8a3603b8baa322.1590089984.git.balaton@eik.bme.hu
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
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

View File

@ -0,0 +1,261 @@
From 2f57a288065de4fffcf182deacd3c75aec90a9ef 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>
---
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

View File

@ -0,0 +1,134 @@
From 54c647d867891b58084d6b36ac2db794c19bed22 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: Shorten long variable names in sm501_2d_operation
This increases readability and cleans up some confusing naming.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Message-id: b9b67b94c46e945252a73c77dfd117132c63c4fb.1590089984.git.balaton@eik.bme.hu
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
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

View File

@ -0,0 +1,42 @@
From a2622f39d8050c86100b40e47b2586d0ebf3b541 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: 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 <balaton@eik.bme.hu>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: 124bf5de8d7cf503b32b377d0445029a76bfbd49.1590089984.git.balaton@eik.bme.hu
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
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