Message ID | 20190719185158.20316-3-alxndr@bu.edu |
---|---|
State | New |
Headers | show |
Series | Avoid sending zero-size packets | expand |
On Fri, Jul 19, 2019 at 06:52:30PM +0000, Oleinik, Alexander wrote: > virtio_net_flush_tx does not check that the packet size is nonzero, > which causes q->aysnc_tx.elem to be set. Then, when the device is reset, there > is an assertion failure since q->aysnc_tx.elem must be flushed/cleared. > Zero-sized packets are unsupported - check packet size, prior to > sending. > > Found while fuzzing virtio-net. The relevant stack-trace: > #8 in __assert_fail (libc.so.6+0x30101) > #9 in virtio_net_reset virtio-net.c:520:13 > #10 in virtio_reset virtio.c:1214:9 > #11 in virtio_pci_reset virtio-pci.c:1810:5 > #12 in qdev_reset_one qdev.c:259:5 > #13 in qdev_walk_children qdev.c:575:15 > #14 in qbus_walk_children bus.c:52:15 > #15 in qdev_walk_children qdev.c:567:15 > #16 in qbus_walk_children bus.c:52:15 > #17 in qemu_devices_reset reset.c:69:9 > #18 in pc_machine_reset pc.c:2628:5 > #19 in qemu_system_reset vl.c:1621:9 > #20 in LLVMFuzzerTestOneInput fuzz.c:184:4 > > Signed-off-by: Alexander Oleinik <alxndr@bu.edu> > --- > hw/net/virtio-net.c | 15 +++++++++------ > 1 file changed, 9 insertions(+), 6 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b9e1cd71cf..743f1c827c 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2074,12 +2074,15 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) out_sg = sg; } - ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index), - out_sg, out_num, virtio_net_tx_complete); - if (ret == 0) { - virtio_queue_set_notification(q->tx_vq, 0); - q->async_tx.elem = elem; - return -EBUSY; + /* Do not try to send 0-sized packets */ + if (iov_size(out_sg, out_num)) { + ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, + queue_index), out_sg, out_num, virtio_net_tx_complete); + if (ret == 0) { + virtio_queue_set_notification(q->tx_vq, 0); + q->async_tx.elem = elem; + return -EBUSY; + } } drop:
virtio_net_flush_tx does not check that the packet size is nonzero, which causes q->aysnc_tx.elem to be set. Then, when the device is reset, there is an assertion failure since q->aysnc_tx.elem must be flushed/cleared. Zero-sized packets are unsupported - check packet size, prior to sending. Found while fuzzing virtio-net. The relevant stack-trace: #8 in __assert_fail (libc.so.6+0x30101) #9 in virtio_net_reset virtio-net.c:520:13 #10 in virtio_reset virtio.c:1214:9 #11 in virtio_pci_reset virtio-pci.c:1810:5 #12 in qdev_reset_one qdev.c:259:5 #13 in qdev_walk_children qdev.c:575:15 #14 in qbus_walk_children bus.c:52:15 #15 in qdev_walk_children qdev.c:567:15 #16 in qbus_walk_children bus.c:52:15 #17 in qemu_devices_reset reset.c:69:9 #18 in pc_machine_reset pc.c:2628:5 #19 in qemu_system_reset vl.c:1621:9 #20 in LLVMFuzzerTestOneInput fuzz.c:184:4 Signed-off-by: Alexander Oleinik <alxndr@bu.edu> --- hw/net/virtio-net.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)