summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2026-03-03 17:27:18 +0000
committerMichael Tokarev <mjt@tls.msk.ru>2026-03-11 16:41:49 +0300
commit42215ee6244cc378ce56a9c1ee7d0889075cc1b2 (patch)
tree7c1e0d769a572612357ef24e004db4fc076786b0
parent071884b988f9932eaffca2d4e86b4f6794273783 (diff)
downloadqemu-42215ee6244cc378ce56a9c1ee7d0889075cc1b2.tar.gz
qemu-42215ee6244cc378ce56a9c1ee7d0889075cc1b2.zip
hw/net/xilinx_ethlite: Check for oversized TX packets
The xilinx_ethlite network device wasn't checking that the TX packet size set by the guest was within the size of its dual port RAM, with the effect that the guest could get it to read off the end of the RAM block. Check the length. There is no provision in this very simple device for reporting errors, so as with various RX errors we just report via tracepoint. This lack of length check has been present since the device was first introduced, though the code implementing the tx path has changed somewhat since then. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3317 Fixes: b43848a1005ce ("xilinx: Add ethlite emulation") Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Message-ID: <20260303172718.437015-1-peter.maydell@linaro.org> [PMD: renamed size -> tx_size to avoid shadow=compatible-local error] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> (cherry picked from commit 6595a8d5d17ea1716ddafb34455ec2b29381e232) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--hw/net/trace-events1
-rw-r--r--hw/net/xilinx_ethlite.c12
2 files changed, 10 insertions, 3 deletions
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 72b69c4a8b..698290fe79 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -517,3 +517,4 @@ xen_netdev_rx(int dev, int idx, int status, int flags) "vif%u idx %d status %d f
# xilinx_ethlite.c
ethlite_pkt_lost(uint32_t rx_ctrl) "rx_ctrl:0x%" PRIx32
ethlite_pkt_size_too_big(uint64_t size) "size:0x%" PRIx64
+ethlite_pkt_tx_size_too_big(uint64_t size) "size:0x%" PRIx64
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 42b19d07c7..665def8a34 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -162,9 +162,15 @@ static void port_tx_write(void *opaque, hwaddr addr, uint64_t value,
break;
case TX_CTRL:
if ((value & (CTRL_P | CTRL_S)) == CTRL_S) {
- qemu_send_packet(qemu_get_queue(s->nic),
- txbuf_ptr(s, port_index),
- s->port[port_index].reg.tx_len);
+ uint32_t tx_size = s->port[port_index].reg.tx_len;
+
+ if (tx_size >= BUFSZ_MAX) {
+ trace_ethlite_pkt_tx_size_too_big(tx_size);
+ } else {
+ qemu_send_packet(qemu_get_queue(s->nic),
+ txbuf_ptr(s, port_index),
+ tx_size);
+ }
if (s->port[port_index].reg.tx_ctrl & CTRL_I) {
eth_pulse_irq(s);
}