aboutsummaryrefslogtreecommitdiff
path: root/hw/net
diff options
context:
space:
mode:
authorXuan Zhuo <xuanzhuo@linux.alibaba.com>2022-11-10 17:57:39 +0800
committerMichael S. Tsirkin <mst@redhat.com>2022-11-10 10:18:55 -0500
commitf47af0af0db5933664c621b8af8067ebbcbe66cd (patch)
tree48ae6c6db7708f472eb4f0c57c78e6c838e0ee09 /hw/net
parent28cf39609603e4b5b2de8b74d4caa4d840425eff (diff)
downloadqemu-f47af0af0db5933664c621b8af8067ebbcbe66cd.zip
qemu-f47af0af0db5933664c621b8af8067ebbcbe66cd.tar.gz
qemu-f47af0af0db5933664c621b8af8067ebbcbe66cd.tar.bz2
virtio-net: fix for heap-buffer-overflow
Run shell script: cat << EOF | valgrind qemu-system-i386 -display none -machine accel=qtest, -m \ 512M -M q35 -nodefaults -device virtio-net,netdev=net0 -netdev \ user,id=net0 -qtest stdio outl 0xcf8 0x80000810 outl 0xcfc 0xc000 outl 0xcf8 0x80000804 outl 0xcfc 0x01 outl 0xc00d 0x0200 outl 0xcf8 0x80000890 outb 0xcfc 0x4 outl 0xcf8 0x80000889 outl 0xcfc 0x1c000000 outl 0xcf8 0x80000893 outw 0xcfc 0x100 EOF Got: ==68666== Invalid read of size 8 ==68666== at 0x688536: virtio_net_queue_enable (virtio-net.c:575) ==68666== by 0x6E31AE: memory_region_write_accessor (memory.c:492) ==68666== by 0x6E098D: access_with_adjusted_size (memory.c:554) ==68666== by 0x6E4DB3: memory_region_dispatch_write (memory.c:1521) ==68666== by 0x6E31AE: memory_region_write_accessor (memory.c:492) ==68666== by 0x6E098D: access_with_adjusted_size (memory.c:554) ==68666== by 0x6E4DB3: memory_region_dispatch_write (memory.c:1521) ==68666== by 0x6EBCD3: flatview_write_continue (physmem.c:2820) ==68666== by 0x6EBFBF: flatview_write (physmem.c:2862) ==68666== by 0x6EF5E7: address_space_write (physmem.c:2958) ==68666== by 0x6DFDEC: cpu_outw (ioport.c:70) ==68666== by 0x6F6DF0: qtest_process_command (qtest.c:480) ==68666== Address 0x29087fe8 is 24 bytes after a block of size 416 in arena "client" That is reported by Alexander Bulekov. https://gitlab.com/qemu-project/qemu/-/issues/1309 Here, the queue_index is the index of the cvq, but in some cases cvq does not have the corresponding NetClientState, so overflow appears. I add a check here, ignore illegal queue_index and cvq queue_index. Note the queue_index is below the VIRTIO_QUEUE_MAX but greater or equal than cvq index could hit this. Other devices are similar. Fixes: 7f863302 ("virtio-net: support queue_enable") Fixes: https://gitlab.com/qemu-project/qemu/-/issues/1309 Reported-by: Alexander Bulekov <alxndr@bu.edu> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Message-Id: <20221110095739.130393-1-xuanzhuo@linux.alibaba.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/net')
-rw-r--r--hw/net/virtio-net.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 8b32339..aba1275 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -549,7 +549,14 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
static void virtio_net_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
{
VirtIONet *n = VIRTIO_NET(vdev);
- NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+ NetClientState *nc;
+
+ /* validate queue_index and skip for cvq */
+ if (queue_index >= n->max_queue_pairs * 2) {
+ return;
+ }
+
+ nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
if (!nc->peer) {
return;
@@ -566,9 +573,16 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
{
VirtIONet *n = VIRTIO_NET(vdev);
- NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+ NetClientState *nc;
int r;
+ /* validate queue_index and skip for cvq */
+ if (queue_index >= n->max_queue_pairs * 2) {
+ return;
+ }
+
+ nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+
if (!nc->peer || !vdev->vhost_started) {
return;
}