* [Qemu-devel] [PATCHv2] virtio-net: correct packet length checks
@ 2010-06-24 15:29 Michael S. Tsirkin
0 siblings, 0 replies; only message in thread
From: Michael S. Tsirkin @ 2010-06-24 15:29 UTC (permalink / raw)
To: qemu-devel; +Cc: Amit Shah, alex.williamson, Juan Quintela
We were requesting too much when checking buffer
length: size already includes host header length.
Further, we should not exit if we get a packet that
is too long, since this might not be under control
of the guest. Just drop the packet.
Red Hat bz 591494
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
This supercedes the patch virtio-net: correct header length checks
Changes from v1:
address review comments
hw/virtio-net.c | 41 ++++++++++++++++++++++++++++-------------
1 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 06ba481..e28d2bd 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -527,17 +527,18 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
{
VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL;
- size_t hdr_len, offset, i;
+ size_t guest_hdr_len, offset, i, host_hdr_len;
if (!virtio_net_can_receive(&n->nic->nc))
return -1;
/* hdr_len refers to the header we supply to the guest */
- hdr_len = n->mergeable_rx_bufs ?
+ guest_hdr_len = n->mergeable_rx_bufs ?
sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
- if (!virtio_net_has_buffers(n, size + hdr_len))
+ host_hdr_len = n->has_vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
+ if (!virtio_net_has_buffers(n, size + guest_hdr_len - host_hdr_len))
return 0;
if (!receive_filter(n, buf, size))
@@ -552,13 +553,14 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
total = 0;
- if ((i != 0 && !n->mergeable_rx_bufs) ||
- virtqueue_pop(n->rx_vq, &elem) == 0) {
+ if (virtqueue_pop(n->rx_vq, &elem) == 0) {
if (i == 0)
return -1;
- fprintf(stderr, "virtio-net truncating packet: "
- "offset %zd, size %zd, hdr_len %zd\n",
- offset, size, hdr_len);
+ fprintf(stderr, "virtio-net unexpected empty queue: "
+ "i %d mergeable %d offset %zd, size %zd, "
+ "guest hdr len %zd, host hdr len %zd guest features 0x%x\n",
+ i, n->mergeable_rx_bufs, offset, size,
+ guest_hdr_len, host_hdr_len, n->vdev.guest_features);
exit(1);
}
@@ -567,7 +569,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
exit(1);
}
- if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != hdr_len) {
+ if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != guest_hdr_len) {
fprintf(stderr, "virtio-net header not in first element\n");
exit(1);
}
@@ -579,19 +581,32 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
offset += receive_header(n, sg, elem.in_num,
- buf + offset, size - offset, hdr_len);
- total += hdr_len;
+ buf + offset, size - offset, guest_hdr_len);
+ total += guest_hdr_len;
}
/* copy in packet. ugh */
len = iov_from_buf(sg, elem.in_num,
buf + offset, size - offset);
total += len;
+ offset += len;
+ /* If buffers can't be merged, at this point we
+ * must have consumed the complete packet.
+ * Otherwise, drop it. */
+ if (!n->mergeable_rx_bufs && offset < size) {
+#if 0
+ fprintf(stderr, "virtio-net truncated non-mergeable packet: "
+
+ "i %d mergeable %d offset %zd, size %zd, "
+ "guest hdr len %zd, host hdr len %zd\n",
+ i, n->mergeable_rx_bufs,
+ offset, size, guest_hdr_len, host_hdr_len);
+#endif
+ return size;
+ }
/* signal other side */
virtqueue_fill(n->rx_vq, &elem, total, i++);
-
- offset += len;
}
if (mhdr)
--
1.7.1.12.g42b7f
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2010-06-24 15:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-24 15:29 [Qemu-devel] [PATCHv2] virtio-net: correct packet length checks Michael S. Tsirkin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.