From: Peter Maydell Date: Tue, 3 Mar 2026 17:27:18 +0000 (+0000) Subject: hw/net/xilinx_ethlite: Check for oversized TX packets X-Git-Tag: v11.0.0-rc0~31^2~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6595a8d5d17ea1716ddafb34455ec2b29381e232;p=thirdparty%2Fqemu.git 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 Reviewed-by: Alistair Francis Reviewed-by: Edgar E. Iglesias 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é --- diff --git a/hw/net/trace-events b/hw/net/trace-events index 23efa91d055..001a20b0e2a 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -527,3 +527,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 ba3acd4c77c..7ea194475f1 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); }