@samitouri / QOSamiQemu / commits / 59fc7b747d

hw/net/rtl8139: Fix handling of VLAN tags on incoming short packets

The rtl8139 receive code handles VLAN tags in incoming packets by copying the VLAN tag to a special field in the receive descriptor, and copying only the actual payload data to the receive buffer. This code tries to ensure that it pads out the payload to at least MIN_BUF_SIZE bytes. In commit 63b901bfd30 we removed the main "pad short frames" code from this device because we switched to requiring net backends to do the padding. However we didn't notice that this broke the VLAN tag handling, which relied on the old code making the buffer at least MIN_BUF_SIZE + VLAN_HLEN bytes so that it could copy MIN_BUF_SIZE bytes into the receive buffer even after removing the VLAN tag. The result is that the guest can make us read 4 bytes off the end of a buffer by feeding itself a suitable short packet in loopback mode. The old behaviour is actually not correct, because the IEEE802.1Q standard says that the minimum ethernet frame size remains 64 bytes including the 4 checksum bytes, and so when a tag is present the payload data only needs to be 56 bytes. (A bridge implementation can choose to pad tagged frames out to 68 bytes, but it doesn't have to, and so all devices have to correctly handle incoming tagged frames that are 64 bytes long.) The RTL8139 datasheet isn't very communicative on this topic, but there's nothing that suggests it adds extra padding on receive that didn't exist in the incoming packet. Drop the last remnants of the padding handling from this device; this avoids overcopying into the guest when we receive a short VLAN tagged packet. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3518 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Bin Meng <bin.meng@processmission.com> Message-ID: <20260731093618.2961031-2-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

Peter Maydell committed Jul 31, 2026 at 10:36 UTC 59fc7b747d56652e09708adff3afaca326e85a2a
1 file changed -5
hw/net/rtl8139.c
-5
@@ -778,7 +778,6 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
778 s->RxBufAddr += size;
779 }
780
781 -#define MIN_BUF_SIZE 60
781 static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high)
782 {
783 return low | ((uint64_t)high << 32);
@@ -1007,10 +1006,6 @@ static ssize_t rtl8139_receive(NetClientState *nc,
1006 lduw_be_p(&buf[ETH_ALEN * 2]) == ETH_P_VLAN) {
1007 dot1q_buf = &buf[ETH_ALEN * 2];
1008 size -= VLAN_HLEN;
1010 - /* if too small buffer, use the tailroom added duing expansion */
1011 - if (size < MIN_BUF_SIZE) {
1012 - size = MIN_BUF_SIZE;
1013 - }
1009
1010 rxdw1 &= ~CP_RX_VLAN_TAG_MASK;
1011 /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */