34b321
From acb67d9c43f3921861eebbabb447a85644e99320 Mon Sep 17 00:00:00 2001
607880
From: Stefan Hajnoczi <stefanha@redhat.com>
607880
Date: Mon, 25 Jul 2016 12:55:36 +0200
34b321
Subject: [PATCH 2/2] virtio: error out if guest exceeds virtqueue size
607880
MIME-Version: 1.0
607880
Content-Type: text/plain; charset=UTF-8
607880
Content-Transfer-Encoding: 8bit
607880
607880
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
607880
Message-id: <1469451336-20117-2-git-send-email-stefanha@redhat.com>
607880
Patchwork-id: 71428
607880
O-Subject: [virt-devel] [RHEL-7.3 EMBARGOED qemu-kvm PATCH 1/1] virtio: error out if guest exceeds virtqueue size
34b321
Bugzilla: 1359729
607880
RH-Acked-by: Thomas Huth <thuth@redhat.com>
607880
RH-Acked-by: Marc-André Lureau <mlureau@redhat.com>
607880
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
607880
607880
A broken or malicious guest can submit more requests than the virtqueue
607880
size permits.
607880
607880
The guest can submit requests without bothering to wait for completion
607880
and is therefore not bound by virtqueue size.  This requires reusing
607880
vring descriptors in more than one request, which is incorrect but
607880
possible.  Processing a request allocates a VirtQueueElement and
607880
therefore causes unbounded memory allocation controlled by the guest.
607880
607880
Exit with an error if the guest provides more requests than the
607880
virtqueue size permits.  This bounds memory allocation and makes the
607880
buggy guest visible to the user.
607880
607880
This patch fixes CVE-2016-5403.
607880
607880
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
607880
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
607880
---
607880
 hw/virtio/virtio.c | 5 +++++
607880
 1 file changed, 5 insertions(+)
607880
607880
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
607880
index 132b5af..a861870 100644
607880
--- a/hw/virtio/virtio.c
607880
+++ b/hw/virtio/virtio.c
607880
@@ -452,6 +452,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
607880
 
607880
     max = vq->vring.num;
607880
 
607880
+    if (vq->inuse >= max) {
607880
+        error_report("Virtqueue size exceeded");
607880
+        exit(1);
607880
+    }
607880
+
607880
     i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
607880
     if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
607880
         vring_avail_event(vq, vring_avail_idx(vq));
607880
-- 
607880
1.8.3.1
607880