Commit aaf0b445 authored by Sasha Levin's avatar Sasha Levin Committed by Will Deacon
Browse files

kvm tools: Prevent PFN wraparound



queue->pfn may be used to point at addresses larger
than 32 bit.
Prevent a wraparound when shifting it left.

Acked-and-tested-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarSasha Levin <levinsasha928@gmail.com>
Signed-off-by: default avatarPekka Enberg <penberg@kernel.org>
parent 874467f8
......@@ -36,6 +36,16 @@ static inline bool virt_queue__available(struct virt_queue *vq)
return vq->vring.avail->idx != vq->last_avail_idx;
}
/*
* Warning: on 32-bit hosts, shifting pfn left may cause a truncation of pfn values
* higher than 4GB - thus, pointing to the wrong area in guest virtual memory space
* and breaking the virt queue which owns this pfn.
*/
static inline void *guest_pfn_to_host(struct kvm *kvm, u32 pfn)
{
return guest_flat_to_host(kvm, (unsigned long)pfn << 12);
}
struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len);
u16 virt_queue__get_iov(struct virt_queue *queue, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm);
......
......@@ -197,7 +197,7 @@ static bool virtio_blk_pci_io_out(struct kvm *self, u16 port, void *data, int si
queue = &bdev->vqs[bdev->queue_selector];
queue->pfn = ioport__read32(data);
p = guest_flat_to_host(self, queue->pfn << 12);
p = guest_pfn_to_host(self, queue->pfn);
vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, 4096);
......
......@@ -199,7 +199,7 @@ static bool virtio_console_pci_io_out(struct kvm *self, u16 port, void *data, in
queue = &cdev.vqs[cdev.queue_selector];
queue->pfn = ioport__read32(data);
p = guest_flat_to_host(self, queue->pfn << 12);
p = guest_pfn_to_host(self, queue->pfn);
vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, 4096);
......
......@@ -245,7 +245,7 @@ static bool virtio_net_pci_io_out(struct kvm *self, u16 port, void *data, int si
queue = &net_device.vqs[net_device.queue_selector];
queue->pfn = ioport__read32(data);
p = guest_flat_to_host(self, queue->pfn << 12);
p = guest_pfn_to_host(self, queue->pfn);
vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, 4096);
......
......@@ -129,7 +129,7 @@ static bool virtio_rng_pci_io_out(struct kvm *kvm, u16 port, void *data, int siz
queue = &rdev.vqs[rdev.queue_selector];
queue->pfn = ioport__read32(data);
p = guest_flat_to_host(kvm, queue->pfn << 12);
p = guest_pfn_to_host(kvm, queue->pfn);
vring_init(&queue->vring, VIRTIO_RNG_QUEUE_SIZE, p, 4096);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment