From: "Michael S. Tsirkin" <[email protected]>
Within virtio-net, receive_filter() reads Ethernet header fields without
any length checks.
But virtio-net sets do_not_pad in NetClientState, so backends such as
socket forward frames at the size supplied by the peer without padding
to the Ethernet minimum. A short frame thus causes an out-of-bounds
read.
Add size checks in receive_filter() and drop the truncated frames.
Fixes: CVE-2026-63320
Fixes: 3831ab2094 ("qemu:virtio-net: Enable filtering based on MAC, promisc,
broadcast and allmulti (Alex Williamson)")
Cc: Jason Wang <[email protected]>
Cc: Alex Williamson <[email protected]>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3626
Reported-by: huntr bubble <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
Message-ID:
<ee5c77b96ab66b2dd518f146def8727216a5c495.1784895727.git....@redhat.com>
(cherry picked from commit 772488562053c1299fc3667a49b3ff1858f83979)
Signed-off-by: Michael Tokarev <[email protected]>
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 1f603179173..24256e866cd 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1750,10 +1750,21 @@ static int receive_filter(VirtIONet *n, const uint8_t
*buf, int size)
if (n->promisc)
return 1;
+ if (size < n->host_hdr_len + 14) {
+ /* Truncated ethernet packet */
+ return 0;
+ }
+
ptr += n->host_hdr_len;
if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
- int vid = lduw_be_p(ptr + 14) & 0xfff;
+ int vid;
+
+ /* Truncated vlan packet */
+ if (size < n->host_hdr_len + 16) {
+ return 0;
+ }
+ vid = lduw_be_p(ptr + 14) & 0xfff;
if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f))))
return 0;
}
--
2.47.3