- pci-host: designware: Limit value range of iATU viewport register - hmat acpi: Fix out of bounds access due to missing use of indirection - migration: Skip only empty block devices - aspeed/hace: Initialize g_autofree pointer - hw/net/vmxnet3: Fix guest-triggerable assert() - qxl: don't assert() if device isn't yet initialized - Avoid unaligned fetch in ladr_match() - linux-user: Fix waitid return of siginfo_t and rusage - hw/net/lan9118: Replace magic '2048' value by MIL_TXFIFO_SIZE definition - stdvga: fix screen blanking - virtio-net: drop too short packets early - ebpf: replace deprecated bpf_program__set_socket_filter - vhsot-user: only read reply of SET_LOG_BASE from vq 0 - cpu: add Tengyun S5000C cpu support - hw/virtio: Fix obtain the buffer id from the last descriptor - hw/core: ensure kernel_end never gets used undefined Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit 1f9e476e96edb07e34e0133a312f478ddab4b6ff)
92 lines
3.1 KiB
Diff
92 lines
3.1 KiB
Diff
From b808292dbbb5e49db4b54123010ed2832d0ac548 Mon Sep 17 00:00:00 2001
|
|
From: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
|
Date: Tue, 13 Aug 2024 00:30:30 -0700
|
|
Subject: [PATCH] virtio-net: drop too short packets early
|
|
|
|
Reproducer from https://gitlab.com/qemu-project/qemu/-/issues/1451
|
|
creates small packet (1 segment, len = 10 == n->guest_hdr_len),
|
|
then destroys queue.
|
|
|
|
"if (n->host_hdr_len != n->guest_hdr_len)" is triggered, if body creates
|
|
zero length/zero segment packet as there is nothing after guest header.
|
|
|
|
qemu_sendv_packet_async() tries to send it.
|
|
|
|
slirp discards it because it is smaller than Ethernet header,
|
|
but returns 0 because tx hooks are supposed to return total length of data.
|
|
|
|
0 is propagated upwards and is interpreted as "packet has been sent"
|
|
which is terrible because queue is being destroyed, nobody is waiting for TX
|
|
to complete and assert it triggered.
|
|
|
|
Fix is discard such empty packets instead of sending them.
|
|
|
|
Length 1 packets will go via different codepath:
|
|
|
|
virtqueue_push(q->tx_vq, elem, 0);
|
|
virtio_notify(vdev, q->tx_vq);
|
|
g_free(elem);
|
|
|
|
and aren't problematic.
|
|
|
|
Signed-off-by: Alexey Dobriyan <adobriyan@yandex-team.ru>
|
|
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
|
(cherry picked from commit 2c3e4e2de699cd4d9f6c71f30a22d8f125cd6164)
|
|
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
|
---
|
|
hw/net/virtio-net.c | 18 ++++++++++++------
|
|
1 file changed, 12 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
|
|
index f3fb9393b3..ab794ee789 100644
|
|
--- a/hw/net/virtio-net.c
|
|
+++ b/hw/net/virtio-net.c
|
|
@@ -2602,18 +2602,14 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
|
|
out_sg = elem->out_sg;
|
|
if (out_num < 1) {
|
|
virtio_error(vdev, "virtio-net header not in first element");
|
|
- virtqueue_detach_element(q->tx_vq, elem, 0);
|
|
- g_free(elem);
|
|
- return -EINVAL;
|
|
+ goto detach;
|
|
}
|
|
|
|
if (n->has_vnet_hdr) {
|
|
if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
|
|
n->guest_hdr_len) {
|
|
virtio_error(vdev, "virtio-net header incorrect");
|
|
- virtqueue_detach_element(q->tx_vq, elem, 0);
|
|
- g_free(elem);
|
|
- return -EINVAL;
|
|
+ goto detach;
|
|
}
|
|
if (n->needs_vnet_hdr_swap) {
|
|
virtio_net_hdr_swap(vdev, (void *) &vhdr);
|
|
@@ -2644,6 +2640,11 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
|
|
n->guest_hdr_len, -1);
|
|
out_num = sg_num;
|
|
out_sg = sg;
|
|
+
|
|
+ if (out_num < 1) {
|
|
+ virtio_error(vdev, "virtio-net nothing to send");
|
|
+ goto detach;
|
|
+ }
|
|
}
|
|
|
|
ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
|
|
@@ -2664,6 +2665,11 @@ drop:
|
|
}
|
|
}
|
|
return num_packets;
|
|
+
|
|
+detach:
|
|
+ virtqueue_detach_element(q->tx_vq, elem, 0);
|
|
+ g_free(elem);
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
|
|
--
|
|
2.41.0.windows.1
|
|
|