66 lines
2.3 KiB
Diff
66 lines
2.3 KiB
Diff
![]() |
From d9c626e4ede58130f64f24f4f9ca1140e4102a70 Mon Sep 17 00:00:00 2001
|
||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||
|
Date: Tue, 19 Jul 2016 13:07:13 +0100
|
||
|
Subject: [PATCH] virtio: error out if guest exceeds virtqueue size
|
||
|
|
||
|
A broken or malicious guest can submit more requests than the virtqueue
|
||
|
size permits, causing unbounded memory allocation in QEMU.
|
||
|
|
||
|
The guest can submit requests without bothering to wait for completion
|
||
|
and is therefore not bound by virtqueue size. This requires reusing
|
||
|
vring descriptors in more than one request, which is not allowed by the
|
||
|
VIRTIO 1.0 specification.
|
||
|
|
||
|
In "3.2.1 Supplying Buffers to The Device", the VIRTIO 1.0 specification
|
||
|
says:
|
||
|
|
||
|
1. The driver places the buffer into free descriptor(s) in the
|
||
|
descriptor table, chaining as necessary
|
||
|
|
||
|
and
|
||
|
|
||
|
Note that the above code does not take precautions against the
|
||
|
available ring buffer wrapping around: this is not possible since the
|
||
|
ring buffer is the same size as the descriptor table, so step (1) will
|
||
|
prevent such a condition.
|
||
|
|
||
|
This implies that placing more buffers into the virtqueue than the
|
||
|
descriptor table size is not allowed.
|
||
|
|
||
|
QEMU is missing the check to prevent this case. Processing a request
|
||
|
allocates a VirtQueueElement leading to unbounded memory allocation
|
||
|
controlled by the guest.
|
||
|
|
||
|
Exit with an error if the guest provides more requests than the
|
||
|
virtqueue size permits. This bounds memory allocation and makes the
|
||
|
buggy guest visible to the user.
|
||
|
|
||
|
This patch fixes CVE-2016-5403 and was reported by Zhenhao Hong from 360
|
||
|
Marvel Team, China.
|
||
|
|
||
|
Reported-by: Zhenhao Hong <hongzhenhao@360.cn>
|
||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||
|
(cherry picked from commit afd9096eb1882f23929f5b5c177898ed231bac66)
|
||
|
[BR: CVE-2016-5403 BSC#991080]
|
||
|
Signed-off-by: Bruce Rogers <brogers@suse.com>
|
||
|
---
|
||
|
hw/virtio/virtio.c | 5 +++++
|
||
|
1 file changed, 5 insertions(+)
|
||
|
|
||
|
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
|
||
|
index 30ede3d..e5ead0d 100644
|
||
|
--- a/hw/virtio/virtio.c
|
||
|
+++ b/hw/virtio/virtio.c
|
||
|
@@ -561,6 +561,11 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz)
|
||
|
|
||
|
max = vq->vring.num;
|
||
|
|
||
|
+ if (vq->inuse >= vq->vring.num) {
|
||
|
+ error_report("Virtqueue size exceeded");
|
||
|
+ exit(1);
|
||
|
+ }
|
||
|
+
|
||
|
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
|
||
|
if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
|
||
|
vring_set_avail_event(vq, vq->last_avail_idx);
|