summaryrefslogtreecommitdiffstats
path: root/drivers/virtio/virtio_ring.c
diff options
context:
space:
mode:
authorMatthias Lange <matthias.lange@kernkonzept.com>2019-09-06 16:59:01 +0200
committerMichael S. Tsirkin <mst@redhat.com>2019-09-09 16:43:15 +0200
commitcf8f1696709ad5bb3138ed8c771c2eb98950cd8a (patch)
tree1bcd78442f26804d5b15643a44eedfdb9c984332 /drivers/virtio/virtio_ring.c
parentmm/balloon_compaction: suppress allocation warnings (diff)
downloadlinux-cf8f1696709ad5bb3138ed8c771c2eb98950cd8a.tar.xz
linux-cf8f1696709ad5bb3138ed8c771c2eb98950cd8a.zip
virtio_ring: fix unmap of indirect descriptors
The function virtqueue_add_split() DMA-maps the scatterlist buffers. In case a mapping error occurs the already mapped buffers must be unmapped. This happens by jumping to the 'unmap_release' label. In case of indirect descriptors the release is wrong and may leak kernel memory. Because the implementation assumes that the head descriptor is already mapped it starts iterating over the descriptor list starting from the head descriptor. However for indirect descriptors the head descriptor is never mapped in case of an error. The fix is to initialize the start index with zero in case of indirect descriptors and use the 'desc' pointer directly for iterating over the descriptor chain. Signed-off-by: Matthias Lange <matthias.lange@kernkonzept.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to '')
-rw-r--r--drivers/virtio/virtio_ring.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index c8be1c4f5b55..bdc08244a648 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -566,13 +566,17 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
unmap_release:
err_idx = i;
- i = head;
+
+ if (indirect)
+ i = 0;
+ else
+ i = head;
for (n = 0; n < total_sg; n++) {
if (i == err_idx)
break;
vring_unmap_one_split(vq, &desc[i]);
- i = virtio16_to_cpu(_vq->vdev, vq->split.vring.desc[i].next);
+ i = virtio16_to_cpu(_vq->vdev, desc[i].next);
}
if (indirect)