From: Peter Maydell <[email protected]> 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 <[email protected]> Reviewed-by: Bin Meng <[email protected]> Message-ID: <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]> --- hw/net/rtl8139.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 424af73a18f..2b61c171f2a 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -778,7 +778,6 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) s->RxBufAddr += size; } -#define MIN_BUF_SIZE 60 static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) { return low | ((uint64_t)high << 32); @@ -1007,10 +1006,6 @@ static ssize_t rtl8139_receive(NetClientState *nc, lduw_be_p(&buf[ETH_ALEN * 2]) == ETH_P_VLAN) { dot1q_buf = &buf[ETH_ALEN * 2]; size -= VLAN_HLEN; - /* if too small buffer, use the tailroom added duing expansion */ - if (size < MIN_BUF_SIZE) { - size = MIN_BUF_SIZE; - } rxdw1 &= ~CP_RX_VLAN_TAG_MASK; /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */ -- 2.53.0
